1# 使用AVScreenCaptureRecorder录屏写文件(ArkTS) 2 3屏幕录制主要为主屏幕录屏功能。 4 5开发者可以调用录屏([AVScreenCaptureRecorder](media-kit-intro.md#avscreencapture))模块的ArkTs接口,完成屏幕录制,采集设备内、麦克风等的音视频源数据。可以调用录屏模块获取音视频文件,然后通过文件的形式流转到其他模块进行播放或处理,达成文件形式分享屏幕内容的场景。 6 7录屏模块和窗口(Window)、图形(Graphic)等模块协同完成整个视频采集的流程。 8 9使用AVScreenCaptureRecorder录制屏幕涉及到AVScreenCaptureRecorder实例的创建、音视频采集参数的配置、采集的开始与停止、资源的释放等。 10 11开始屏幕录制时正在通话中或者屏幕录制过程中来电,录屏将自动停止。因通话中断的录屏会上报SCREENCAPTURE_STATE_STOPPED_BY_CALL状态。 12 13本开发指导将以完成一次屏幕数据录制的过程为例,向开发者讲解如何使用AVScreenCaptureRecorder进行屏幕录制,详细的API声明请参考[AVScreenCaptureRecoder API参考](../../reference/apis-media-kit/js-apis-media.md#avscreencapturerecorder12)。 14 15如果配置了采集麦克风音频数据,需对应配置麦克风权限ohos.permission.MICROPHONE和申请长时任务,配置方式请参见[向用户申请权限](../../security/AccessToken/request-user-authorization.md)、[申请长时任务](../../task-management/continuous-task.md)。 16 17## 申请权限 18 19在开发此功能前,开发者应根据实际需求申请相关权限: 20 21- 当需要使用麦克风时,需要申请**ohos.permission.MICROPHONE**麦克风权限。申请方式请参考:[向用户申请授权](../../security/AccessToken/request-user-authorization.md)。 22- 当需要读取图片或视频文件时,请优先使用媒体库[Picker选择媒体资源](../medialibrary/photoAccessHelper-photoviewpicker.md)。 23- 当需要保存图片或视频文件时,请优先使用[安全控件保存媒体资源](../medialibrary/photoAccessHelper-savebutton.md)。 24 25> **说明:** 26> 27> 仅应用需要克隆、备份或同步用户公共目录的图片、视频类文件时,可申请ohos.permission.READ_IMAGEVIDEO、ohos.permission.WRITE_IMAGEVIDEO权限来读写音频文件,申请方式请参考<!--RP1-->[申请受控权限](../../security/AccessToken/declare-permissions-in-acl.md)<!--RP1End-->。 28 29## 开发步骤及注意事项 30 31使用AVScreenCaptureRecorder时要明确其状态的变化,在创建实例后,调用对应的方法可以进入指定的状态实现对应的行为。在确定的状态下执行不合适的方法会导致AVScreenCaptureRecorder发生错误,开发者需要在调用状态转换的方法前进行状态检查,避免程序运行异常。 32 331. 添加头文件。 34 35 ```javascript 36 import media from '@ohos.multimedia.media'; 37 ``` 38 392. 创建AVScreenCaptureRecorder类型的成员变量screenCapture。 40 41 ```javascript 42 // 声明一个AVScreenCaptureRecorder类型的变量 43 private screenCapture?: media.AVScreenCaptureRecorder; 44 // 创建一个AVScreenCaptureRecorder,并赋值给screenCapture成员变量 45 this.screenCapture = await media.createAVScreenCaptureRecorder(); 46 ``` 47 483. 对成员变量screenCapture设置监听函数,分别监听不同状态和异常情况。 49 50 ```javascript 51 this.screenCapture.on('stateChange', async (infoType: media.AVScreenCaptureStateCode) => { 52 switch (infoType) { 53 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STARTED: 54 console.info("录屏成功开始后会收到的回调"); 55 break; 56 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_CANCELED: 57 this.screenCapture?.release(); 58 this.screenCapture = undefined; 59 console.info("不允许使用录屏功能"); 60 break; 61 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER: 62 this.screenCapture?.release(); 63 this.screenCapture = undefined; 64 console.info("通过录屏胶囊结束录屏,底层录制会停止"); 65 break; 66 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_INTERRUPTED_BY_OTHER: 67 console.info("录屏因其他中断而停止,底层录制会停止"); 68 break; 69 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_CALL: 70 console.info("录屏过程因通话中断,底层录制会停止"); 71 break; 72 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNAVAILABLE: 73 console.info("录屏麦克风不可用"); 74 break; 75 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_MUTED_BY_USER: 76 console.info("录屏麦克风被用户静音"); 77 break; 78 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNMUTED_BY_USER: 79 console.info("录屏麦克风被用户取消静音"); 80 break; 81 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_ENTER_PRIVATE_SCENE: 82 // 目前可以从系统直接注册监听到进入隐私场景 83 console.info("录屏进入隐私场景"); 84 break; 85 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_EXIT_PRIVATE_SCENE: 86 console.info("录屏退出隐私场景"); 87 break; 88 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER_SWITCHES: 89 console.info("用户账号切换,底层录制会停止"); 90 break; 91 default: 92 break; 93 } 94 }) 95 this.screenCapture.on('error', (err) => { 96 console.info("处理异常情况"); 97 }) 98 ``` 99 1004. 配置屏幕录制参数。 101 102 创建AVScreenCaptureRecorder实例screenCapture后,可以设置屏幕录制所需要的参数。 103 104 参数videoBitrate、audioSampleRate、audioChannelCount、audioBitrate、preset为可选参数,若不设置则可按默认值进行设置,如下示例中提供了可选参数的默认值。麦克风和系统音的音频流共用一套音频参数,分别是音频采样率、音频通道数和音频比特率,对应audioSampleRate、audioChannelCount和audioBitrate参数。 105 106 ```javascript 107 captureConfig: media.AVScreenCaptureRecordConfig = { 108 // 开发者可以根据自身的需要设置宽高 109 frameWidth: 768, 110 frameHeight: 1280, 111 // 参考应用文件访问与管理开发示例新建并读写一个文件fd 112 fd: 0, 113 // 可选参数及其默认值 114 videoBitrate: 10000000, 115 audioSampleRate: 48000, 116 audioChannelCount: 2, 117 audioBitrate: 96000, 118 preset: media.AVScreenCaptureRecordPreset.SCREEN_RECORD_PRESET_H264_AAC_MP4 119 }; 120 ``` 121 1225. 基于预先配置的屏幕录制参数,调用init()方法初始化screenCapture。 123 124 ```javascript 125 await this.screenCapture.init(this.captureConfig); 126 ``` 127 1286. 创建豁免隐私窗口,这里填写的是子窗口id和主窗口id,具体开发步骤可参见[窗口API](../../reference/apis-arkui/js-apis-window.md#windowproperties) 129 130 ```javascript 131 let windowIDs = [57, 86]; 132 await screenCapture.skipPrivacyMode(windowIDs); 133 ``` 134 1357. 调用startRecording()方法开始进行屏幕录制,并通过监听函数监听状态。 136 137 ```javascript 138 await this.screenCapture.startRecording(); 139 ``` 140 1418. 停止录屏。 142 143 - 点击录屏胶囊中的结束按钮停止录制:基于回调函数实现,录屏对象实例screenCapture会触发SCREENCAPTURE_STATE_STOPPED_BY_USER的回调,通知应用此次录屏已停止,不需要开发者主动调用stopRecording()方法。 144 145 - 应用主动调用stopRecording()方法,停止录屏。 146 147 ```javascript 148 await this.screenCapture.stopRecording(); 149 ``` 150 1519. 调用release()方法销毁实例,释放资源。 152 153 ```javascript 154 await this.screenCapture.release(); 155 ``` 156 157## 完整示例 158 159下面展示了使用AVScreenCaptureRecorder屏幕录屏存文件的完整示例代码。 160 161```javascript 162import media from '@ohos.multimedia.media'; 163 164export class AVScreenCaptureDemo { 165 private screenCapture?: media.AVScreenCaptureRecorder; 166 captureConfig: media.AVScreenCaptureRecordConfig = { 167 // 开发者可以根据自身的需要设置宽高 168 frameWidth: 768, 169 frameHeight: 1280, 170 // 参考应用文件访问与管理开发示例新建并读写一个文件fd 171 fd: 0, 172 // 可选参数及其默认值 173 videoBitrate: 10000000, 174 audioSampleRate: 48000, 175 audioChannelCount: 2, 176 audioBitrate: 96000, 177 preset: media.AVScreenCaptureRecordPreset.SCREEN_RECORD_PRESET_H264_AAC_MP4 178 }; 179 180 // 调用startRecording方法可以开始一次录屏存文件的流程,结束录屏可以通过点击录屏胶囊停止按钮进行操作。 181 public async startRecording() { 182 this.screenCapture = await media.createAVScreenCaptureRecorder(); 183 if (this.screenCapture != undefined) { 184 // success 185 } else { 186 // failed 187 return; 188 } 189 this.screenCapture?.on('stateChange', async (infoType: media.AVScreenCaptureStateCode) => { 190 switch (infoType) { 191 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STARTED: 192 console.info("录屏成功开始后会收到的回调"); 193 break; 194 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_CANCELED: 195 this.screenCapture?.release(); 196 this.screenCapture = undefined; 197 console.info("不允许使用录屏功能"); 198 break; 199 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER: 200 this.screenCapture?.release(); 201 this.screenCapture = undefined; 202 console.info("通过录屏胶囊结束录屏,底层录制会停止"); 203 break; 204 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_INTERRUPTED_BY_OTHER: 205 console.info("录屏因其他中断而停止,底层录制会停止"); 206 break; 207 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_CALL: 208 console.info("录屏过程因通话中断,底层录制会停止"); 209 break; 210 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNAVAILABLE: 211 console.info("录屏麦克风不可用"); 212 break; 213 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_MUTED_BY_USER: 214 console.info("录屏麦克风被用户静音"); 215 break; 216 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNMUTED_BY_USER: 217 console.info("录屏麦克风被用户取消静音"); 218 break; 219 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_ENTER_PRIVATE_SCENE: 220 // 目前可以从系统直接注册监听到进入隐私场景 221 console.info("录屏进入隐私场景"); 222 break; 223 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_EXIT_PRIVATE_SCENE: 224 console.info("录屏退出隐私场景"); 225 break; 226 case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER_SWITCHES: 227 console.info("用户账号切换,底层录制会停止"); 228 break; 229 default: 230 break; 231 } 232 }) 233 this.screenCapture?.on('error', (err) => { 234 console.info("处理异常情况"); 235 }) 236 await this.screenCapture?.init(this.captureConfig); 237 238 // 豁免隐私窗口 239 let windowIDs = [57, 86]; 240 await this.screenCapture?.skipPrivacyMode(windowIDs); 241 242 await this.screenCapture?.startRecording(); 243 } 244 245 // 可以主动调用stopRecording方法来停止录屏。 246 public async stopRecording() { 247 if (this.screenCapture == undefined) { 248 // Error 249 return; 250 } 251 await this.screenCapture?.stopRecording(); 252 253 // 调用release()方法销毁实例,释放资源。 254 await this.screenCapture?.release(); 255 256 // 最后需要关闭创建的录屏文件fd, fs.close(fd); 257 } 258} 259```