在之前的文章提到过,我有一个视频频道(CScript)和一档音频播客节目(流动人口)。视频平均两周更新一次,音频节目则比较不稳定一些大约1-2月更新一期。制作视频和播客整个流程还是比较繁琐的。需要选题,写稿,拍摄(录制)。完成拍摄之后真正的挑战才刚刚开始。接下来就到了剪辑媒体文件的时候,我用过几款剪辑软件。例如:iMovie, Final Cut Pro, Danvinci Resolve, 库乐队等工具来剪辑。我花费时间最多的就是,拆分和重新拼接整合媒体文件。作为一名开发者,我做了一段时间剪辑工作之后就开始酝酿找一些开发工具把重复的工作流程使用程序代替。
我最先开刀的部分就是视频的字幕,经常会有用户留言告诉我“希望加字幕”。但是如果完完整整的把一个视频的字幕用手写一遍至少在半小时以上。我想:“现在语音识别的服务那么多,我随便找个免费服务生成一下字幕文件算了”。实际上我发现我错了,基本都是付费服务。即使不付费也会限制使用频次。感谢伟大的互联网公司,不放过任何赚钱的机会。在Github找到一个autosub(开源字幕生成软件,现在已经不维护了),鼓捣了一下。发现可以用了,美中不足的是生成了一些错别字(大概20%是错的,还可以接受)。
这个轮子是用Python写的,我比较好奇他是怎么实现的把音频文件转成对应的字幕文件。于是去阅读了源码。看完源代码恍然大悟。简单的概括一下就是三个部分:1.音频断言 2.语音识别 3. 拼接字幕文件格式。
此软件使用了开源软件ffmpeg(请原谅我到现在才提到今天的主角)对音频文件进行切片处理。原因是一个视频从头到尾不应该是一句话。视频之间的间隔是不需要生成字幕的。那么,如何判断哪部分需要拆分呢?
音频文件波形图
如上图所示,箭头标注的部分都是没有声音产生的。我们在这个位置的两端来去除没有声音的部分就好了。思路已经有了,但是只有思路是不可能解决问题的。接着来说ffmpeg,看下官网的介绍:
“完整的跨平台解决方案,用于记录,转换和流传输音频和视频。”
有这个软件就可以对音频视频做出类CRUD的操作了。我这样解释只是为了让大家快速了解它,要想用好ffmpeg还需要具备更多对媒体文件的认知才行。回到正题,现在我们要拆分媒体文件。那么使用ffmpeg怎么来操作呢?
ffmpeg -i 03.m4a -af silencedetect=noise=-30dB:d=0.5 -f null - 2> vol.txt
解释一下上面的命令的作用: 把03.m4a这个音频文件中音量在30dB以内持续0.5秒以上的部分标记出来记录在vol.txt 这个文件中。下图为关于音量分贝的描述:
那么看下这个文件记录了什么:
在红框圈中的部分,就是每一个沉默标记段落的开始和结束的时间节点。这样我们就可以继续使用下面的命令来拆分音频:
ffmpeg -ss <silence_end - 0.25> -t <next_silence_start - silence_end + 2 * 0.25> -i 03.m4a 03_part.m4a
-ss指定切割时间点,-t指定时长。0.25是增加的句柄。
拆分了音频文件之后呢,接下来就是把音频转化成文字了。这一步尤为关键,只要白嫖一下Google的api就好了:
基于js的请求语音api请求代码
const stream = fs.createReadStream(`chunks/audio_${srt_id}.flac`);
const url = 'http://www.google.com/speech-api/v2/recognize?client=chromium&lang=zh-CN&key=AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw&output=json'
var req = urllib.request(url, {
stream: stream,
headers: {
'Content-Type': 'audio/x-flac; rate=16000',
},
method: 'POST',
enableProxy: true,
proxy: "http://0.0.0.0:1087/", //需要fanqiang的Google你懂的
dataType: 'text'
}, function (err, data, res) {
if (err) {
// console.log(JSON.parse(err.data))
// console.log(err)
} else {
let split_response_data = data.split('\n')
if (data.trim() != '{"result":[]}') {
let trans_ary = JSON.parse(split_response_data[1])
let text_content = trans_ary.result[0].alternative[0].transcript
row.text = text_content
subtitle.push(row)
subtitle = _.sortBy(subtitle, ['id']);
console.log(row.text)
let temp = parser.toSrt(subtitle)
fs.writeFileSync('test.srt', temp);
}
}
});
最后把音频和时间轴拼接成srt文件,例如这样:
1
00:00:02,100 --> 00:00:04,700
你好我是XXXX
2
00:00:05,600 --> 00:00:09,000
你好我是XXXX
3
00:00:10,900 --> 00:00:12,000
你是谁aa
4
00:00:12,200 --> 00:00:15,000
你可以自由
这样视频的字幕文件就好了,直接导入编辑软件就👌啦!我就可以把加字幕的活给自动化了。还可以使用ffmpeg把沉默的片段给去除。现在很多剪辑小工具都是基于ffmpeg开发的,如果你对音视频创作有兴趣可以自己开发一些小工具。(发现我前面说的有点啰嗦,导致后面的内容有点坍塌,如果你喜欢这篇内容我可以以后再继续介绍ffmpeg的其他作用)
资料:
更多关于CScrit频道的信息:
-
Bilibili/Youtube/公众号: CScript
-
Telegram群组: t.me/CScriptGrou…
如果你喜欢本频道的内容,请帮忙点赞转发关注!更多的关注就会有更多的灵感✌️✌️