• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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