最近由于項目中的需求,需要實現(xiàn)一個可以暫停錄音并播放已錄制部分的功能蛉艾,以此文記錄一下實現(xiàn)的過程钳踊,希望能給大家提供一些幫助
OmRecorder介紹
OmRecorder是一個開源的衷敌,用于實現(xiàn)音頻錄制的第三方庫,支持Pcm拓瞪,Wav格式的音頻錄制缴罗,并支持暫停與續(xù)錄的功能。對于OmRecorder的更多介紹與使用說明可以看它的Github主頁祭埂,本文就不贅述了面氓。但是OmRecorder只能在音頻錄制全部完成后才可以播放音頻,所以下面主要介紹的就是在其的基礎(chǔ)上實現(xiàn)在暫停錄制的情況下實現(xiàn)需求蛆橡。
實現(xiàn)思路
首先我們來看看OmRecorder中Wav格式下結(jié)束錄制時的流程:
//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();
}
根據(jù)上面的代碼可以看出舌界,OmRecorder中Wav完成錄制的操作就是將錄制的流全部寫入文件后再為文件加上一個Header,一個可播放的Wav文件就生成出來了泰演。既然如此呻拌,那么在暫停播放時仿照這個流程,將錄制的音頻文件復制一份出來睦焕,再為其加上Header藐握,不就是一個可以播放的文件了嗎。
具體實現(xiàn)
仿制Wav類創(chuàng)建一個新的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實現(xiàn)的自定義Record類的具體代碼,其中的構(gòu)造函數(shù)中添加了一個tempFile參數(shù)本谜,這就是暫停播放時保存的已錄制部分可播放的Wav文件抬闷,需要注意的是上面代碼中使用的WavHeader類的訪問權(quán)限在OmRecorder中是default的,不能夠直接使用耕突,所以需要完整拷貝一份來用笤成。
至此,自定義的Recorder就已經(jīng)完成了眷茁,之后只需要使用這個類來進行音頻錄制即可炕泳,由于是仿照OmRecorder中的Wav來實現(xiàn)的,所以除了構(gòu)造函數(shù)中多出一個參數(shù)外其它部分與文檔中的Wav使用方法完全一致上祈。
最后附上項目的Github地址:https://github.com/aa352160/AudioRecordDialog