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-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 of the AudioCapturer. 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 > **NOTE** 22 > 23 > In the case of the microphone audio source (when **SourceType** is set to **SOURCE_TYPE_MIC**), you must request the **ohos.permission.MICROPHONE** permission. For details, see [Requesting User Authorization](../../security/AccessToken/request-user-authorization.md). 24 25 ```ts 26 import { audio } from '@kit.AudioKit'; 27 28 let audioStreamInfo: audio.AudioStreamInfo = { 29 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Sampling rate. 30 channels: audio.AudioChannel.CHANNEL_2, // Channel. 31 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Sampling format. 32 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Encoding format. 33 }; 34 35 let audioCapturerInfo: audio.AudioCapturerInfo = { 36 source: audio.SourceType.SOURCE_TYPE_MIC, 37 capturerFlags: 0 38 }; 39 40 let audioCapturerOptions: audio.AudioCapturerOptions = { 41 streamInfo: audioStreamInfo, 42 capturerInfo: audioCapturerInfo 43 }; 44 45 audio.createAudioCapturer(audioCapturerOptions, (err, data) => { 46 if (err) { 47 console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); 48 } else { 49 console.info('Invoke createAudioCapturer succeeded.'); 50 let audioCapturer = data; 51 } 52 }); 53 ``` 54 552. Call **on('readData')** to subscribe to the audio data read callback. 56 57 ```ts 58 import { BusinessError } from '@kit.BasicServicesKit'; 59 import { fileIo } from '@kit.CoreFileKit'; 60 61 let bufferSize: number = 0; 62 class Options { 63 offset?: number; 64 length?: number; 65 } 66 67 let path = getContext().cacheDir; 68 let filePath = path + '/StarWars10s-2C-48000-4SW.wav'; 69 let file: fileIo.File = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); 70 71 let readDataCallback = (buffer: ArrayBuffer) => { 72 let options: Options = { 73 offset: bufferSize, 74 length: buffer.byteLength 75 } 76 fileIo.writeSync(file.fd, buffer, options); 77 bufferSize += buffer.byteLength; 78 } 79 audioCapturer.on('readData', readDataCallback); 80 ``` 81 823. Call **start()** to switch the AudioCapturer to the **running** state and start recording. 83 84 ```ts 85 import { BusinessError } from '@kit.BasicServicesKit'; 86 87 audioCapturer.start((err: BusinessError) => { 88 if (err) { 89 console.error(`Capturer start failed, code is ${err.code}, message is ${err.message}`); 90 } else { 91 console.info('Capturer start success.'); 92 } 93 }); 94 ``` 95 964. Call **stop()** to stop recording. 97 98 ```ts 99 import { BusinessError } from '@kit.BasicServicesKit'; 100 101 audioCapturer.stop((err: BusinessError) => { 102 if (err) { 103 console.error(`Capturer stop failed, code is ${err.code}, message is ${err.message}`); 104 } else { 105 console.info('Capturer stopped.'); 106 } 107 }); 108 ``` 109 1105. Call **release()** to release the instance. 111 112 ```ts 113 import { BusinessError } from '@kit.BasicServicesKit'; 114 115 audioCapturer.release((err: BusinessError) => { 116 if (err) { 117 console.error(`capturer release failed, code is ${err.code}, message is ${err.message}`); 118 } else { 119 console.info('capturer released.'); 120 } 121 }); 122 ``` 123 124 125### Sample Code 126 127Refer to the sample code below to record audio using AudioCapturer. 128 129```ts 130import { audio } from '@kit.AudioKit'; 131import { BusinessError } from '@kit.BasicServicesKit'; 132import { fileIo } from '@kit.CoreFileKit'; 133 134const TAG = 'AudioCapturerDemo'; 135 136class Options { 137 offset?: number; 138 length?: number; 139} 140 141let context = getContext(this); 142let bufferSize: number = 0; 143let audioCapturer: audio.AudioCapturer | undefined = undefined; 144let audioStreamInfo: audio.AudioStreamInfo = { 145 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Sampling rate. 146 channels: audio.AudioChannel.CHANNEL_2, // Channel. 147 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Sampling format. 148 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Encoding format. 149} 150let audioCapturerInfo: audio.AudioCapturerInfo = { 151 source: audio.SourceType.SOURCE_TYPE_MIC, // Audio source type. 152 capturerFlags: 0 // Flag indicating an AudioCapturer. 153} 154let audioCapturerOptions: audio.AudioCapturerOptions = { 155 streamInfo: audioStreamInfo, 156 capturerInfo: audioCapturerInfo 157} 158 159let path = getContext().cacheDir; 160let filePath = path + '/StarWars10s-2C-48000-4SW.wav'; 161let file: fileIo.File = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); 162 163let readDataCallback = (buffer: ArrayBuffer) => { 164 let options: Options = { 165 offset: bufferSize, 166 length: buffer.byteLength 167 } 168 fileIo.writeSync(file.fd, buffer, options); 169 bufferSize += buffer.byteLength; 170} 171 172// Create an AudioCapturer instance, and set the events to listen for. 173function init() { 174 audio.createAudioCapturer(audioCapturerOptions, (err, capturer) => { // Create an AudioCapturer instance. 175 if (err) { 176 console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); 177 return; 178 } 179 console.info(`${TAG}: create AudioCapturer success`); 180 audioCapturer = capturer; 181 if (audioCapturer !== undefined) { 182 (audioCapturer as audio.AudioCapturer).on('readData', readDataCallback); 183 } 184 }); 185} 186 187// Start audio recording. 188function start() { 189 if (audioCapturer !== undefined) { 190 let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; 191 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. 192 console.error(`${TAG}: start failed`); 193 return; 194 } 195 196 // Start recording. 197 (audioCapturer as audio.AudioCapturer).start((err: BusinessError) => { 198 if (err) { 199 console.error('Capturer start failed.'); 200 } else { 201 console.info('Capturer start success.'); 202 } 203 }); 204 } 205} 206 207// Stop recording. 208function stop() { 209 if (audioCapturer !== undefined) { 210 // The AudioCapturer can be stopped only when it is in the STATE_RUNNING or STATE_PAUSED state. 211 if ((audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_PAUSED) { 212 console.info('Capturer is not running or paused'); 213 return; 214 } 215 216 // Stop recording. 217 (audioCapturer as audio.AudioCapturer).stop((err: BusinessError) => { 218 if (err) { 219 console.error('Capturer stop failed.'); 220 } else { 221 fileIo.close(file); 222 console.info('Capturer stop success.'); 223 } 224 }); 225 } 226} 227 228// Release the instance. 229function release() { 230 if (audioCapturer !== undefined) { 231 // The AudioCapturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state. 232 if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED || (audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_NEW) { 233 console.info('Capturer already released'); 234 return; 235 } 236 237 // Release the resources. 238 (audioCapturer as audio.AudioCapturer).release((err: BusinessError) => { 239 if (err) { 240 console.error('Capturer release failed.'); 241 } else { 242 console.info('Capturer release success.'); 243 } 244 }); 245 } 246} 247``` 248