最近由于项目中的需求,需要实现一个可以暂停录音并播放已录制部分的功能,以此文记录一下实现的过程,希望能给大家提供一些帮助
OmRecorder介绍
OmRecorder是一个开源的,用于实现音频录制的第三方库,支持Pcm,Wav格式的音频录制,并支持暂停与续录的功能。对于OmRecorder的更多介绍与使用说明可以看它的Github主页,本文就不赘述了。但是OmRecorder只能在音频录制全部完成后才可以播放音频,所以下面主要介绍的就是在其的基础上实现在暂停录制的情况下实现需求。
实现思路
首先我们来看看OmRecorder中Wav格式下结束录制时的流程:
//omrecorder.Wav
@Override public void stopRecording() {
try {
super.stopRecording();
//写入Wav文件的Header
writeWavHeader();
} catch (IOException e) {
throw new RuntimeException("Error in applying wav header", e);
}
}
private void writeWavHeader() throws IOException {
final RandomAccessFile wavFile = randomAccessFile(file);
wavFile.seek(0); // to the beginning
wavFile.write(new WavHeader(pullTransport.pullableSource(), file.length()).toBytes());
wavFile.close();
}
再看看它的父类中的stopRecording方法又干了些什么:
//omrecorder.AbstractRecorder
@Override public void stopRecording() throws IOException {
pullTransport.stop();
outputStream.flush();
outputStream.close();
}
根据上面的代码可以看出,OmRecorder中Wav完成录制的操作就是将录制的流全部写入文件后再为文件加上一个Header,一个可播放的Wav文件就生成出来了。既然如此,那么在暂停播放时仿照这个流程,将录制的音频文件复制一份出来,再为其加上Header,不就是一个可以播放的文件了吗。
具体实现
仿制Wav类创建一个新的Recorder类,继承AbstractRecorder,并修改其中的pauseRecording方法:
class CustomRecorder(pullTransport: PullTransport, var recordFile: File, val tempFile: File) : AbstractRecorder(pullTransport, recordFile) {
override fun pauseRecording() {
super.pauseRecording()
try {
if (tempFile.exists()) { tempFile.delete() }
FileUtil.copyFile(recordFile.path, tempFile.path)
writeWavHeader(tempFile)
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun stopRecording() {
try {
super.stopRecording()
writeWavHeader(recordFile)
} catch (e: IOException) {
throw RuntimeException("Error in applying wav header", e)
}
}
@Throws(IOException::class)
private fun writeWavHeader(targetFile: File) {
val wavFile = randomAccessFile(targetFile)
wavFile.seek(0) // to the beginning
wavFile.write(WavHeader(pullTransport.pullableSource(), targetFile.length()).toBytes())
wavFile.close()
}
private fun randomAccessFile(file: File): RandomAccessFile {
val randomAccessFile: RandomAccessFile
try {
randomAccessFile = RandomAccessFile(file, "rw")
} catch (e: FileNotFoundException) {
throw RuntimeException(e)
}
return randomAccessFile
}
}
以上是我使用kotlin实现的自定义Record类的具体代码,其中的构造函数中添加了一个tempFile参数,这就是暂停播放时保存的已录制部分可播放的Wav文件,需要注意的是上面代码中使用的WavHeader类的访问权限在OmRecorder中是default的,不能够直接使用,所以需要完整拷贝一份来用。
至此,自定义的Recorder就已经完成了,之后只需要使用这个类来进行音频录制即可,由于是仿照OmRecorder中的Wav来实现的,所以除了构造函数中多出一个参数外其它部分与文档中的Wav使用方法完全一致。
最后附上项目的Github地址:https://github.com/aa352160/AudioRecordDialog