开发时遇到一个难题,即我想将在前端录制的音频拼接起来,但总遇到一些不明所以的问题,希望有老哥解答。
下面我简单说明一下我遇到的问题:
初始的时候我使用js-audio-recorder这个包来实现在前端录制语音。
因为临时用了百度的语音转写API,采样值固定在16000.
我尝试了好几种方法来拼接我录制的音频,只有一种方法成功了,那就是在前端使用Crunker
这个包来实现,因为crunker
中用了Web API,所以无法在服务端使用,这样音频数据多的话,延迟太久。
并且crunker
还有一个巨大的问题,那就是拼接以后的音频迷之大,我看了一下10k的音频拼接后变成100多k,放大了10倍。
有老哥说这是采样率的问题,我试着调低了一点采样率,音频质量是降了一点,但结果是音频彻底变质,几乎听不清了。
遂放弃Crunker
。
回到服务端,我使用过AudioSprite
这个包,但是官方的示例太少,只能合成音频(叠加),不懂得如何拼接。
然后用了ffmpeg
这个包,因为依旧没有找到示例,只能自己尝试但一直报错不明所以。
后来,看到了一种使用stream流直接拼合blob数据的方法,如下:
//创建一个可写入的地址,使用stream流的方式,将音频数据写入新的地址中
let filepath = path.join(__dirname, '../../../','public','uploads')+'/uploads_'+ Math.round(Math.random()*Math.pow(10,16))+'.mp3';
let dhh = fs.createWriteStream(filepath); //创建可写入流
var files = SpeechSequence; //获取音频序列
// SpeechSequence = files;
let currentfile;
let stream;
function main(){
if (!files.length) {
dhh.end("Done");
console.log('结束');
return;
}
// 删除文件数组中的第一个元素,并返回第一个元素
currentfile = files.shift();
console.log("下一个拼接:" + currentfile);
// 获取第一个文件的流
stream = fs.createReadStream(currentfile);
// 写入创建好的流文件中
stream.pipe(dhh, {end: false});
stream.on('error',function(error){
console.log('写入错误'+ error);
})
// 当前文件写入完成回调
stream.on("end", function() {
// console.log(currentfile + ' appended');
main();
});
// console.log("3");
}
main();
console.log("拼接好的音频:" + filepath);
我通过百度语音合成API合成的音频,是可以通过这个方法进行拼接的。
但这个方法并不能拼接我在前端录制的音频,来自前端录制的语音blob通过steam流拼接以后,播放只能播放第一段语音。
补充:
经尝试,原来ffmpeg这个包要自己下载,然后配置系统路径,之前一直用npm安装。
但结果还是一样,合成的语音可以拼接,录制的语音通过audioconcat
这个包实现拼接后只能听到第一段。(audioconcat
是使用ffmpeg
进行拼接的)。
所以问题可能是前端录制的音频文件有问题,但我换了个recorder-js
这个包来实现依旧无法解决问题。
希望有老哥帮忙,谢谢!
我想,你的问题其实可以从如下4个方面来考虑:
对于1,从你的介绍中可见 已经是多个 统一格式的 音频文件
对于2,没有看到具体介绍
对于3,你只介绍了有ffmpeg
对于4,只能大致了解需要按某种顺序,将1中文件首尾连在一起。
其实在这里用ffmpeg是比较恰当的,因为ffmpeg其实能实现任何支持解码音频格式 向支持的编码格式输出。所有待拼接的文件写入一个文本文件列表(清单文件,命名其实都无所谓),比如
filelist.txt
用
就可以完成拼接,这时ffmpeg会自动根据
<输出文件路径>
中扩展名来推测输出编码,一般扩展名可以是mp3
、m4a
、wav
之类,也可以在<输出文件路径>
前用参数来详细指定输出文件的类型、编码率、采样率等参数。不过要速度快就需要所谓统一输入和输出文件格式要求啦,这里的统一是指:
编码格式统一
这时的指令变成:
因为不涉及重新编码,其实基本上就是数据包的复制,只有metadata中音频总长度和文件大小会发生变化。
你前面尝试中多段拼接只播放第一段的问题就是文件中metadata中音频总长和文件大小没有正确处理,这样播放时就只能播放第一段。
关于ffmpeg拼接音频视频,可以参考:https://trac.ffmpeg.org/wiki/...