示例场景:ATS侧启动相机,使用摄像头采集视频流数据,获取相机视频流数据传递到native侧,通过buffer模式将视频编码成MP4文件保存到沙箱路径。
方案描述:具体实现步骤可分为:
Step1:申请权限,启动相机。
Step2: 启动录制,获取视频流数据,获取一帧图像转成JPG格式保存到沙箱路径。
Step3: 视频流数据传递到native侧,进行压缩编码,生成文件保存。
步骤一: 申请权限,启动相机。需要相机、麦克风、媒体位置、写入媒体和读取媒体权限。
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.MICROPHONE",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.MEDIA_LOCATION",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.WRITE_MEDIA",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.READ_MEDIA",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
}
]
2:启动相机,预览实现。导入camera接口,创建双路预览流通道,使用XComponent组件和ImageReceiver组件创建Surface用来显示和获取预览图像。
async function createDualChannelPreview(cameraManager: camera.CameraManager, XComponentSurfaceId: string, receiver: image.ImageReceiver): Promise<void> {
// 获取支持的相机设备对象
let camerasDevices: Array<camera.CameraDevice> = cameraManager.getSupportedCameras();
// 获取支持的模式类型
let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(camerasDevices[0]);
let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0;
if (!isSupportPhotoMode) {
console.error('photo mode not support');
return;
}
// 获取profile对象
let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices[0], camera.SceneMode.NORMAL_PHOTO); // 获取对应相机设备profiles
let previewProfiles: Array<camera.Profile> = profiles.previewProfiles;
// 预览流1
let previewProfilesObj: camera.Profile = previewProfiles[0];
// 预览流2
let previewProfilesObj2: camera.Profile = previewProfiles[0];
// 创建 预览流1 输出对象
let previewOutput: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentSurfaceId);
// 创建 预览流2 输出对象
let imageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
let previewOutput2: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj2, imageReceiverSurfaceId);
// 创建cameraInput对象
let cameraInput: camera.CameraInput = cameraManager.createCameraInput(camerasDevices[0]);
// 打开相机
await cameraInput.open();
// 会话流程
let photoSession: camera.CaptureSession = cameraManager.createCaptureSession();
// 开始配置会话
photoSession.beginConfig();
// 把CameraInput加入到会话
photoSession.addInput(cameraInput);
// 把 预览流1 加入到会话
photoSession.addOutput(previewOutput);
// 把 预览流2 加入到会话
photoSession.addOutput(previewOutput2);
// 提交配置信息
await photoSession.commitConfig();
// 会话开始
await photoSession.start();
}
## **步骤二**:启动录制,获取相机视频流数据。
1:生成相机视频流数据:视频流数据是通过在onPageShow里面启动本地录制生成,当页面显示时,会调用 startRecord()方法开始录制,在页面隐藏时,调用 stopRecorder()函数停止录制视频,并释放相机资源。
async onPageShow() {
this.startRecord();
await grantPermission().then(res => {
console.info(TAG, `权限申请成功 ${JSON.stringify(res)}`);
if (res) {
createDualChannelPreview(this.surfaceId, this.receiver);
}
})
}
private startRecord() {
videoCompressor.startRecorder(getContext(), cameraWidth, cameraHeight)
.then((data) => {
if (data.code == CompressorResponseCode.SUCCESS) {
Logger.debug("videoCompressor-- record success");
} else {
Logger.debug("videoCompressor code:" + data.code + "--error message:" + data.message);
}
}).catch((err: Error) => {
Logge