1# 录像实现方案 2 3## 开发流程 4 5在获取到相机支持的输出流能力后,开始创建录像流,开发流程如下。 6 7 8 9 10## 完整示例 11[BaseContext获取方式](../reference/apis/js-apis-inner-application-baseContext.md)。 12```ts 13import camera from '@ohos.multimedia.camera'; 14import { BusinessError } from '@ohos.base'; 15import media from '@ohos.multimedia.media'; 16import common from '@ohos.app.ability.common'; 17 18async function videoRecording(baseContext: common.BaseContext, surfaceId: string): Promise<void> { 19 // 创建CameraManager对象 20 let cameraManager: camera.CameraManager = camera.getCameraManager(baseContext); 21 if (!cameraManager) { 22 console.error("camera.getCameraManager error"); 23 return; 24 } 25 26 // 监听相机状态变化 27 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 28 console.log(`camera : ${cameraStatusInfo.camera.cameraId}`); 29 console.log(`status: ${cameraStatusInfo.status}`); 30 }); 31 32 // 获取相机列表 33 let cameraArray: Array<camera.CameraDevice> = []; 34 try { 35 cameraArray = cameraManager.getSupportedCameras(); 36 } catch (error) { 37 let err = error as BusinessError; 38 console.error(`getSupportedCameras call failed. error code: ${err.code}`); 39 } 40 41 if (cameraArray.length <= 0) { 42 console.error("cameraManager.getSupportedCameras error") 43 return; 44 } 45 46 // 获取相机设备支持的输出流能力 47 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0]); 48 if (!cameraOutputCap) { 49 console.error("cameraManager.getSupportedOutputCapability error") 50 return; 51 } 52 console.log("outputCapability: " + JSON.stringify(cameraOutputCap)); 53 54 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 55 if (!previewProfilesArray) { 56 console.error("createOutput previewProfilesArray == null || undefined"); 57 } 58 59 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 60 if (!photoProfilesArray) { 61 console.error("createOutput photoProfilesArray == null || undefined"); 62 } 63 64 let videoProfilesArray: Array<camera.VideoProfile> = cameraOutputCap.videoProfiles; 65 if (!videoProfilesArray) { 66 console.error("createOutput videoProfilesArray == null || undefined"); 67 } 68 69 let metadataObjectTypesArray: Array<camera.MetadataObjectType> = cameraOutputCap.supportedMetadataObjectTypes; 70 if (!metadataObjectTypesArray) { 71 console.error("createOutput metadataObjectTypesArray == null || undefined"); 72 } 73 74 // 配置参数以实际硬件设备支持的范围为准 75 let aVRecorderProfile: media.AVRecorderProfile = { 76 audioBitrate: 48000, 77 audioChannels: 2, 78 audioCodec: media.CodecMimeType.AUDIO_AAC, 79 audioSampleRate: 48000, 80 fileFormat: media.ContainerFormatType.CFT_MPEG_4, 81 videoBitrate: 2000000, 82 videoCodec: media.CodecMimeType.VIDEO_MPEG4, 83 videoFrameWidth: 640, 84 videoFrameHeight: 480, 85 videoFrameRate: 30 86 }; 87 let aVRecorderConfig: media.AVRecorderConfig = { 88 audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, 89 videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, 90 profile: aVRecorderProfile, 91 url: 'fd://', // 文件需先由调用者创建,赋予读写权限,将文件fd传给此参数,eg.fd://45--file:///data/media/01.mp4 92 rotation: 0, // 合理值0、90、180、270,非合理值prepare接口将报错 93 location: { latitude: 30, longitude: 130 } 94 }; 95 96 let avRecorder: media.AVRecorder | undefined = undefined; 97 try { 98 avRecorder = await media.createAVRecorder(); 99 } catch (error) { 100 let err = error as BusinessError; 101 console.error(`createAVRecorder call failed. error code: ${err.code}`); 102 } 103 104 if (avRecorder === undefined) { 105 return; 106 } 107 108 try { 109 await avRecorder.prepare(aVRecorderConfig); 110 } catch (error) { 111 let err = error as BusinessError; 112 console.error(`prepare call failed. error code: ${err.code}`); 113 } 114 115 let videoSurfaceId: string | undefined = undefined; // 该surfaceID用于传递给相机接口创造videoOutput 116 try { 117 videoSurfaceId = await avRecorder.getInputSurface(); 118 } catch (error) { 119 let err = error as BusinessError; 120 console.error(`getInputSurface call failed. error code: ${err.code}`); 121 } 122 if (videoSurfaceId === undefined) { 123 return; 124 } 125 // 创建VideoOutput对象 126 let videoOutput: camera.VideoOutput | undefined = undefined; 127 try { 128 videoOutput = cameraManager.createVideoOutput(videoProfilesArray[0], videoSurfaceId); 129 } catch (error) { 130 let err = error as BusinessError; 131 console.error(`Failed to create the videoOutput instance. error: ${JSON.stringify(err)}`); 132 } 133 if (videoOutput === undefined) { 134 return; 135 } 136 // 监听视频输出错误信息 137 videoOutput.on('error', (error: BusinessError) => { 138 console.log(`Preview output error code: ${error.code}`); 139 }); 140 141 //创建会话 142 let captureSession: camera.CaptureSession | undefined = undefined; 143 try { 144 captureSession = cameraManager.createCaptureSession(); 145 } catch (error) { 146 let err = error as BusinessError; 147 console.error(`Failed to create the CaptureSession instance. error: ${JSON.stringify(err)}`); 148 } 149 if (captureSession === undefined) { 150 return; 151 } 152 // 监听session错误信息 153 captureSession.on('error', (error: BusinessError) => { 154 console.log(`Capture session error code: ${error.code}`); 155 }); 156 157 // 开始配置会话 158 try { 159 captureSession.beginConfig(); 160 } catch (error) { 161 let err = error as BusinessError; 162 console.error(`Failed to beginConfig. error: ${JSON.stringify(err)}`); 163 } 164 165 // 创建相机输入流 166 let cameraInput: camera.CameraInput | undefined = undefined; 167 try { 168 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 169 } catch (error) { 170 let err = error as BusinessError; 171 console.error(`Failed to createCameraInput. error: ${JSON.stringify(err)}`); 172 } 173 if (cameraInput === undefined) { 174 return; 175 } 176 // 监听cameraInput错误信息 177 let cameraDevice: camera.CameraDevice = cameraArray[0]; 178 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 179 console.log(`Camera input error code: ${error.code}`); 180 }); 181 182 // 打开相机 183 try { 184 await cameraInput.open(); 185 } catch (error) { 186 let err = error as BusinessError; 187 console.error(`Failed to open cameraInput. error: ${JSON.stringify(err)}`); 188 } 189 190 // 向会话中添加相机输入流 191 try { 192 captureSession.addInput(cameraInput); 193 } catch (error) { 194 let err = error as BusinessError; 195 console.error(`Failed to add cameraInput. error: ${JSON.stringify(err)}`); 196 } 197 198 // 创建预览输出流,其中参数 surfaceId 参考下面 XComponent 组件,预览流为XComponent组件提供的surface 199 let previewOutput: camera.PreviewOutput | undefined = undefined; 200 try { 201 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 202 } catch (error) { 203 let err = error as BusinessError; 204 console.error(`Failed to create the PreviewOutput instance. error: ${JSON.stringify(err)}`); 205 } 206 207 if (previewOutput === undefined) { 208 return; 209 } 210 // 向会话中添加预览输入流 211 try { 212 captureSession.addOutput(previewOutput); 213 } catch (error) { 214 let err = error as BusinessError; 215 console.error(`Failed to add previewOutput. error: ${JSON.stringify(err)}`); 216 } 217 218 // 向会话中添加录像输出流 219 try { 220 captureSession.addOutput(videoOutput); 221 } catch (error) { 222 let err = error as BusinessError; 223 console.error(`Failed to add videoOutput. error: ${JSON.stringify(err)}`); 224 } 225 226 // 提交会话配置 227 try { 228 await captureSession.commitConfig(); 229 } catch (error) { 230 let err = error as BusinessError; 231 console.error(`captureSession commitConfig error: ${JSON.stringify(err)}`); 232 } 233 234 // 启动会话 235 try { 236 await captureSession.start(); 237 } catch (error) { 238 let err = error as BusinessError; 239 console.error(`captureSession start error: ${JSON.stringify(err)}`); 240 } 241 242 // 启动录像输出流 243 videoOutput.start((err: BusinessError) => { 244 if (err) { 245 console.error(`Failed to start the video output. error: ${JSON.stringify(err)}`); 246 return; 247 } 248 console.log('Callback invoked to indicate the video output start success.'); 249 }); 250 251 // 开始录像 252 try { 253 await avRecorder.start(); 254 } catch (error) { 255 let err = error as BusinessError; 256 console.error(`avRecorder start error: ${JSON.stringify(err)}`); 257 } 258 259 // 停止录像输出流 260 videoOutput.stop((err: BusinessError) => { 261 if (err) { 262 console.error(`Failed to stop the video output. error: ${JSON.stringify(err)}`); 263 return; 264 } 265 console.log('Callback invoked to indicate the video output stop success.'); 266 }); 267 268 // 停止录像 269 try { 270 await avRecorder.stop(); 271 } catch (error) { 272 let err = error as BusinessError; 273 console.error(`avRecorder stop error: ${JSON.stringify(err)}`); 274 } 275 276 // 停止当前会话 277 captureSession.stop(); 278 279 // 释放相机输入流 280 cameraInput.close(); 281 282 // 释放预览输出流 283 previewOutput.release(); 284 285 // 释放录像输出流 286 videoOutput.release(); 287 288 // 释放会话 289 captureSession.release(); 290 291 // 会话置空 292 captureSession = undefined; 293} 294``` 295