• 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 = {
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 = {
31     source: audio.SourceType.SOURCE_TYPE_MIC,
32     capturerFlags: 0
33   };
34
35   let 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) => {
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   let file = fs.openSync(path, 0o2 | 0o100);
66   let bufferSize = await audioCapturer.getBufferSize();
67   let buffer = await audioCapturer.read(bufferSize, true);
68   fs.writeSync(file.fd, buffer);
69   ```
70
714. Call **stop()** to stop recording.
72
73   ```ts
74   audioCapturer.stop((err) => {
75     if (err) {
76       console.error(`Capturer stop failed, code is ${err.code}, message is ${err.message}`);
77     } else {
78       console.info('Capturer stopped.');
79     }
80   });
81   ```
82
835. Call **release()** to release the instance.
84
85   ```ts
86   audioCapturer.release((err) => {
87     if (err) {
88       console.error(`capturer release failed, code is ${err.code}, message is ${err.message}`);
89     } else {
90       console.info('capturer released.');
91     }
92   });
93   ```
94
95
96### Sample Code
97
98Refer to the sample code below to record audio using AudioCapturer.
99
100```ts
101import audio from '@ohos.multimedia.audio';
102import fs from '@ohos.file.fs';
103
104const TAG = 'AudioCapturerDemo';
105
106export default class AudioCapturerDemo {
107  private audioCapturer = undefined;
108  private audioStreamInfo = {
109    samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
110    channels: audio.AudioChannel.CHANNEL_1,
111    sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
112    encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
113  }
114  private audioCapturerInfo = {
115    source: audio.SourceType.SOURCE_TYPE_MIC, // Audio source type.
116    capturerFlags: 0 // Flag indicating an AudioCapturer.
117  }
118  private audioCapturerOptions = {
119    streamInfo: this.audioStreamInfo,
120    capturerInfo: this.audioCapturerInfo
121  }
122
123  // Create an AudioCapturer instance, and set the events to listen for.
124  init() {
125    audio.createAudioCapturer(this.audioCapturerOptions, (err, capturer) => { // Create an AudioCapturer instance.
126      if (err) {
127        console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`);
128        return;
129      }
130
131      console.info(`${TAG}: create AudioCapturer success`);
132      this.audioCapturer = capturer;
133      this.audioCapturer.on('markReach', 1000, (position) => { // Subscribe to the markReach event. A callback is triggered when the number of captured frames reaches 1000.
134        if (position === 1000) {
135          console.info('ON Triggered successfully');
136        }
137      });
138      this.audioCapturer.on('periodReach', 2000, (position) => { // Subscribe to the periodReach event. A callback is triggered when the number of captured frames reaches 2000.
139        if (position === 2000) {
140          console.info('ON Triggered successfully');
141        }
142      });
143
144    });
145  }
146
147  // Start audio recording.
148  async start() {
149    let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED];
150    if (stateGroup.indexOf(this.audioCapturer.state) === -1) { // Recording can be started only when the AudioCapturer is in the STATE_PREPARED, STATE_PAUSED, or STATE_STOPPED state.
151      console.error(`${TAG}: start failed`);
152      return;
153    }
154    await this.audioCapturer.start(); // Start recording.
155
156    let context = getContext(this);
157    const path = context.filesDir + '/test.wav'; // Path for storing the recorded audio file.
158
159    let file = fs.openSync(path, 0o2 | 0o100); // Create the file if it does not exist.
160    let fd = file.fd;
161    let numBuffersToCapture = 150; // Write data for 150 times.
162    let count = 0;
163    while (numBuffersToCapture) {
164      let bufferSize = await this.audioCapturer.getBufferSize();
165      let buffer = await this.audioCapturer.read(bufferSize, true);
166      let options = {
167        offset: count * bufferSize,
168        length: bufferSize
169      };
170      if (buffer === undefined) {
171        console.error(`${TAG}: read buffer failed`);
172      } else {
173        let number = fs.writeSync(fd, buffer, options);
174        console.info(`${TAG}: write date: ${number}`);
175      }
176      numBuffersToCapture--;
177      count++;
178    }
179  }
180
181  // Stop recording.
182  async stop() {
183    // The AudioCapturer can be stopped only when it is in the STATE_RUNNING or STATE_PAUSED state.
184    if (this.audioCapturer.state !== audio.AudioState.STATE_RUNNING && this.audioCapturer.state !== audio.AudioState.STATE_PAUSED) {
185      console.info('Capturer is not running or paused');
186      return;
187    }
188    await this.audioCapturer.stop(); // Stop recording.
189    if (this.audioCapturer.state === audio.AudioState.STATE_STOPPED) {
190      console.info('Capturer stopped');
191    } else {
192      console.error('Capturer stop failed');
193    }
194  }
195
196  // Release the instance.
197  async release() {
198    // The AudioCapturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state.
199    if (this.audioCapturer.state === audio.AudioState.STATE_RELEASED || this.audioCapturer.state === audio.AudioState.STATE_NEW) {
200      console.info('Capturer already released');
201      return;
202    }
203    await this.audioCapturer.release(); // Release the instance.
204    if (this.audioCapturer.state == audio.AudioState.STATE_RELEASED) {
205      console.info('Capturer released');
206    } else {
207      console.error('Capturer release failed');
208    }
209  }
210}
211```
212