1# Camera Recording Sample (ArkTS) 2 3This topic provides sample code that covers the complete recording process to help you understand the complete API calling sequence. 4 5Before referring to the sample code, you are advised to read [Device Input Management](camera-device-input.md), [Camera Session Management](camera-session-management.md), [Camera Recording](camera-recording.md), and other related topics in [Camera Development (ArkTS)](camera-preparation.md). 6 7## Development Process 8 9After obtaining the output stream capabilities supported by the camera, create a video stream. The development process is as follows: 10 11 12 13 14## Sample Code 15For details about how to obtain the context, see [Obtaining the Context of UIAbility](../../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 16 17```ts 18import { camera } from '@kit.CameraKit'; 19import { BusinessError } from '@kit.BasicServicesKit'; 20import { media } from '@kit.MediaKit'; 21import { common } from '@kit.AbilityKit'; 22import { photoAccessHelper } from '@kit.MediaLibraryKit'; 23import { fileIo as fs } from '@kit.CoreFileKit'; 24 25async function videoRecording(context: common.Context, surfaceId: string): Promise<void> { 26 // Create a CameraManager instance. 27 let cameraManager: camera.CameraManager = camera.getCameraManager(context); 28 if (!cameraManager) { 29 console.error("camera.getCameraManager error"); 30 return; 31 } 32 33 // Listen for camera status changes. 34 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 35 if (err !== undefined && err.code !== 0) { 36 console.error('cameraStatus with errorCode = ' + err.code); 37 return; 38 } 39 console.info(`camera : ${cameraStatusInfo.camera.cameraId}`); 40 console.info(`status: ${cameraStatusInfo.status}`); 41 }); 42 43 // Obtain the camera list. 44 let cameraArray: Array<camera.CameraDevice> = []; 45 try { 46 cameraArray = cameraManager.getSupportedCameras(); 47 } catch (error) { 48 let err = error as BusinessError; 49 console.error(`getSupportedCameras call failed. error code: ${err.code}`); 50 } 51 52 if (cameraArray.length <= 0) { 53 console.error("cameraManager.getSupportedCameras error"); 54 return; 55 } 56 57 // Obtain the supported modes. 58 let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]); 59 let isSupportVideoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_VIDEO) >= 0; 60 if (!isSupportVideoMode) { 61 console.error('video mode not support'); 62 return; 63 } 64 65 // Obtain the output stream capabilities supported by the camera. 66 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_VIDEO); 67 if (!cameraOutputCap) { 68 console.error("cameraManager.getSupportedOutputCapability error") 69 return; 70 } 71 console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 72 73 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 74 if (!previewProfilesArray) { 75 console.error("createOutput previewProfilesArray == null || undefined"); 76 } 77 78 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 79 if (!photoProfilesArray) { 80 console.error("createOutput photoProfilesArray == null || undefined"); 81 } 82 83 let videoProfilesArray: Array<camera.VideoProfile> = cameraOutputCap.videoProfiles; 84 if (!videoProfilesArray) { 85 console.error("createOutput videoProfilesArray == null || undefined"); 86 } 87 // The width and height of videoProfile must be the same as those of AVRecorderProfile. 88 let videoSize: camera.Size = { 89 width: 640, 90 height: 480 91 } 92 let videoProfile: undefined | camera.VideoProfile = videoProfilesArray.find((profile: camera.VideoProfile) => { 93 return profile.size.width === videoSize.width && profile.size.height === videoSize.height; 94 }); 95 if (!videoProfile) { 96 console.error('videoProfile is not found'); 97 return; 98 } 99 // Configure the parameters based on those supported by the hardware device. 100 let aVRecorderProfile: media.AVRecorderProfile = { 101 audioBitrate: 48000, 102 audioChannels: 2, 103 audioCodec: media.CodecMimeType.AUDIO_AAC, 104 audioSampleRate: 48000, 105 fileFormat: media.ContainerFormatType.CFT_MPEG_4, 106 videoBitrate: 2000000, 107 videoCodec: media.CodecMimeType.VIDEO_AVC, 108 videoFrameWidth: videoSize.width, 109 videoFrameHeight: videoSize.height, 110 videoFrameRate: 30 111 }; 112 let options: photoAccessHelper.CreateOptions = { 113 title: Date.now().toString() 114 }; 115 let accessHelper: photoAccessHelper.PhotoAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); 116 let videoUri: string = await accessHelper.createAsset(photoAccessHelper.PhotoType.VIDEO, 'mp4', options); 117 let file: fs.File = fs.openSync(videoUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 118 let aVRecorderConfig: media.AVRecorderConfig = { 119 audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, 120 videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, 121 profile: aVRecorderProfile, 122 url: `fd://${file.fd.toString()}`, // Before passing in a file descriptor to this parameter, the file must be created by the caller and granted with the read and write permissions. Example value: fd://45--file:///data/media/01.mp4. 123 rotation: 0, // The value can be 0, 90, 180, or 270. If any other value is used, prepare() reports an error. 124 location: { latitude: 30, longitude: 130 } 125 }; 126 127 let avRecorder: media.AVRecorder | undefined = undefined; 128 try { 129 avRecorder = await media.createAVRecorder(); 130 } catch (error) { 131 let err = error as BusinessError; 132 console.error(`createAVRecorder call failed. error code: ${err.code}`); 133 } 134 135 if (avRecorder === undefined) { 136 return; 137 } 138 139 try { 140 await avRecorder.prepare(aVRecorderConfig); 141 } catch (error) { 142 let err = error as BusinessError; 143 console.error(`prepare call failed. error code: ${err.code}`); 144 } 145 146 let videoSurfaceId: string | undefined = undefined; // The surfaceID is passed in to the camera API to create a VideoOutput instance. 147 try { 148 videoSurfaceId = await avRecorder.getInputSurface(); 149 } catch (error) { 150 let err = error as BusinessError; 151 console.error(`getInputSurface call failed. error code: ${err.code}`); 152 } 153 if (videoSurfaceId === undefined) { 154 return; 155 } 156 // Create a VideoOutput instance. 157 let videoOutput: camera.VideoOutput | undefined = undefined; 158 try { 159 videoOutput = cameraManager.createVideoOutput(videoProfile, videoSurfaceId); 160 } catch (error) { 161 let err = error as BusinessError; 162 console.error(`Failed to create the videoOutput instance. error: ${JSON.stringify(err)}`); 163 } 164 if (videoOutput === undefined) { 165 return; 166 } 167 // Listen for video output errors. 168 videoOutput.on('error', (error: BusinessError) => { 169 console.error(`Preview output error code: ${error.code}`); 170 }); 171 172 // Create a session. 173 let videoSession: camera.VideoSession | undefined = undefined; 174 try { 175 videoSession = cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO) as camera.VideoSession; 176 } catch (error) { 177 let err = error as BusinessError; 178 console.error(`Failed to create the session instance. error: ${JSON.stringify(err)}`); 179 } 180 if (videoSession === undefined) { 181 return; 182 } 183 // Listen for session errors. 184 videoSession.on('error', (error: BusinessError) => { 185 console.error(`Video session error code: ${error.code}`); 186 }); 187 188 // Start configuration for the session. 189 try { 190 videoSession.beginConfig(); 191 } catch (error) { 192 let err = error as BusinessError; 193 console.error(`Failed to beginConfig. error: ${JSON.stringify(err)}`); 194 } 195 196 // Create a camera input stream. 197 let cameraInput: camera.CameraInput | undefined = undefined; 198 try { 199 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 200 } catch (error) { 201 let err = error as BusinessError; 202 console.error(`Failed to createCameraInput. error: ${JSON.stringify(err)}`); 203 } 204 if (cameraInput === undefined) { 205 return; 206 } 207 // Listen for camera input errors. 208 let cameraDevice: camera.CameraDevice = cameraArray[0]; 209 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 210 console.error(`Camera input error code: ${error.code}`); 211 }); 212 213 // Open the camera. 214 try { 215 await cameraInput.open(); 216 } catch (error) { 217 let err = error as BusinessError; 218 console.error(`Failed to open cameraInput. error: ${JSON.stringify(err)}`); 219 } 220 221 // Add the camera input stream to the session. 222 try { 223 videoSession.addInput(cameraInput); 224 } catch (error) { 225 let err = error as BusinessError; 226 console.error(`Failed to add cameraInput. error: ${JSON.stringify(err)}`); 227 } 228 229 // Create a preview output stream. For details about the surfaceId parameter, see the <XComponent>. The preview stream is the surface provided by the <XComponent>. 230 let previewOutput: camera.PreviewOutput | undefined = undefined; 231 try { 232 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 233 } catch (error) { 234 let err = error as BusinessError; 235 console.error(`Failed to create the PreviewOutput instance. error: ${JSON.stringify(err)}`); 236 } 237 238 if (previewOutput === undefined) { 239 return; 240 } 241 // Add the preview output stream to the session. 242 try { 243 videoSession.addOutput(previewOutput); 244 } catch (error) { 245 let err = error as BusinessError; 246 console.error(`Failed to add previewOutput. error: ${JSON.stringify(err)}`); 247 } 248 249 // Add a video output stream to the session. 250 try { 251 videoSession.addOutput(videoOutput); 252 } catch (error) { 253 let err = error as BusinessError; 254 console.error(`Failed to add videoOutput. error: ${JSON.stringify(err)}`); 255 } 256 257 // Commit the session configuration. 258 try { 259 await videoSession.commitConfig(); 260 } catch (error) { 261 let err = error as BusinessError; 262 console.error(`videoSession commitConfig error: ${JSON.stringify(err)}`); 263 } 264 265 // Start the session. 266 try { 267 await videoSession.start(); 268 } catch (error) { 269 let err = error as BusinessError; 270 console.error(`videoSession start error: ${JSON.stringify(err)}`); 271 } 272 273 // Start the video output stream. 274 videoOutput.start((err: BusinessError) => { 275 if (err) { 276 console.error(`Failed to start the video output. error: ${JSON.stringify(err)}`); 277 return; 278 } 279 console.info('Callback invoked to indicate the video output start success.'); 280 }); 281 282 // Start video recording. 283 try { 284 await avRecorder.start(); 285 } catch (error) { 286 let err = error as BusinessError; 287 console.error(`avRecorder start error: ${JSON.stringify(err)}`); 288 } 289 290 // Stop the video output stream. 291 videoOutput.stop((err: BusinessError) => { 292 if (err) { 293 console.error(`Failed to stop the video output. error: ${JSON.stringify(err)}`); 294 return; 295 } 296 console.info('Callback invoked to indicate the video output stop success.'); 297 }); 298 299 // Stop video recording. 300 try { 301 await avRecorder.stop(); 302 } catch (error) { 303 let err = error as BusinessError; 304 console.error(`avRecorder stop error: ${JSON.stringify(err)}`); 305 } 306 307 // Stop the session. 308 videoSession.stop(); 309 310 // Close the files. 311 fs.closeSync(file); 312 313 // Release the camera input stream. 314 cameraInput.close(); 315 316 // Release the preview output stream. 317 previewOutput.release(); 318 319 // Release the video output stream. 320 videoOutput.release(); 321 322 // Release the session. 323 videoSession.release(); 324 325 // Set the session to null. 326 videoSession = undefined; 327} 328``` 329