video-recorder.md 5.1 KB
Newer Older
W
wusongqing 已提交
1
# 视频录制开发指导
W
wusongqing 已提交
2

W
wusongqing 已提交
3
## 场景介绍
W
wusongqing 已提交
4

W
wusongqing 已提交
5
视频录制的主要工作是捕获音视频信号,完成音视频编码并保存到文件中,帮助开发者轻松实现音视频录制功能。它允许调用者指定录制的编码格式、封装格式、文件路径等参数。
W
wusongqing 已提交
6

W
wusongqing 已提交
7
**图1** 视频录制状态机
W
wusongqing 已提交
8

W
wusongqing 已提交
9
![zh-ch_image_video_recorder_state_machine](figures/zh-ch_image_video_recorder_state_machine.png)
W
wusongqing 已提交
10 11 12



W
wusongqing 已提交
13
**图2** 视频录制零层图
W
wusongqing 已提交
14

W
wusongqing 已提交
15
![zh-ch_image_video_recorder_zero](figures/zh-ch_image_video_recorder_zero.png)
W
wusongqing 已提交
16

W
wusongqing 已提交
17
## 开发步骤
W
wusongqing 已提交
18

Z
zengyawen 已提交
19
详细API含义可参考:[媒体服务API文档VideoRecorder](../reference/apis/js-apis-media.md)
W
wusongqing 已提交
20

W
wusongqing 已提交
21
### 全流程场景
W
wusongqing 已提交
22

23 24
端到端的开发示例请参考:https://gitee.com/openharmony/app_samples/tree/master/media

W
wusongqing 已提交
25
包含流程:创建实例,设置录制参数,录制视频,暂停录制,恢复录制,停止录制,释放资源等流程。
W
wusongqing 已提交
26 27

```js
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
import media from '@ohos.multimedia.media'
import mediaLibrary from '@ohos.multimedia.mediaLibrary'

let testFdNumber;

// pathName是传入的录制文件名,例如:01.mp4,生成后的文件地址:/storage/media/100/local/files/Movies/01.mp4
// 使用mediaLibrary需要添加以下权限, ohos.permission.MEDIA_LOCATION、ohos.permission.WRITE_MEDIA、ohos.permission.READ_MEDIA
async function getFd(pathName) {
    let displayName = pathName;
    const mediaTest = mediaLibrary.getMediaLibrary();
    let fileKeyObj = mediaLibrary.FileKey;
    let mediaType = mediaLibrary.MediaType.VIDEO;
    let publicPath = await mediaTest.getPublicDirectory(mediaLibrary.DirectoryType.DIR_VIDEO);
    let dataUri = await mediaTest.createAsset(mediaType, displayName, publicPath);
    if (dataUri != undefined) {
        let args = dataUri.id.toString();
        let fetchOp = {
            selections : fileKeyObj.ID + "=?",
            selectionArgs : [args],
        }
        let fetchFileResult = await mediaTest.getFileAssets(fetchOp);
        let fileAsset = await fetchFileResult.getAllObject();
        let fdNumber = await fileAsset[0].open('Rw');
        fdNumber = "fd://" + fdNumber.toString();
        testFdNumber = fdNumber;
    }
}

await getFd('01.mp4');

W
wusongqing 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
let videoProfile = {
    audioBitrate : 48000,
    audioChannels : 2,
    audioCodec : 'audio/mp4a-latm',
    audioSampleRate : 48000,
    fileFormat : 'mp4',
    videoBitrate : 48000,
    videoCodec : 'video/mp4v-es',
    videoFrameWidth : 640,
    videoFrameHeight : 480,
    videoFrameRate : 30
}

let videoConfig = {
    audioSourceType : 1,
    videoSourceType : 0,
    profile : videoProfile,
75
    url : testFdNumber, // testFdNumber由getFd生成
W
wusongqing 已提交
76 77 78 79
    orientationHint : 0,
    location : { latitude : 30, longitude : 130 },
}
	
W
wusongqing 已提交
80
// 当发生错误上上报的错误回调接口
W
wusongqing 已提交
81 82 83 84 85 86
function failureCallback(error) {
    console.info('error happened, error name is ' + error.name);
    console.info('error happened, error code is ' + error.code);
    console.info('error happened, error message is ' + error.message);
}
	
W
wusongqing 已提交
87
// 当发生异常时,系统调用的错误回调接口
W
wusongqing 已提交
88 89 90 91 92 93
function catchCallback(error) {
    console.info('catch error happened, error name is ' + error.name);
    console.info('catch error happened, error code is ' + error.code);
    console.info('catch error happened, error message is ' + error.message);
}
	
W
wusongqing 已提交
94 95
let videoRecorder = null; // videoRecorder空对象在createVideoRecorder成功后赋值
let surfaceID = null; // 用于保存getInputSurface返回的surfaceID
96

W
wusongqing 已提交
97
// 创建videoRecorder对象
W
wusongqing 已提交
98 99 100 101 102 103 104 105 106 107
await media.createVideoRecorder().then((recorder) => {
    console.info('case createVideoRecorder called');
    if (typeof (recorder) != 'undefined') {
        videoRecorder = recorder;
        console.info('createVideoRecorder success');
    } else {
        console.info('createVideoRecorder failed');
    }
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
108
// 获取surfaceID并保存下来传递给camera相关接口
W
wusongqing 已提交
109 110 111 112 113
await videoRecorder.getInputSurface().then((surface) => {
    console.info('getInputSurface success');
    surfaceID = surface;
}, failureCallback).catch(catchCallback);
	
W
wusongqing 已提交
114
// 视频录制依赖相机相关接口,以下需要先调用相机起流接口后才能继续执行
W
wusongqing 已提交
115

W
wusongqing 已提交
116
// 视频录制启动接口
W
wusongqing 已提交
117 118 119 120
await videoRecorder.start().then(() => {
    console.info('start success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
121
// 调用pause接口时需要暂停camera出流
W
wusongqing 已提交
122 123 124 125
await videoRecorder.pause().then(() => {
    console.info('pause success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
126
// 调用resume接口时需要恢复camera出流
W
wusongqing 已提交
127 128 129 130
await videoRecorder.resume().then(() => {
    console.info('resume success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
131
// 停止camera出流后,停止视频录制
W
wusongqing 已提交
132 133 134 135
await videoRecorder.stop().then(() => {
    console.info('stop success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
136
// 重置录制相关配置
W
wusongqing 已提交
137 138 139 140
await videoRecorder.reset().then(() => {
    console.info('reset success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
141
// 释放视频录制相关资源并释放camera对象相关资源
W
wusongqing 已提交
142 143 144 145
await videoRecorder.release().then(() => {
    console.info('release success');
}, failureCallback).catch(catchCallback);

W
wusongqing 已提交
146
// 相关对象置null
W
wusongqing 已提交
147 148 149
videoRecorder = null;
surfaceID = null;
```
W
wusongqing 已提交
150