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