相机采集:摄像头、麦克风采集数据样本(YUV/PCM),相机功能设置
画面预览:将图像渲染到画布
编辑模块:添加美颜、滤镜、动态贴纸等
录制:视频多段录制、回删等 素材模块
为了方便您快速集成,我们将特效相机逻辑封装在进阶使用类(PipeMediator) 中,您只需控制采集时机即可.
接口文件 | 功能 |
---|---|
PipeMediator | 进阶使用类 |
AudioConvert | 音频转换 |
PreviewManager | 画面预览 |
RecordManager | 视频录制 |
BeautyManager | 美颜特效 |
RenderPipe | 核心渲染管道 |
示例
// PipeMediator.java
/**
* @param buffer NV21数据
* @param bufferWidth NV21数据宽度
* @param bufferHeight NV21数据高度
* @param stride 每行数据长度
* @return
*/
public Image onFrameAvailable(ByteBuffer buffer, int bufferWidth, int bufferHeight, int stride){
if (!isReady) return null;
synchronized (PipeMediator.class) {
//1. 通过ImageConvert 将Android默认的OES纹理转换为可处理的Texture2D纹理
Image in = mImageConvert.onFrameAvailable(buffer,bufferWidth,bufferHeight,stride);
//2. 通过BeautyManager进行美颜处理
Image out = mBeautyManager.processFrame(in);
//3. 将处理后的Image显示到View上
if (mCurrentPreviewRect == null) {
mPreviewManager.updateImage(out);
} else {
mPreviewManager.updateImage(out, mCurrentPreviewRect);
}
//4. 需要录制的情况下 将处理后的Image对象送入RecordManager进行文件输出
if (mRecordManager != null) {
long recordPos = System.currentTimeMillis();
mRecordManager.sendImage(out, recordPos);
}
in.release();
out.release();
return out;
}
}
// PipeMediator.java
/**
* @param context Context 对象
* @param parent 渲染View父布局
* @param aspect 默认渲染尺寸比例
* @return Init结果 不为0时 说明参数存在错误
*/
public Pair<Boolean,Integer> requestInit(Context context, ViewGroup parent, SizeF aspect);
/**
* @param renderWidth 渲染画面宽度 默认值为720
*/
public void setRenderWidth(int renderWidth);
/**
* @param aspect 更新渲染画面比例
*/
public void updateAspect(SizeF aspect);
/**
* @param rectF 实际渲染区域 默认计算方式为fitin
*/
public void changedRect(@Nullable RectF rectF);
/**
* 开始录制视频
*
* @param outputPath 视频输出绝对路径
* @param width 视频输出宽度
* @param height 视频输出高度
* @param watermark 水印图片
* @param watermarkPos 水印位置 // 0 : tl, 1 : tr, 2 : bl, 3 : br
*/
public void startRecord(String outputPath, int width, int height, @Nullable Bitmap watermark, int watermarkPos);
/**
* @return 获取美颜属性管理类
*/
public BeautyManager getBeautyManager()
摄像头、麦克风采集数据样本(SurfaceTexture/PCM)。包括摄像头切换、闪光灯、画面对焦、分辨率及码率设置等
接口文件 | 功能 |
---|---|
TuCameraImpl | 相机采集功能 |
TuSurfaceTextureHolder | 相机数据回调 |
示例
TuSurfaceTextureHolder mCameraHolder = new TuSurfaceTextureHolder() {
@Override
public SurfaceTexture requestSurfaceTexture() {
// 获取相机绘制纹理
mSurfaceTexture = mPipeMediator.getSurfaceTexture();
return mSurfaceTexture;
}
@Override
public void setInputRotation(ImageOrientation previewOrientation) {
// 获取相机方向
mPreviewOrientation = previewOrientation;
mPipeMediator.setInputRotation(previewOrientation.getDegree(),previewOrientation.isMirrored());
}
@Override
public void setInputSize(TuSdkSize previewOptimizeSize) {
// 获取相机尺寸
mInputSize = previewOptimizeSize;
mRecordView.setDisplaySize(mInputSize.width,mInputSize.height);
mPipeMediator.setInputSize(mInputSize.width,mInputSize.height);
}
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
if (!mPipeMediator.isReady()){
//第一帧回调的时候 初始化PipeMediator对象
TuSdkSize size = ViewSize.create(mCameraView);
mCurrentRatio = TuCameraAspectRatio.of(size.width,size.height);
mPipeMediator.requestInit(getBaseContext(),mCameraView,new SizeF(mCurrentRatio.getX(),mCurrentRatio.getY()));
mRecordView.initFilterPipe(mPipeMediator.getBeautyManager());
mCurrentRenderSize = TuSdkSize.create((int) PROCESS_WIDTH, (int) (PROCESS_WIDTH / mCurrentRatio.getX() * mCurrentRatio.getY()));
}
//通知PipeMediator从相机绘制纹理中获取当前画面
Image image = mPipeMediator.onFrameAvailable();
if (!isRecording){
//如果录制未开启 资源的释放需要在这里进行
image.release();
}
}
};
mCamera = new TuCameraImpl();
// 设置相机纹理回调
mCamera.setSurfaceHolder(mCameraHolder);
// 设置是否相机是否默认使用最大尺寸采集
mCamera.setFullFrame(false);
// 相机预初始化
if (!mCamera.prepare()) return;
// 设置预览尺寸
mCamera.cameraSize().setPreviewSize(PREVIEW_SIZE);
// 设置相机默认采集方向
mCamera.cameraBuilder().setDefaultFacing(CameraConfigs.CameraFacing.Front);
// 设置相机预览方向 mCamera.cameraOrient().setDisplayRotation(getWindowManager().getDefaultDisplay().getRotation());
// 设置相机纹理输出方向
mCamera.cameraOrient().setOutputImageOrientation(InterfaceOrientation.Portrait);
// 设置相机状态回调
mCamera.setCameraListener(new TuCamera.TuCameraListener() {
@Override
public void onStatusChanged(CameraConfigs.CameraState status, TuCamera camera) {
if (status == START){
mRecordView.setExposure();
}
}
});
调整相机参数
//TuCamera.java
/** 相机接口 */
public interface TuCamera {
/** 相机相机参数处理接口 */
TuCameraParams cameraParams();
/** 相机方向处理接口 */
TuCameraOrient cameraOrient();
/** 相机聚焦接口 */
TuCameraFocus cameraFocus();
/** 相机长宽接口 */
TuCameraSize cameraSize();
/** 相机拍摄接口 */
TuCameraShot cameraShot();
/** 准备初始化相机 [是否初始化成功] */
boolean prepare();
/** 切换前后摄像头 [是否启动摄像头成功] */
boolean rotateCamera();
/** 相机前后位置 */
CameraFacing getFacing();
/** 开始预览 [是否启动摄像头成功] */
boolean startPreview();
/** 开始预览 [是否启动摄像头成功] */
boolean startPreview(CameraFacing facing);
/** Pause camera preview [是否成功暂定预览] */
boolean pausePreview();
/** Resume camera preview [是否成功恢复预览] */
boolean resumePreview();
/** 停止预览 */
void stopPreview();
/** 拍摄照片 [是否开始拍摄] */
boolean shotPhoto();
/** 释放资源 */
void release();
}
/** 相机参数处理接口 */
public interface TuCameraParams {
/** 配置相机参数 @param builder 相机创建接口 */
void configure(TuCameraBuilder builder);
/** 相机状态改变 */
void changeStatus(CameraState status);
/** 当前镜头是否有闪光灯 */
boolean canSupportFlash();
/** 闪关灯模式 @see # {@link org.lasque.tusdkpulse.core.utils.hardware.CameraConfigs.CameraFlash} */
CameraFlash getFlashMode();
/** 设置闪光灯模式 **/
void setFlashMode(CameraFlash flashMode);
/** 是否需要统一配置参数 (默认true, 取消三星默认降噪,锐化) */
void setUnifiedParameters(boolean unifiedParameters);
/** 设置抗条带 */
void setAntibandingMode(CameraAntibanding antiBandingMode);
/** 设置白平衡 */
void setWhiteBalance(CameraWhiteBalance whiteBalance);
/** 设置曝光补偿级数 **/
void setExposureCompensation(int ev);
/** 处理相机焦距变化 [是否放大焦距]*/
void setZoom(int scale, boolean isZoomIn);
/**
* 获取当前设备支持的最小曝光级数
*
* @return 最小曝光级数
*/
public int getMinExposureCompensation();
/**
* 获取当前设备支持的最大曝光级数
*
* @return 最大曝光级数
*/
public int getMaxExposureCompensation();
/**
* 获取当前曝光级数
*
* @return 当前曝光级数
*/
public int getCurrentExposureCompensation();
/**
* 获取当前设别曝光补偿Step
*
* @return 当前曝光补偿Step
*/
public float getExposureCompensationStep();
}
将采集的数据样本转换成 Image。
接口文件 | 功能 |
---|---|
ImageConvert | 样本转换 |
Image | 图像结构 |
// ImageConvert.java
// 通知纹理更新
public Image onFrameAvailable();
// 获取纹理
public SurfaceTexture getSurfaceTexture();
// 获取实际渲染尺寸
public TuSdkSize getRenderSize();
像素格式、采样分辨率
// ImageConvert.java
// 设置渲染比例
public boolean setAspect(double w,double h);
//更新比例
public void updateAspect(double w,double h);
// 设置输入尺寸与方向
public void setInputSize(int width,int height,ImageOrientation cameraOrientation);
// 设置渲染宽度
public void setRenderWidth(int renderWidth);
将采集的数据样本添加变速、变调、混音等。
接口文件 | 功能 |
---|---|
AudioConvert | 音频转换 |
AudioConvert.AudioItem | 音频数据 |
// AudioConvert.java
public static class AudioItem {
// PCM数据
public byte[] buffer;
// 数据长度
public int length;
// 时间戳
public long time;
public AudioItem(byte[] buffer, int length, long time);
}
// 送入转换数据
public int sendAudioData(AudioItem item);
// 接收数据
public AudioItem receiveAudioData() throws InterruptedException;
// AudioConvert.java
/**
* @param channels 声道数
* @param sampleRate 音频采样率
* @return 初始化状态
*/
public boolean requestInit(int channels, int sampleRate);
/**
* @param path 混音文件路径
* @param startPos 混音文件开始播放位置
*/
public void initAudioMixer(String path, Long startPos);
/**
* 重置混音器
*/
public void resetAudioMixer();
/**
* 开启音频处理
*/
public void startAudioConvert();
/**
* 结束音频处理
*/
public void stopAudioConvert();
/**
* 开始混音文件播放
*/
public void startAudioPlayer();
/**
* 结束混音文件播放
*/
public void stopAudioPlayer();
将Image渲染到画布
接口文件 | 功能 |
---|---|
PreviewManager | 画面预览 |
Image | 图像 |
// PreviewManager.java
/**
* @param context 上下文对象
* @param parent 父控件
* @return 初始化状态
*/
public Pair<Boolean,Integer> requestInit(Context context, ViewGroup parent);
/**
* 更新预览画面
* @param image 纹理资源
*/
public void updateImage(Image image);
/**
* 更新预览画面
* @param image 纹理资源
* @param rectF 渲染区域
*/
public void updateImage(Image image, RectF rectF);
画面比例、背景颜色、拍照/截图
// PreviewManager.java
/**
* 设置背景颜色
* @param color 画布背景颜色
*/
public void setBackgroundColor(int color);
在预览、视频录制的过程中,您可以给画面设置各种特效。
接口文件 | 功能 |
---|---|
Beauty | 美颜特效接口 |
BeautyManager | 美颜特效实现 |
Image | 图像 |
// BeautyManager.java
/**
* @param renderPipe 渲染队列
* @return 初始化状态
*/
public boolean requestInit(RenderPipe renderPipe);
/**
* 图像处理
* @param in 输入纹理
* @return 输出纹理
*/
public Image processFrame(final Image in);
// Beauty.java
public interface Beauty {
/**
* 美肤模式
*/
public static enum BeautySkinMode {
None(""),
/**
* 精准美肤
*/
SkinNatural,
/**
* 极致美肤
*/
SkinMoist,
/**
* 自然美肤
*/
Beauty;
}
/**
* 美妆-口红-口红样式
*/
public enum BeautyLipstickStyle {
/**
* 雾面
*/
Matte(0),
/**
* 水润
*/
Moisturizing(2),
/**
* 滋润
*/
Moisturize(1);
public static BeautyLipstickStyle getStyleFromValue;
}
/**
* @param beautyStyle 美肤模式
*/
void setBeautyStyle(BeautySkinMode beautyStyle);
/**
* @param level 磨皮级别
*/
void setSmoothLevel(float level);
/**
* @param level 美白级别
*/
void setWhiteningLevel(float level);
/**
* 仅限 精准/极致 美肤模式使用
* @param level 红润级别
*/
void setRuddyLevel(float level);
/**
* 仅限 自然美肤模式使用
* @param level 锐化级别
*/
void setSharpenLevel(float level);
/**
* @return 当前是否开启了微整形
*/
boolean hasPlastic();
/**
* @param level 设置大眼级别 [0-1]
*/
void setEyeEnlargeLevel(float level);
/**
* @param level 设置瘦脸级别 [0-1]
*/
void setCheekThinLevel(float level);
/**
* @param level 设置窄脸级别 [0-1]
*/
void setCheekNarrowLevel(float level);
/**
* @param level 设置小脸级别 [0-1]
*/
void setFaceSmallLevel(float level);
/**
* @param level 设置瘦鼻级别 [0 - 1]
*/
void setNoseWidthLevel(float level);
/**
* @param level 设置长鼻级别 [0 - 1]
*/
void setNoseHeightLevel(float level);
/**
* @param level 设置嘴型级别 [-1 - 1]
*/
void setMouthWidthLevel(float level);
/**
* @param level 设置唇厚级别 [-1 - 1]
*/
void setLipsThicknessLevel(float level);
/**
* @param level 设置缩人中界别 [-1 - 1]
*/
void setPhilterumThicknessLevel(float level);
/**
* @param level 设置细眉级别 [-1 - 1]
*/
void setBrowThicknessLevel(float level);
/**
* @param level 设置眉高级别 [-1 - 1]
*/
void setBrowHeightLevel(float level);
/**
* @param level 设置下巴(拉伸或收缩)级别 [-1 - 1]
*/
void setChinThicknessLevel(float level);
/**
* @param level 设置下颌骨级别 [0 - 1]
*/
void setCheekLowBoneNarrowLevel(float level);
/**
* @param level 设置眼角级别 [0 - 1]
*/
void setEyeAngleLevel(float level);
/**
* @param level 设置开内眼角级别 [0 - 1]
*/
void setEyeInnerConerLevel(float level);
/**
* @param level 设置开外眼角级别 [0 - 1]
*/
void setEyeOuterConerLevel(float level);
/**
* @param level 设置眼距级别 [-1 - 1]
*/
void setEyeDistanceLevel(float level);
/**
* @param level 设置眼移动级别 [-1 - 1]
*/
void setEyeHeightLevel(float level);
/**
* @param level 设置发际线级别 [-1 - 1]
*/
void setForeheadHeightLevel(float level);
/**
* @param level 设置瘦颧骨级别 [-1 - 1]
*/
void setCheekBoneNarrowLevel(float level);
/**
* @param level 这是双眼皮级别 [0 - 1]
*/
void setEyelidLevel(float level);
/**
* @param level 设置卧蚕级别 [0 - 1]
*/
void setEyemazingLevel(float level);
/**
* @param level 设置白牙级别 [0 - 1]
*/
void setWhitenTeethLevel(float level);
/**
* @param level 设置亮眼级别 [0 - 1]
*/
void setEyeDetailLevel(float level);
/**
* @param level 设置祛黑眼圈级别 [0 - 1]
*/
void setRemovePouchLevel(float level);
/**
* @param level 设置祛法令纹级别 [0 - 1]
*/
void setRemoveWrinklesLevel(float level);
/**
* @param enable 设置开启美妆-口红
*/
void setLipEnable(boolean enable);
/**
* @param style 设置口红样式 水润 滋润 雾面
*/
void setLipStyle(BeautyLipstickStyle style);
/**
* @param opacity 设置口红透明度 [0 - 1]
*/
void setLipOpacity(float opacity);
/**
* @param color 设置口红颜色
*/
void setLipColor(int color);
/**
* @param enable 设置开启美妆-腮红
*/
void setBlushEnable(boolean enable);
/**
* @param opacity 设置腮红透明度 [0 - 1]
*/
void setBlushOpacity(float opacity);
/**
* @param stickerId 设置腮红ID
*/
void setBlushStickerId(long stickerId);
/**
* @param enable 设置开启美妆-眉毛
*/
void setBrowEnable(boolean enable);
/**
* @param opacity 设置眉毛透明度 [0 - 1]
*/
void setBrowOpacity(float opacity);
/**
* @param stickerId 设置眉毛ID
*/
void setBrowStickerId(long stickerId);
/**
* @param enable 设置开启美妆-眼影
*/
void setEyeshadowEnable(boolean enable);
/**
* @param opacity 设置眼影透明度 [0 - 1]
*/
void setEyeshadowOpacity(float opacity);
/**
* @param stickerId 设置眼影ID
*/
void setEyeshadowStickerId(long stickerId);
/**
* @param enable 设置开启美妆-眼线
*/
void setEyelineEnable(boolean enable);
/**
* @param opacity 设置眼线透明度 [0 - 1]
*/
void setEyelineOpacity(float opacity);
/**
* @param stickerId 设置眼线ID
*/
void setEyelineStickerId(long stickerId);
/**
* @param enable 设置开启美妆-睫毛
*/
void setEyelashEnable(boolean enable);
/**
* @param opacity 设置睫毛透明度 [0 - 1]
*/
void setEyelashOpacity(float opacity);
/**
* @param stickerId 设置睫毛ID
*/
void setEyelashStickerId(long stickerId);
/**
* @param enable 设置开启美妆-修容
*/
void setFacialEnable(boolean enable);
/**
* @param opacity 设置修容透明度 [0 - 1]
*/
void setFacialOpacity(float opacity);
/**
* @param stickerId 设置修容ID
*/
void setFacialStickerId(long stickerId);
/**
* 设置滤镜
* @param filterCode 滤镜代号
*/
void setFilter(String filterCode);
/**
* @param strength 滤镜强度 [0 - 1]
*/
void setFilterStrength(float strength);
/**
* 设置人脸动态贴纸
* @param stickerId 贴纸ID
*/
void setDynamicSticker(long stickerId);
/**
* @return 当前是否使用了人脸动态贴纸
*/
boolean hasDynamicSticker();
/**
* 设置人脸哈哈镜
* @param code 哈哈镜代号
*/
void setMonsterFace(String code);
/**
* @return 当前是否使用了人脸哈哈镜
*/
boolean hasMonsterFace();
/**
* 设置视频合拍
* @param videoRect 合拍素材渲染区域 [0,0,1,1]
* @param cameraRect 相机画面渲染区域 [0,0,1,1]
* @param videoPath 合拍素材路径
*/
void setJoiner(RectF videoRect,RectF cameraRect,String videoPath);
/**
* 取消合拍
*/
void deleteJoiner();
/**
* 更新合拍素材以及相机渲染区域
* @param videoRect 合拍素材渲染区域 [0,0,1,1]
* @param cameraRect 相机画面渲染区域 [0,0,1,1]
*/
void updateJoiner(RectF videoRect,RectF cameraRect);
/**
* @return 当前是否应用了合拍功能
*/
boolean hasJoiner();
/**
* 合拍素材跳转
* @param ts 视频跳转位置
* @return 是否跳转成功
*/
boolean joinerSeek(long ts);
/**
* 调节合拍视频播放速度
* @param videoStretch 播放速度
*/
void updateVideoStretch(double videoStretch);
/**
* 设置渲染宽度
* @param size 渲染宽度
*/
void setRenderSize(TuSdkSize size);
/**
* 设置合拍视频开始播放位置
* @param ts
*/
void updateJoinerPlayerStartPos(long ts);
/**
* 设置合拍视频播放状态
* @param isPlaying 是否开始播放
*/
void setJoinerPlayerState(boolean isPlaying);
}
视频分段录制、变速录制、视频合成保存等
接口文件 | 功能 |
---|---|
RecordManager | 视频录制 |
Image | 图像 |
VideoFragmentItem | 视频录制片段 |
// RecordManager.java
public static class VideoFragmentItem{
/**
* 片段保存路径
*/
public String path;
/**
* 片段长度
*/
public long fragmentDuration;
}
public static interface RecordListener{
/**
* 进度回调
* @param progress 比例 0~1
* @param ts 时间戳
*/
void onProgress(float progress,long ts);
/**
* 录制超时回调
*/
void onRecordTimeOut();
/**
* 启动录制回调
*/
void onRecordStart();
/**
* 录制暂停回调
*/
void onRecordPause();
/**
* 录制停止回调
*/
void onRecordStop();
}
/**
* 创建视频录制工具
*
* @param outputPath 最终输出路径
* @param width 视频宽度
* @param height 视频高度
* @param channels 音频声道数
* @param sampleRate 音频采样率
* @param watermark 水印图片
* @param watermarkPos 水印位置
* @param glContext 纹理采集环境上下文
* @return 创建状态 -1 参数异常 0 成功
*/
public Pair<Boolean,Integer> newExporter(String outputPath, int width, int height, int channels, int sampleRate, @Nullable Bitmap watermark, int watermarkPos, GLContext glContext);
/**
* @return 开始视频录制
*/
public boolean startExporter();
/**
* 重置录制工具状态
*/
public void resetExporter();
/**
* @return 暂停录制
*/
public boolean pauseExporter();
/**
* @return 停止录制
*/
public boolean stopExporter();
/**
* 输入视频
* @param image 视频帧
* @param ts 时间戳
*/
public void sendImage(Image image,long ts);
/**
* 输入音频 最大可处理4096长度的数据
* @param buffer 音频数据
* @param length 数据长度
* @param ts 时间戳
*/
public void sendAudio(byte[] buffer,int length,long ts);
录制速度、声音设置、设置水印
// RecordManager.java
/**
* @param listener 录制监听
*/
public void setRecordListener(RecordListener listener);
/**
* @param durationMS 录制最大时间
*/
public void setMaxRecordDuration(long durationMS);
/**
* @param stretch 更新视频速度
*/
public void updateStretch(double stretch);
// RecordManager.java
/**
* @return 弹出最后一段录制片段
*/
public VideoFragmentItem popFragment();
/**
* @return 获取当前录制片段数量
*/
public int getFragmentSize();
/**
* @return 获取当前录制时长
*/
public long getCurrentRecordDuration();
/**
* 保存视频 目前适配到Android11
* @param input 输入路径
* @param output 输出路径 可以为公共区域
*/
public void saveVideo(String input,String output);