• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using AudioCapturer for Audio Recording
2
3The AudioCapturer is used to record Pulse Code Modulation (PCM) audio data. It is suitable if you have extensive audio development experience and want to implement more flexible recording features.
4
5## Development Guidelines
6
7The full recording process involves creating an **AudioCapturer** instance, configuring audio recording parameters, starting and stopping recording, and releasing the instance. In this topic, you will learn how to use the AudioCapturer to recording audio data. Before the development, you are advised to read [AudioCapturer](../reference/apis/js-apis-audio.md#audiocapturer8) for the API reference.
8
9The figure below shows the state changes of the AudioCapturer. After an **AudioCapturer** instance is created, different APIs can be called to switch the AudioCapturer to different states and trigger the required behavior. If an API is called when the AudioCapturer is not in the given state, the system may throw an exception or generate other undefined behavior. Therefore, you are advised to check the AudioCapturer state before triggering state transition.
10
11**Figure 1** AudioCapturer state transition
12![AudioCapturer state change](figures/audiocapturer-status-change.png)
13
14You can call **on('stateChange')** to listen for state changes. For details about each state, see [AudioState](../reference/apis/js-apis-audio.md#audiostate8).
15
16### How to Develop
17
181. Set audio recording parameters and create an **AudioCapturer** instance. For details about the parameters, see [AudioCapturerOptions](../reference/apis/js-apis-audio.md#audiocaptureroptions8).
19
20   ```ts
21   import audio from '@ohos.multimedia.audio';
22
23   let audioStreamInfo: audio.AudioStreamInfo = {
24     samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
25     channels: audio.AudioChannel.CHANNEL_2,
26     sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
27     encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
28   };
29
30   let audioCapturerInfo: audio.AudioCapturerInfo = {
31     source: audio.SourceType.SOURCE_TYPE_MIC,
32     capturerFlags: 0
33   };
34
35   let audioCapturerOptions: audio.AudioCapturerOptions = {
36     streamInfo: audioStreamInfo,
37     capturerInfo: audioCapturerInfo
38   };
39
40   audio.createAudioCapturer(audioCapturerOptions, (err, data) => {
41     if (err) {
42       console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`);
43     } else {
44       console.info('Invoke createAudioCapturer succeeded.');
45       let audioCapturer = data;
46     }
47   });
48   ```
49
502. Call **start()** to switch the AudioCapturer to the **running** state and start recording.
51
52   ```ts
53   audioCapturer.start((err: BusinessError) => {
54     if (err) {
55       console.error(`Capturer start failed, code is ${err.code}, message is ${err.message}`);
56     } else {
57       console.info('Capturer start success.');
58     }
59   });
60   ```
61
623. Specify the recording file path and call **read()** to read the data in the buffer.
63
64   ```ts
65   import fs from '@ohos.file.fs';
66
67   let context = getContext(this);
68   async function read() {
69     let path = context.filesDir;
70     const filePath = path + '/voice_call_data.wav';
71     let file: fs.File = fs.openSync(filePath, 0o2 | 0o100);
72     let bufferSize: number = await audioCapturer.getBufferSize();
73     let buffer: ArrayBuffer = await audioCapturer.read(bufferSize, true);
74     fs.writeSync(file.fd, buffer);
75   }
76   ```
77
784. Call **stop()** to stop recording.
79
80   ```ts
81   audioCapturer.stop((err: BusinessError) => {
82     if (err) {
83       console.error(`Capturer stop failed, code is ${err.code}, message is ${err.message}`);
84     } else {
85       console.info('Capturer stopped.');
86     }
87   });
88   ```
89
905. Call **release()** to release the instance.
91
92   ```ts
93   audioCapturer.release((err: BusinessError) => {
94     if (err) {
95       console.error(`capturer release failed, code is ${err.code}, message is ${err.message}`);
96     } else {
97       console.info('capturer released.');
98     }
99   });
100   ```
101
102
103### Sample Code
104
105Refer to the sample code below to record audio using AudioCapturer.
106
107```ts
108import audio from '@ohos.multimedia.audio';
109import fs from '@ohos.file.fs';
110
111const TAG = 'AudioCapturerDemo';
112let context = getContext(this);
113
114let audioCapturer: audio.AudioCapturer | undefined = undefined;
115let audioStreamInfo: audio.AudioStreamInfo = {
116  samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
117  channels: audio.AudioChannel.CHANNEL_1,
118  sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
119  encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
120}
121let audioCapturerInfo: audio.AudioCapturerInfo = {
122  source: audio.SourceType.SOURCE_TYPE_MIC, // Audio source type.
123  capturerFlags: 0 // Flag indicating an AudioCapturer.
124}
125let audioCapturerOptions: audio.AudioCapturerOptions = {
126  streamInfo: audioStreamInfo,
127  capturerInfo: audioCapturerInfo
128}
129
130// Create an AudioCapturer instance, and set the events to listen for.
131async function init() {
132  audio.createAudioCapturer(audioCapturerOptions, (err, capturer) => { // Create an AudioCapturer instance.
133    if (err) {
134      console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`);
135      return;
136    }
137    console.info(`${TAG}: create AudioCapturer success`);
138    audioCapturer = capturer;
139    if (audioCapturer !== undefined) {
140      (audioCapturer as audio.AudioCapturer).on('markReach', 1000, (position: number) => { // Subscribe to the markReach event. A callback is triggered when the number of captured frames reaches 1000.
141        if (position === 1000) {
142          console.info('ON Triggered successfully');
143        }
144      });
145      (audioCapturer as audio.AudioCapturer).on('periodReach', 2000, (position: number) => { // Subscribe to the periodReach event. A callback is triggered when the number of captured frames reaches 2000.
146        if (position === 2000) {
147          console.info('ON Triggered successfully');
148        }
149      });
150    }
151  });
152}
153
154// Start audio recording.
155async function start() {
156  if (audioCapturer !== undefined) {
157    let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED];
158    if (stateGroup.indexOf((audioCapturer as audio.AudioCapturer).state.valueOf()) === -1) { // Recording can be started only when the AudioCapturer is in the STATE_PREPARED, STATE_PAUSED, or STATE_STOPPED state.
159      console.error(`${TAG}: start failed`);
160      return;
161    }
162    await (audioCapturer as audio.AudioCapturer).start(); // Start recording.
163    const path = context.filesDir + '/test.wav'; // Path for storing the recorded audio file.
164    let file = fs.openSync(path, 0o2 | 0o100); // Create the file if it does not exist.
165    let fd = file.fd;
166    let numBuffersToCapture = 150; // Write data for 150 times.
167    let count = 0;
168    class Options {
169      offset: number = 0;
170      length: number = 0
171    }
172    while (numBuffersToCapture) {
173      let bufferSize = await (audioCapturer as audio.AudioCapturer).getBufferSize();
174      let buffer = await (audioCapturer as audio.AudioCapturer).read(bufferSize, true);
175      let options: Options = {
176        offset: count * bufferSize,
177        length: bufferSize
178      };
179      if (buffer === undefined) {
180        console.error(`${TAG}: read buffer failed`);
181      } else {
182        let number = fs.writeSync(fd, buffer, options);
183        console.info(`${TAG}: write date: ${number}`);
184      }
185      numBuffersToCapture--;
186      count++;
187    }
188  }
189}
190
191// Stop recording.
192async function stop() {
193  if (audioCapturer !== undefined) {
194    // The AudioCapturer can be stopped only when it is in the STATE_RUNNING or STATE_PAUSED state.
195    if ((audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_PAUSED) {
196      console.info('Capturer is not running or paused');
197      return;
198    }
199    await (audioCapturer as audio.AudioCapturer).stop(); // Stop recording.
200    if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_STOPPED) {
201       console.info('Capturer stopped');
202    } else {
203       console.error('Capturer stop failed');
204    }
205  }
206}
207
208// Release the instance.
209async function release() {
210  if (audioCapturer !== undefined) {
211    // The AudioCapturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state.
212    if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED || (audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_NEW) {
213      console.info('Capturer already released');
214      return;
215    }
216    await (audioCapturer as audio.AudioCapturer).release(); // Release resources.
217    if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED) {
218      console.info('Capturer released');
219    } else {
220      console.error('Capturer release failed');
221    }
222  }
223}
224```
225