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 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