• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Video Recording (ArkTS)
2
3As another important function of the camera application, video recording is the process of cyclic frame capture. To smooth video recording, you can follow step 4 in [Photo Capture](camera-shooting.md) to set the resolution, flash, focal length, photo quality, and rotation angle.
4
5## How to Develop
6
7Read [Camera](../../reference/apis-camera-kit/js-apis-camera.md) for the API reference.
8
91. Import the media module.
10
11   The [APIs](../../reference/apis-media-kit/js-apis-media.md) provided by this module are used to obtain the surface ID and create a video output stream.
12
13   ```ts
14   import { BusinessError } from '@kit.BasicServicesKit';
15   import { camera } from '@kit.CameraKit';
16   import { media } from '@kit.MediaKit';
17   ```
18
192. Create a surface.
20
21   Call **createAVRecorder()** of the media module to create an **AVRecorder** instance, and call [getInputSurface](../../reference/apis-media-kit/js-apis-media.md#getinputsurface9) of the instance to obtain the surface ID, which is associated with the video output stream to process the stream data.
22
23   ```ts
24   async function getVideoSurfaceId(aVRecorderConfig: media.AVRecorderConfig): Promise<string | undefined> {  // For details about aVRecorderConfig, see the next section.
25     let avRecorder: media.AVRecorder | undefined = undefined;
26     try {
27       avRecorder = await media.createAVRecorder();
28     } catch (error) {
29       let err = error as BusinessError;
30       console.error(`createAVRecorder call failed. error code: ${err.code}`);
31     }
32     if (avRecorder === undefined) {
33       return undefined;
34     }
35     avRecorder.prepare(aVRecorderConfig, (err: BusinessError) => {
36       if (err == null) {
37         console.info('prepare success');
38       } else {
39         console.error('prepare failed and error is ' + err.message);
40       }
41     });
42     let videoSurfaceId = await avRecorder.getInputSurface();
43     return videoSurfaceId;
44   }
45   ```
46
473. Create a video output stream.
48
49   Obtain the video output streams supported by the current device from **videoProfiles** in the [CameraOutputCapability](../../reference/apis-camera-kit/js-apis-camera.md#cameraoutputcapability) class. Then, define video recording parameters and use [createVideoOutput](../../reference/apis-camera-kit/js-apis-camera.md#createvideooutput) to create a video output stream.
50
51   > **NOTE**
52   >
53   > The preview stream and video output stream must have the same aspect ratio of the resolution. For example, the aspect ratio in the code snippet below is 640:480 (which is equal to 4:3), then the aspect ratio of the resolution of the preview stream must also be 4:3. This means that the resolution can be 640:480, 960:720, 1440:1080, or the like.
54   >
55   > To obtain the video rotation angle (specified by **rotation**), call [getVideoRotation](../../reference/apis-camera-kit/js-apis-camera.md#getvideorotation12) in the [VideoOutput](../../reference/apis-camera-kit/js-apis-camera.md#videooutput) class.
56
57   ```ts
58   async function getVideoOutput(cameraManager: camera.CameraManager, videoSurfaceId: string, cameraOutputCapability: camera.CameraOutputCapability): Promise<camera.VideoOutput | undefined> {
59     let videoProfilesArray: Array<camera.VideoProfile> = cameraOutputCapability.videoProfiles;
60     if (!videoProfilesArray) {
61       console.error("createOutput videoProfilesArray == null || undefined");
62       return undefined;
63     }
64     // AVRecorderProfile.
65     let aVRecorderProfile: media.AVRecorderProfile = {
66       fileFormat: media.ContainerFormatType.CFT_MPEG_4, // Video file container format. Only MP4 is supported.
67       videoBitrate: 100000, // Video bit rate.
68       videoCodec: media.CodecMimeType.VIDEO_AVC, // Video file encoding format. AVC is supported.
69       videoFrameWidth: 640, // Video frame width.
70       videoFrameHeight: 480, // Video frame height.
71       videoFrameRate: 30 // Video frame rate.
72     };
73     // Define video recording parameters. The ratio of the resolution width (videoFrameWidth) to the resolution height (videoFrameHeight) of the video output stream must be the same as that of the preview stream.
74     let aVRecorderConfig: media.AVRecorderConfig = {
75       videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,
76       profile: aVRecorderProfile,
77       url: 'fd://35',
78       rotation: 90 // The value of rotation is 90, which is obtained through getPhotoRotation.
79     };
80     // Create an AVRecorder instance.
81     let avRecorder: media.AVRecorder | undefined = undefined;
82     try {
83       avRecorder = await media.createAVRecorder();
84     } catch (error) {
85       let err = error as BusinessError;
86       console.error(`createAVRecorder call failed. error code: ${err.code}`);
87     }
88     if (avRecorder === undefined) {
89       return undefined;
90     }
91     // Set video recording parameters.
92     avRecorder.prepare(aVRecorderConfig);
93     // Create a VideoOutput instance.
94     let videoOutput: camera.VideoOutput | undefined = undefined;
95     // The width and height of the videoProfile object passed in by createVideoOutput must be the same as those of aVRecorderProfile.
96     let videoProfile: undefined | camera.VideoProfile = videoProfilesArray.find((profile: camera.VideoProfile) => {
97       return profile.size.width === aVRecorderProfile.videoFrameWidth && profile.size.height === aVRecorderProfile.videoFrameHeight;
98     });
99     if (!videoProfile) {
100       console.error('videoProfile is not found');
101       return;
102     }
103     try {
104       videoOutput = cameraManager.createVideoOutput(videoProfile, videoSurfaceId);
105     } catch (error) {
106       let err = error as BusinessError;
107       console.error('Failed to create the videoOutput instance. errorCode = ' + err.code);
108     }
109     return videoOutput;
110   }
111   ```
112
1134. Start video recording.
114
115   Call [start](../../reference/apis-camera-kit/js-apis-camera.md#start-1) of the **VideoOutput** instance to start the video output stream, and then call [start](../../reference/apis-media-kit/js-apis-media.md#start9) of the **AVRecorder** instance to start recording.
116
117   ```ts
118   async function startVideo(videoOutput: camera.VideoOutput, avRecorder: media.AVRecorder): Promise<void> {
119     videoOutput.start(async (err: BusinessError) => {
120       if (err) {
121         console.error(`Failed to start the video output ${err.message}`);
122         return;
123       }
124       console.info('Callback invoked to indicate the video output start success.');
125     });
126     try {
127       await avRecorder.start();
128     } catch (error) {
129       let err = error as BusinessError;
130       console.error(`avRecorder start error: ${JSON.stringify(err)}`);
131     }
132   }
133   ```
134
1355. Stop video recording.
136
137   Call [stop](../../reference/apis-media-kit/js-apis-media.md#stop9-3) of the **AVRecorder** instance to stop recording, and then call [stop](../../reference/apis-camera-kit/js-apis-camera.md#stop-1) of the **VideoOutput** instance to stop the video output stream.
138
139   ```ts
140   async function stopVideo(videoOutput: camera.VideoOutput, avRecorder: media.AVRecorder): Promise<void> {
141     try {
142       await avRecorder.stop();
143     } catch (error) {
144       let err = error as BusinessError;
145       console.error(`avRecorder stop error: ${JSON.stringify(err)}`);
146     }
147     videoOutput.stop((err: BusinessError) => {
148       if (err) {
149         console.error(`Failed to stop the video output ${err.message}`);
150         return;
151       }
152       console.info('Callback invoked to indicate the video output stop success.');
153     });
154   }
155   ```
156
157
158## Status Listening
159
160During camera application development, you can listen for the status of the video output stream, including recording start, recording end, and video output errors.
161
162- Register the **'frameStart'** event to listen for recording start events. This event can be registered when a **VideoOutput** instance is created and is triggered when the bottom layer starts exposure for recording for the first time. Video recording starts as long as a result is returned.
163
164  ```ts
165  function onVideoOutputFrameStart(videoOutput: camera.VideoOutput): void {
166    videoOutput.on('frameStart', (err: BusinessError) => {
167      if (err !== undefined && err.code !== 0) {
168        return;
169      }
170      console.info('Video frame started');
171    });
172  }
173  ```
174
175- Register the **'frameEnd'** event to listen for recording end events. This event can be registered when a **VideoOutput** instance is created and is triggered when the last frame of recording ends. Video recording ends as long as a result is returned.
176
177  ```ts
178  function onVideoOutputFrameEnd(videoOutput: camera.VideoOutput): void {
179    videoOutput.on('frameEnd', (err: BusinessError) => {
180      if (err !== undefined && err.code !== 0) {
181        return;
182      }
183      console.info('Video frame ended');
184    });
185  }
186  ```
187
188- Register the **'error'** event to listen for video output errors. The callback function returns an error code when an API is incorrectly used. For details about the error code types, see [CameraErrorCode](../../reference/apis-camera-kit/js-apis-camera.md#cameraerrorcode).
189
190  ```ts
191  function onVideoOutputError(videoOutput: camera.VideoOutput): void {
192    videoOutput.on('error', (error: BusinessError) => {
193      console.error(`Video output error code: ${error.code}`);
194    });
195  }
196  ```
197
198<!--RP1-->
199<!--RP1End-->
200