1# Using AudioCapturer for Audio Recording (ArkTS) 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-audio-kit/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 14 15You can call **on('stateChange')** to listen for state changes. For details about each state, see [AudioState](../reference/apis-audio-kit/js-apis-audio.md#audiostate8). 16 17### How to Develop 18 191. Set audio recording parameters and create an **AudioCapturer** instance. For details about the parameters, see [AudioCapturerOptions](../reference/apis-audio-kit/js-apis-audio.md#audiocaptureroptions8). 20 21 ```ts 22 import audio from '@ohos.multimedia.audio'; 23 24 let audioStreamInfo: audio.AudioStreamInfo = { 25 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, 26 channels: audio.AudioChannel.CHANNEL_2, 27 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, 28 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW 29 }; 30 31 let audioCapturerInfo: audio.AudioCapturerInfo = { 32 source: audio.SourceType.SOURCE_TYPE_MIC, 33 capturerFlags: 0 34 }; 35 36 let audioCapturerOptions: audio.AudioCapturerOptions = { 37 streamInfo: audioStreamInfo, 38 capturerInfo: audioCapturerInfo 39 }; 40 41 audio.createAudioCapturer(audioCapturerOptions, (err, data) => { 42 if (err) { 43 console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); 44 } else { 45 console.info('Invoke createAudioCapturer succeeded.'); 46 let audioCapturer = data; 47 } 48 }); 49 ``` 50 512. Call **start()** to switch the AudioCapturer to the **running** state and start recording. 52 53 ```ts 54 import { BusinessError } from '@ohos.base'; 55 56 audioCapturer.start((err: BusinessError) => { 57 if (err) { 58 console.error(`Capturer start failed, code is ${err.code}, message is ${err.message}`); 59 } else { 60 console.info('Capturer start success.'); 61 } 62 }); 63 ``` 64 653. Specify the recording file path and call **read()** to read the data in the buffer. 66 67 ```ts 68 import fs from '@ohos.file.fs'; 69 70 let context = getContext(this); 71 async function read() { 72 let path = context.filesDir; 73 const filePath = path + '/voice_call_data.wav'; 74 let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 75 let bufferSize: number = await audioCapturer.getBufferSize(); 76 let buffer: ArrayBuffer = await audioCapturer.read(bufferSize, true); 77 fs.writeSync(file.fd, buffer); 78 } 79 ``` 80 814. Call **stop()** to stop recording. 82 83 ```ts 84 import { BusinessError } from '@ohos.base'; 85 86 audioCapturer.stop((err: BusinessError) => { 87 if (err) { 88 console.error(`Capturer stop failed, code is ${err.code}, message is ${err.message}`); 89 } else { 90 console.info('Capturer stopped.'); 91 } 92 }); 93 ``` 94 955. Call **release()** to release the instance. 96 97 ```ts 98 import { BusinessError } from '@ohos.base'; 99 100 audioCapturer.release((err: BusinessError) => { 101 if (err) { 102 console.error(`capturer release failed, code is ${err.code}, message is ${err.message}`); 103 } else { 104 console.info('capturer released.'); 105 } 106 }); 107 ``` 108 109 110### Sample Code 111 112Refer to the sample code below to record audio using AudioCapturer. 113 114```ts 115import audio from '@ohos.multimedia.audio'; 116import fs from '@ohos.file.fs'; 117 118const TAG = 'AudioCapturerDemo'; 119let context = getContext(this); 120 121let audioCapturer: audio.AudioCapturer | undefined = undefined; 122let audioStreamInfo: audio.AudioStreamInfo = { 123 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, 124 channels: audio.AudioChannel.CHANNEL_1, 125 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, 126 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW 127} 128let audioCapturerInfo: audio.AudioCapturerInfo = { 129 source: audio.SourceType.SOURCE_TYPE_MIC, // Audio source type. 130 capturerFlags: 0 // Flag indicating an AudioCapturer. 131} 132let audioCapturerOptions: audio.AudioCapturerOptions = { 133 streamInfo: audioStreamInfo, 134 capturerInfo: audioCapturerInfo 135} 136 137// Create an AudioCapturer instance, and set the events to listen for. 138async function init() { 139 audio.createAudioCapturer(audioCapturerOptions, (err, capturer) => { // Create an AudioCapturer instance. 140 if (err) { 141 console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); 142 return; 143 } 144 console.info(`${TAG}: create AudioCapturer success`); 145 audioCapturer = capturer; 146 if (audioCapturer !== undefined) { 147 (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. 148 if (position === 1000) { 149 console.info('ON Triggered successfully'); 150 } 151 }); 152 (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. 153 if (position === 2000) { 154 console.info('ON Triggered successfully'); 155 } 156 }); 157 } 158 }); 159} 160 161// Start audio recording. 162async function start() { 163 if (audioCapturer !== undefined) { 164 let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; 165 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. 166 console.error(`${TAG}: start failed`); 167 return; 168 } 169 await (audioCapturer as audio.AudioCapturer).start(); // Start recording. 170 const filePath = context.filesDir + '/test.wav'; // Path for storing the recorded audio file. 171 let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); // Create the file if it does not exist. 172 let fd = file.fd; 173 let numBuffersToCapture = 150; // Write data for 150 times. 174 let count = 0; 175 class Options { 176 offset: number = 0; 177 length: number = 0 178 } 179 while (numBuffersToCapture) { 180 let bufferSize = await (audioCapturer as audio.AudioCapturer).getBufferSize(); 181 let buffer = await (audioCapturer as audio.AudioCapturer).read(bufferSize, true); 182 let options: Options = { 183 offset: count * bufferSize, 184 length: bufferSize 185 }; 186 if (buffer === undefined) { 187 console.error(`${TAG}: read buffer failed`); 188 } else { 189 let number = fs.writeSync(fd, buffer, options); 190 console.info(`${TAG}: write date: ${number}`); 191 } 192 numBuffersToCapture--; 193 count++; 194 } 195 } 196} 197 198// Stop recording. 199async function stop() { 200 if (audioCapturer !== undefined) { 201 // The AudioCapturer can be stopped only when it is in the STATE_RUNNING or STATE_PAUSED state. 202 if ((audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_PAUSED) { 203 console.info('Capturer is not running or paused'); 204 return; 205 } 206 await (audioCapturer as audio.AudioCapturer).stop(); // Stop recording. 207 if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_STOPPED) { 208 console.info('Capturer stopped'); 209 } else { 210 console.error('Capturer stop failed'); 211 } 212 } 213} 214 215// Release the instance. 216async function release() { 217 if (audioCapturer !== undefined) { 218 // The AudioCapturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state. 219 if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED || (audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_NEW) { 220 console.info('Capturer already released'); 221 return; 222 } 223 await (audioCapturer as audio.AudioCapturer).release(); // Release resources. 224 if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED) { 225 console.info('Capturer released'); 226 } else { 227 console.error('Capturer release failed'); 228 } 229 } 230} 231``` 232