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 > When the microphone audio source is set ([SourceType](../../reference/apis-audio-kit/js-apis-audio.md#sourcetype8) is set to **SOURCE_TYPE_MIC**, **SOURCE_TYPE_VOICE_RECOGNITION**, **SOURCE_TYPE_VOICE_COMMUNICATION**, or **SOURCE_TYPE_VOICE_MESSAGE**), the permission ohos.permission.MICROPHONE is required. For details about how to apply for the permission, 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 as fs } from '@kit.CoreFileKit'; 60 61 class Options { 62 offset?: number; 63 length?: number; 64 } 65 66 let bufferSize: number = 0; 67 let path = getContext().cacheDir; 68 let filePath = path + '/StarWars10s-2C-48000-4SW.pcm'; 69 let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 70 let readDataCallback = (buffer: ArrayBuffer) => { 71 let options: Options = { 72 offset: bufferSize, 73 length: buffer.byteLength 74 } 75 fs.writeSync(file.fd, buffer, options); 76 bufferSize += buffer.byteLength; 77 }; 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### Sample Code 125 126Refer to the sample code below to record audio using AudioCapturer. 127 128```ts 129import { audio } from '@kit.AudioKit'; 130import { BusinessError } from '@kit.BasicServicesKit'; 131import { fileIo as fs } from '@kit.CoreFileKit'; 132 133const TAG = 'AudioCapturerDemo'; 134 135class Options { 136 offset?: number; 137 length?: number; 138} 139 140let bufferSize: number = 0; 141let audioCapturer: audio.AudioCapturer | undefined = undefined; 142let audioStreamInfo: audio.AudioStreamInfo = { 143 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Sampling rate. 144 channels: audio.AudioChannel.CHANNEL_2, // Channel. 145 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Sampling format. 146 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Encoding format. 147}; 148let audioCapturerInfo: audio.AudioCapturerInfo = { 149 source: audio.SourceType.SOURCE_TYPE_MIC, // Audio source type. 150 capturerFlags: 0 // Flag indicating an AudioCapturer. 151}; 152let audioCapturerOptions: audio.AudioCapturerOptions = { 153 streamInfo: audioStreamInfo, 154 capturerInfo: audioCapturerInfo 155}; 156let path = getContext().cacheDir; 157let filePath = path + '/StarWars10s-2C-48000-4SW.pcm'; 158let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 159let readDataCallback = (buffer: ArrayBuffer) => { 160 let options: Options = { 161 offset: bufferSize, 162 length: buffer.byteLength 163 } 164 fs.writeSync(file.fd, buffer, options); 165 bufferSize += buffer.byteLength; 166}; 167 168// Create an AudioCapturer instance, and set the events to listen for. 169function init() { 170 audio.createAudioCapturer(audioCapturerOptions, (err, capturer) => { // Create an AudioCapturer instance. 171 if (err) { 172 console.error(`Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); 173 return; 174 } 175 console.info(`${TAG}: create AudioCapturer success`); 176 audioCapturer = capturer; 177 if (audioCapturer !== undefined) { 178 (audioCapturer as audio.AudioCapturer).on('readData', readDataCallback); 179 } 180 }); 181} 182 183// Start audio recording. 184function start() { 185 if (audioCapturer !== undefined) { 186 let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; 187 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. 188 console.error(`${TAG}: start failed`); 189 return; 190 } 191 192 // Start recording. 193 (audioCapturer as audio.AudioCapturer).start((err: BusinessError) => { 194 if (err) { 195 console.error('Capturer start failed.'); 196 } else { 197 console.info('Capturer start success.'); 198 } 199 }); 200 } 201} 202 203// Stop recording. 204function stop() { 205 if (audioCapturer !== undefined) { 206 // The AudioCapturer can be stopped only when it is in the STATE_RUNNING or STATE_PAUSED state. 207 if ((audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_PAUSED) { 208 console.info('Capturer is not running or paused'); 209 return; 210 } 211 212 // Stop recording. 213 (audioCapturer as audio.AudioCapturer).stop((err: BusinessError) => { 214 if (err) { 215 console.error('Capturer stop failed.'); 216 } else { 217 fs.close(file); 218 console.info('Capturer stop success.'); 219 } 220 }); 221 } 222} 223 224// Release the instance. 225function release() { 226 if (audioCapturer !== undefined) { 227 // The AudioCapturer can be released only when it is not in the STATE_RELEASED or STATE_NEW state. 228 if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED || (audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_NEW) { 229 console.info('Capturer already released'); 230 return; 231 } 232 233 // Release the resources. 234 (audioCapturer as audio.AudioCapturer).release((err: BusinessError) => { 235 if (err) { 236 console.error('Capturer release failed.'); 237 } else { 238 console.info('Capturer release success.'); 239 } 240 }); 241 } 242} 243``` 244