1# Camera Development 2 3## When to Use 4 5With the APIs provided by the **Camera** module, you can access and operate camera devices and develop new functions. Common operations include preview, photographing, and video recording. You can also implement flash control, exposure time control, focus mode control, zoom control, and much more. 6 7Before calling camera APIs, be familiar with the following concepts: 8 9- **Static camera capabilities**: A series of parameters used to describe inherent capabilities of a camera, such as orientation and supported resolution. 10- **Physical camera**: An independent camera device. The physical camera ID is a string that uniquely identifies a physical camera. 11- **Asynchronous operation**: A non-blocking operation that allows other operations to execute before it completes. To prevent the UI thread from being blocked, some **Camera** calls are asynchronous. Each asynchronous API provides the callback and promise functions. 12 13## How to Develop 14 15### Available APIs 16 17For details about the APIs, see [Camera Management](../reference/apis/js-apis-camera.md). 18 19### Full-Process Scenario 20 21The full process includes applying for permissions, creating an instance, setting parameters, managing sessions, taking photos, recording videos, and releasing resources. 22 23#### Applying for Permissions 24 25You must apply for the permissions for your application to access the camera device and other functions. The following table lists camera-related permissions. 26 27| Permission| Attribute Value | 28| -------- | ------------------------------ | 29| Camera| ohos.permission.CAMERA | 30| Call recording| ohos.permission.MICROPHONE | 31| Storage| ohos.permission.WRITE_MEDIA | 32| Read| ohos.permission.READ_MEDIA | 33| Location| ohos.permission.MEDIA_LOCATION | 34 35The code snippet is as follows: 36 37```typescript 38const PERMISSIONS: Array<string> = [ 39 'ohos.permission.CAMERA', 40 'ohos.permission.MICROPHONE', 41 'ohos.permission.MEDIA_LOCATION', 42 'ohos.permission.READ_MEDIA', 43 'ohos.permission.WRITE_MEDIA' 44] 45 46function applyPermission() { 47 console.info('[permission] get permission'); 48 globalThis.abilityContext.requestPermissionFromUser(PERMISSIONS) 49 } 50``` 51 52#### Creating an Instance 53 54You must create an independent **CameraManager** instance before performing camera operations. If this operation fails, the camera may be occupied or unusable. If the camera is occupied, wait until it is released. You can call **getSupportedCameras()** to obtain the list of cameras supported by the current device. The list stores all camera IDs of the current device. Each of these IDs can be used to create an independent **CameraManager** instance. If the list is empty, no camera is available for the current device and subsequent operations cannot be performed. The camera has preview, shooting, video recording, and metadata output streams. You can use **getSupportedOutputCapability()** to obtain the output stream capabilities of the camera and configure them in the **profile** field in **CameraOutputCapability**. The procedure for creating a **CameraManager** instance is as follows: 55 56```typescript 57import camera from '@ohos.multimedia.camera' 58import image from '@ohos.multimedia.image' 59import media from '@ohos.multimedia.media' 60 61// Create a CameraManager instance. 62context: any = getContext(this) 63let cameraManager = camera.getCameraManager(this.context) 64if (!cameraManager) { 65 console.error("camera.getCameraManager error") 66 return; 67} 68// Listen for camera state changes. 69cameraManager.on('cameraStatus', (cameraStatusInfo) => { 70 console.log(`camera : ${cameraStatusInfo.camera.cameraId}`); 71 console.log(`status: ${cameraStatusInfo.status}`); 72}) 73 74// Obtain the camera list. 75let cameraArray = cameraManager.getSupportedCameras(); 76if (cameraArray.length <= 0) { 77 console.error("cameraManager.getSupportedCameras error") 78 return; 79} 80 81for (let index = 0; index < cameraArray.length; index++) { 82 console.log('cameraId : ' + cameraArray[index].cameraId); // Obtain the camera ID. 83 console.log('cameraPosition : ' + cameraArray[index].cameraPosition); // Obtain the camera position. 84 console.log('cameraType : ' + cameraArray[index].cameraType); // Obtain the camera type. 85 console.log('connectionType : ' + cameraArray[index].connectionType); // Obtain the camera connection type. 86} 87 88// Create a camera input stream. 89let cameraInput 90try { 91 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 92} catch () { 93 console.error('Failed to createCameraInput errorCode = ' + error.code); 94} 95 96// Listen for CameraInput errors. 97let cameraDevice = cameraArray[0]; 98cameraInput.on('error', cameraDevice, (error) => { 99 console.log(`Camera input error code: ${error.code}`); 100}) 101 102// Open the camera. 103await cameraInput.open(); 104 105// Obtain the output stream capabilities supported by the camera. 106let cameraOutputCap = cameraManager.getSupportedOutputCapability(cameraArray[0]); 107if (!cameraOutputCap) { 108 console.error("cameraManager.getSupportedOutputCapability error") 109 return; 110} 111console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 112 113let previewProfilesArray = cameraOutputCap.previewProfiles; 114if (!previewProfilesArray) { 115 console.error("createOutput previewProfilesArray == null || undefined") 116} 117 118let photoProfilesArray = cameraOutputCap.photoProfiles; 119if (!photoProfilesArray) { 120 console.error("createOutput photoProfilesArray == null || undefined") 121} 122 123let videoProfilesArray = cameraOutputCap.videoProfiles; 124if (!videoProfilesArray) { 125 console.error("createOutput videoProfilesArray == null || undefined") 126} 127 128let metadataObjectTypesArray = cameraOutputCap.supportedMetadataObjectTypes; 129if (!metadataObjectTypesArray) { 130 console.error("createOutput metadataObjectTypesArray == null || undefined") 131} 132 133// Create a preview stream. For details about the surfaceId parameter, see the XComponent section. The preview stream is the surface provided by the XComponent. 134let previewOutput 135try { 136 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId) 137} catch (error) { 138 console.error("Failed to create the PreviewOutput instance.") 139} 140 141// Listen for PreviewOutput errors. 142previewOutput.on('error', (error) => { 143 console.log(`Preview output error code: ${error.code}`); 144}) 145 146// Create an ImageReceiver instance and set photo parameters. Wherein, the resolution must be one of the photographing resolutions supported by the current device, which are obtained by photoProfilesArray. 147let imageReceiver = await image.createImageReceiver(1920, 1080, 4, 8) 148// Obtain the surface ID for displaying the photos. 149let photoSurfaceId = await imageReceiver.getReceivingSurfaceId() 150// Create a photographing output stream. 151let photoOutput 152try { 153 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0], photoSurfaceId) 154} catch (error) { 155 console.error('Failed to createPhotoOutput errorCode = ' + error.code); 156} 157 158// Define video recording parameters. 159let videoConfig = { 160 audioSourceType: 1, 161 videoSourceType: 1, 162 profile: { 163 audioBitrate: 48000, 164 audioChannels: 2, 165 audioCodec: 'audio/mp4v-es', 166 audioSampleRate: 48000, 167 durationTime: 1000, 168 fileFormat: 'mp4', 169 videoBitrate: 48000, 170 videoCodec: 'video/mp4v-es', 171 videoFrameWidth: 640, 172 videoFrameHeight: 480, 173 videoFrameRate: 30 174 }, 175 url: 'file:///data/media/01.mp4', 176 orientationHint: 0, 177 maxSize: 100, 178 maxDuration: 500, 179 rotation: 0 180} 181 182// Create a video recording output stream. 183let videoRecorder 184media.createVideoRecorder().then((recorder) => { 185 console.log('createVideoRecorder called') 186 videoRecorder = recorder 187}) 188// Set video recording parameters. 189videoRecorder.prepare(videoConfig) 190// Obtain the surface ID for video recording. 191let videoSurfaceId 192videoRecorder.getInputSurface().then((id) => { 193 console.log('getInputSurface called') 194 videoSurfaceId = id 195}) 196 197// Create a VideoOutput instance. 198let videoOutput 199try { 200 videoOutput = cameraManager.createVideoOutput(videoProfilesArray[0], videoSurfaceId) 201} catch (error) { 202 console.error('Failed to create the videoOutput instance. errorCode = ' + error.code); 203} 204 205// Listen for VideoOutput errors. 206videoOutput.on('error', (error) => { 207 console.log(`Preview output error code: ${error.code}`); 208}) 209``` 210Surfaces must be created in advance for the preview, shooting, and video recording stream. The preview stream is the surface provided by the **XComponent**, the shooting stream is the surface provided by **ImageReceiver**, and the video recording stream is the surface provided by **VideoRecorder**. 211 212**XComponent** 213 214```typescript 215mXComponentController: XComponentController = new XComponentController // Create an XComponentController. 216 217build() { 218 Flex() { 219 XComponent({ // Create an XComponent. 220 id: '', 221 type: 'surface', 222 libraryname: '', 223 controller: this.mXComponentController 224 }) 225 .onload(() => { // Set the onload callback. 226 // Set the surface width and height (1920 x 1080). For details about how to set the preview size, see the preview resolutions supported by the current device, which are obtained by previewProfilesArray. 227 this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080}) 228 // Obtain the surface ID. 229 globalThis.surfaceId = mXComponentController.getXComponentSurfaceId() 230 }) 231 .width('1920px') // Set the width of the XComponent. 232 .height('1080px') // Set the height of the XComponent. 233 } 234} 235``` 236 237**ImageReceiver** 238 239```typescript 240function getImageReceiverSurfaceId() { 241 let receiver = image.createImageReceiver(640, 480, 4, 8) 242 console.log(TAG + 'before ImageReceiver check') 243 if (receiver !== undefined) { 244 console.log('ImageReceiver is ok') 245 surfaceId1 = receiver.getReceivingSurfaceId() 246 console.log('ImageReceived id: ' + JSON.stringify(surfaceId1)) 247 } else { 248 console.log('ImageReceiver is not ok') 249 } 250 } 251``` 252 253**VideoRecorder** 254 255```typescript 256function getVideoRecorderSurface() { 257 await getFd('CameraManager.mp4'); 258 mVideoConfig.url = mFdPath; 259 media.createVideoRecorder((err, recorder) => { 260 console.info('Entering create video receiver') 261 mVideoRecorder = recorder 262 console.info('videoRecorder is :' + JSON.stringify(mVideoRecorder)) 263 console.info('videoRecorder.prepare called.') 264 mVideoRecorder.prepare(mVideoConfig, (err) => { 265 console.info('videoRecorder.prepare success.') 266 mVideoRecorder.getInputSurface((err, id) => { 267 console.info('getInputSurface called') 268 mVideoSurface = id 269 console.info('getInputSurface surfaceId: ' + JSON.stringify(mVideoSurface)) 270 }) 271 }) 272 }) 273 } 274``` 275 276#### Managing Sessions 277 278##### Creating a Session 279 280```typescript 281// Create a session. 282let captureSession 283try { 284 captureSession = cameraManager.createCaptureSession() 285} catch (error) { 286 console.error('Failed to create the CaptureSession instance. errorCode = ' + error.code); 287} 288 289// Listen for session errors. 290captureSession.on('error', (error) => { 291 console.log(`Capture session error code: ${error.code}`); 292}) 293 294// Start configuration for the session. 295try { 296 captureSession.beginConfig() 297} catch (error) { 298 console.error('Failed to beginConfig. errorCode = ' + error.code); 299} 300 301// Add the camera input stream to the session. 302try { 303 captureSession.addInput(cameraInput) 304} catch (error) { 305 console.error('Failed to addInput. errorCode = ' + error.code); 306} 307 308// Add the preview input stream to the session. 309try { 310 captureSession.addOutput(previewOutput) 311} catch (error) { 312 console.error('Failed to addOutput(previewOutput). errorCode = ' + error.code); 313} 314 315// Add the photographing output stream to the session. 316try { 317 captureSession.addOutput(photoOutput) 318} catch (error) { 319 console.error('Failed to addOutput(photoOutput). errorCode = ' + error.code); 320} 321 322// Commit the session configuration. 323await captureSession.commitConfig() 324 325// Start the session. 326await captureSession.start().then(() => { 327 console.log('Promise returned to indicate the session start success.'); 328}) 329``` 330 331##### Switching a Session 332 333```typescript 334// Stop the session. 335await captureSession.stop() 336 337// Start configuration for the session. 338try { 339 captureSession.beginConfig() 340} catch (error) { 341 console.error('Failed to beginConfig. errorCode = ' + error.code); 342} 343 344// Remove the photographing output stream from the session. 345try { 346 captureSession.removeOutput(photoOutput) 347} catch (error) { 348 console.error('Failed to removeOutput(photoOutput). errorCode = ' + error.code); 349} 350 351// Add a video recording output stream to the session. 352try { 353 captureSession.addOutput(videoOutput) 354} catch (error) { 355 console.error('Failed to addOutput(videoOutput). errorCode = ' + error.code); 356} 357 358// Commit the session configuration. 359await captureSession.commitConfig() 360 361// Start the session. 362await captureSession.start().then(() => { 363 console.log('Promise returned to indicate the session start success.'); 364}) 365``` 366 367#### Setting Parameters 368 369```typescript 370// Check whether the camera has flash. 371let flashStatus 372try { 373 flashStatus = captureSession.hasFlash() 374} catch (error) { 375 console.error('Failed to hasFlash. errorCode = ' + error.code); 376} 377console.log('Promise returned with the flash light support status:' + flashStatus); 378 379if (flashStatus) { 380 // Check whether the auto flash mode is supported. 381 let flashModeStatus 382 try { 383 let status = captureSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO) 384 flashModeStatus = status 385 } catch (error) { 386 console.error('Failed to check whether the flash mode is supported. errorCode = ' + error.code); 387 } 388 if(flashModeStatus) { 389 // Set the flash mode to auto. 390 try { 391 captureSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO) 392 } catch (error) { 393 console.error('Failed to set the flash mode. errorCode = ' + error.code); 394 } 395 } 396} 397 398// Check whether the continuous auto focus is supported. 399let focusModeStatus 400try { 401 let status = captureSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO) 402 focusModeStatus = status 403} catch (error) { 404 console.error('Failed to check whether the focus mode is supported. errorCode = ' + error.code); 405} 406 407if (focusModeStatus) { 408 // Set the focus mode to continuous auto focus. 409 try { 410 captureSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO) 411 } catch (error) { 412 console.error('Failed to set the focus mode. errorCode = ' + error.code); 413 } 414} 415 416// Obtain the zoom ratio range supported by the camera. 417let zoomRatioRange 418try { 419 zoomRatioRange = captureSession.getZoomRatioRange() 420} catch (error) { 421 console.error('Failed to get the zoom ratio range. errorCode = ' + error.code); 422} 423 424// Set a zoom ratio. 425try { 426 captureSession.setZoomRatio(zoomRatioRange[0]) 427} catch (error) { 428 console.error('Failed to set the zoom ratio value. errorCode = ' + error.code); 429} 430``` 431 432#### Taking Photos 433 434```typescript 435let settings = { 436 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the image quality to high. 437 rotation: camera.ImageRotation.ROTATION_0 // Set the image rotation angle to 0. 438} 439// Use the current photographing settings to take photos. 440photoOutput.capture(settings, async (err) => { 441 if (err) { 442 console.error('Failed to capture the photo ${err.message}'); 443 return; 444 } 445 console.log('Callback invoked to indicate the photo capture request success.'); 446}); 447``` 448 449#### Recording Videos 450 451```typescript 452// Start the video recording output stream. 453videoOutput.start(async (err) => { 454 if (err) { 455 console.error('Failed to start the video output ${err.message}'); 456 return; 457 } 458 console.log('Callback invoked to indicate the video output start success.'); 459}); 460 461// Start video recording. 462videoRecorder.start().then(() => { 463 console.info('videoRecorder start success'); 464} 465 466// Stop video recording. 467videoRecorder.stop().then(() => { 468 console.info('stop success'); 469} 470 471// Stop the video recording output stream. 472videoOutput.stop((err) => { 473 if (err) { 474 console.error('Failed to stop the video output ${err.message}'); 475 return; 476 } 477 console.log('Callback invoked to indicate the video output stop success.'); 478}); 479``` 480 481For details about the APIs used for saving photos, see [Image Processing](image.md#using-imagereceiver). 482 483#### Releasing Resources 484 485```typescript 486// Stop the session. 487captureSession.stop() 488 489// Release the camera input stream. 490cameraInput.close() 491 492// Release the preview output stream. 493previewOutput.release() 494 495// Release the photographing output stream. 496photoOutput.release() 497 498// Release the video recording output stream. 499videoOutput.release() 500 501// Release the session. 502captureSession.release() 503 504// Set the session to null. 505captureSession = null 506``` 507 508## Process Flowchart 509 510The following figure shows the process of using the camera. 511 512