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_IMAGEVIDEOohos.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```