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