Read the original article:Record and play sound using AVRecorder and AVPlayer
Context
AVRecorder can be used to record audio files. AVPlayer can be used to play audio files.
Description
AVRecorder and AVPlayer can be used together to record and play audio files.
Solution / Approach
Important Notice: AVRecorder needs microphone permission.
Recorder
! Important: Recorder functions should be called with respect to the current recorder state.
import { media } from '@kit.MediaKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Observed
export default class Recorder {
private recorder: media.AVRecorder | undefined = undefined;
private fileName: string = ''
recorderState: media.AVRecorderState = 'idle'
// to inform the UI
get readyToRecord(): boolean {
return this.recorderState === 'idle' || this.recorderState === 'released'
}
// to inform the UI
get recording(): boolean {
return this.recorderState === 'started'
}
async start(context: Context) {
// initialize recorder
try {
this.recorder = await media.createAVRecorder()
// Callback function for state changes.
this.recorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {
this.recorderState = state // track state changes
})
// Callback function for errors.
this.recorder.on('error', (err: BusinessError) => {
console.error(`avRecorder failed, code is ${err.code}, message is ${err.message}`);
})
let avProfile: media.AVRecorderProfile = {
audioBitrate: 100000, // Audio bit rate.
audioChannels: 2, // Number of audio channels.
audioCodec: media.CodecMimeType.AUDIO_AAC, // Audio encoding format.
audioSampleRate: 48000, // Audio sampling rate.
fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // Container format.
};
// save file to the app files
let filePath: string = context.filesDir + `/${Date.now()}.mp3`;
this.fileName = filePath.split('/').pop() as string
let audioFile: fs.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
let fileFd = audioFile.fd; // Obtain the file FD.
let avConfig: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // Audio input source.
profile: avProfile,
url: 'fd://' + fileFd.toString(), // Obtain the file descriptor of the created audio file
};
await this.recorder.prepare(avConfig)
await this.recorder.start();
} catch (e) {
console.log('start err:', e.code, e.message)
}
}
async stopAndSave() {
try {
await this.recorder?.stop()
await this.recorder?.reset()
await this.recorder?.release();
this.recorder = undefined;
return this.fileName
} catch (e) {
console.log('stop err:', e.code, e.message)
throw new Error(e.message)
}
}
}
Player
! Important: Player functions should be called with respect to the current player state.
import { media } from "@kit.MediaKit";
import { audio } from "@kit.AudioKit";
import { fileIo as fs } from '@kit.CoreFileKit';
@Observed
export default class Player {
private player: media.AVPlayer | undefined = undefined
playerState: string = "idle"
// to inform the UI
get playing() {
return this.playerState === 'playing'
}
private async init(filePath: string) {
try {
this.player = await media.createAVPlayer()
this.player.on('error', (e) => {
console.log('player on error:', e.code, e.message)
})
this.player.on('stateChange', async (state: string) => {
this.playerState = state;
switch (state) {
case 'idle':
console.log('state: idle');
break;
case 'initialized':
console.log('state: initialized');
this.player!.audioRendererInfo = {
usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
rendererFlags: 0
};
this.player!.prepare();
break;
case 'prepared':
console.log('state: prepared');
this.player!.play();
break;
case 'playing':
console.log('state: playing');
break;
case 'paused':
console.log('state: paused');
break;
case 'completed':
console.log('state: completed');
break;
case 'stopped':
console.log('state: stopped');
break;
case 'released':
console.log('state: released');
this.player = undefined
break;
default:
console.log('state: should not happen', state);
break;
}
})
let file = await fs.open(filePath)
let fdPath = 'fd://' + file.fd.toString()
this.player!.url = fdPath
} catch (e) {
console.log('init err:', e)
}
}
async start(filePath: string) {
try {
if (!this.player) {
await this.init(filePath)
} else {
await this.player.play()
}
} catch (e) {
console.log('start err:', e)
}
}
async pause() {
this.player?.pause()
}
async stop() {
if (this.playerState === 'prepared' || this.playerState === 'playing' || this.playerState === 'paused' ||
this.playerState === 'completed') {
await this.player?.stop()
await this.player?.reset()
await this.player?.release()
this.player = undefined
}
}
}
Key Takeaways
- Use AVRecorder to save audio files.
- Use AVPLayer to play audio files.
- Be sure to get microphone permission.
Top comments (0)