Before developing a camera application, you must request required permissions.
A camera application invokes and controls a camera device to perform basic operations such as preview, photo capture, and video recording.
Video recording is also one of the most important features of a camera app. Recording is the capture of cyclic frames. For custom recording configurations, refer to step 4 in Photo Capture to set parameters such as resolution, flash, focal length, photo quality, and rotation angle.
For detailed API descriptions, see @ohos.multimedia.camera (Camera Management).
Import the media module.
Creating the SurfaceId for the recording output stream and the recording output data requires the media APIs provided by the system, that is, @ohos.multimedia.media (Media Service). The following shows how to import the media APIs.
import { BusinessError } from '@kit.BasicServicesKit';
import { camera } from '@kit.CameraKit';
import { media } from '@kit.MediaKit'; Create a surface.
Call createAVRecorder() of the media module to create an AVRecorder instance, and call getInputSurface of the instance to obtain the surface ID, which is associated with the video output stream to process the stream data.
this.avRecorder = await this.createAVRecorder();
if (this.avRecorder === undefined) {
Logger.error(TAG, 'Failed to create the avRecorder.');
return;
}
await this.prepareAVRecorder();
let videoSurfaceId = await this.avRecorder.getInputSurface(); Create a video output stream.
Obtain the video output streams supported by the current device from videoProfiles in CameraOutputCapability. Then, define video recording parameters and use createVideoOutput to create a video output stream.
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.
Before setting the resolution width and height of the preview output stream, call AVRecorderProfile to obtain the configurable width and height range for video frames.
To obtain the video rotation angle (specified by rotation), call getVideoRotation in VideoOutput.
To configure the frame rate for a video output stream, select a suitable videoProfile from videoProfiles of CameraOutputCapability. Ensure that frameRateRange of the selected VideoProfile meets your service requirements.
createVideoOutputFn(cameraManager: camera.CameraManager, videoProfileObj: camera.VideoProfile,
surfaceId: string): camera.VideoOutput | undefined {
let videoOutput: camera.VideoOutput | undefined = undefined;
try {
videoOutput = cameraManager.createVideoOutput(videoProfileObj, surfaceId);
Logger.info(TAG, `createVideoOutputFn success: ${videoOutput}`);
} catch (error) {
let err = error as BusinessError;
Logger.error(TAG, `createVideoOutputFn failed: ${err.code}`);
}
return videoOutput;
} Start video recording.
Before setting the preview stream frame rate, call getActiveFrameRate to query the frame rate of the current recording stream.
If a frame rate range has been set for the recording stream, the preview stream frame rate must be set to the same range.
If a fixed frame rate has been set for the recording stream, the preview stream frame rate must be set to a divisor of the recording frame rate and must also be a fixed frame rate.
On some devices, if the front camera recording resolution is set to 3280*2160, the video may appear upside down in recording mode. It is recommended that you call setVideoStabilizationMode after commitConfig to avoid this issue.
Call start of the VideoOutput instance to start the video output stream, and then call start of the AVRecorder instance to start recording.
async startVideo(): Promise<void> {
Logger.info(TAG, 'startVideo is called');
try {
await this.videoOutput?.start();
await this.avRecorder?.start();
this.isRecording = true;
} catch (error) {
let err = error as BusinessError;
Logger.error(TAG, `startVideo err: ${err.code}`);
}
Logger.info(TAG, 'startVideo End of call');
} Stop video recording.
Call stop of the AVRecorder instance to stop recording, and then call stop of the VideoOutput instance to stop the video output stream.
async stopVideo(): Promise<void> {
Logger.info(TAG, 'stopVideo is called');
if (!this.isRecording) {
Logger.info(TAG, 'not in recording');
return;
}
try {
if (this.avRecorder) {
await this.avRecorder.stop();
}
if (this.videoOutput) {
await this.videoOutput.stop();
}
this.isRecording = false;
} catch (error) {
let err = error as BusinessError;
Logger.error(TAG, `stopVideo err: ${err.code}`);
}
Logger.info(TAG, 'stopVideo End of call');
} During camera application development, you can listen for the status of the video output stream, including recording start, recording end, and video output errors.
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. The recording is considered to have started when this event is triggered.
videoOutput.on('frameStart', (err: BusinessError) => {
if (err !== undefined && err.code !== 0) {
return;
}
console.info('Video frame started');
}); 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. The recording stream is considered to have ended when this event is triggered.
videoOutput.on('frameEnd', (err: BusinessError) => {
if (err !== undefined && err.code !== 0) {
return;
}
console.info('Video frame ended');
}); Register a fixed error callback to listen for recording output errors. The callback returns the error code corresponding to the error that occurs when the recording output API is used. For details about the error code types, see CameraErrorCode.
videoOutput.on('error', (error: BusinessError) => {
console.error(`Video output error code: ${error.code}`);
});