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