使用ffmpeg命令行裁剪合并mp4封装的H.264视频音频流

最近因为工作上的关系又要重操旧业折腾视频编码了,而且这次更偏向实际应用一些。

工作时使用到的工具:

  • CamStudio – 屏幕录像,可录音。Free, GPL license
  • MediaCoder – Audio/Video Transcode Interface
  • FFmpeg – Audio/Video CODEC Converter. Free, LGPL
  • StreamEye – 视频码流分析器。Commercial
  • YUVviewer – YUV RAW码流播放器
  • MediaPlayer

这次的工作是为了录制一次培训讲座中Lab部分的演示。录制很麻烦,起码NG了千万次,而且有过长时间的返工。那么最后为了减少重新录制的麻烦,我选择了输出片段的方式。期望依靠后期处理来进行裁剪和合并的操作。但我并没有Adobe Premier这种非线性编辑器,所以就略显麻烦。折腾很久。

首先CamStudio输出的视频是AVI封装,视频为CamStudio专用编码、音频则是PCM。所以第一步是将这个原始的AVI码流使用MediaCoder的界面小批量地将它用x264编码,Baseline profile@L3.1。这样可以在其他并未预装CamStudio解码器的机器正常播放。

接下来,需要把录成的各个章节小片段合并。我尝试过许多种组合,国产流氓软件我们就不再提及。这里记录下使用FFmpeg的操作过程。来源于搜索到的这篇文章。它的一个思路就是将mp4用MPEG TS码流,而TS码流在文本数据层面可以进行拼接的动作。那么我这里还多了一步转换成mp4封装的步骤,vcode和acode就不指定了,FFmpeg的默认编码必然满足我的需要。

ffmpeg -i demo2-1.avi demo2-1.mp4
ffmpeg -i demo2-2.avi demo2-2.mp4
...
ffmpeg -i 1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
ffmpeg -i 2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 2.ts
ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4

后来嫌麻烦,写了个Batch做这个合并的事情。放心,FFmpeg跑的挺快的。我在Windows下干活,也可以根据需要转成shell脚本。

@echo off

ffmpeg -i %1 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
ffmpeg -i %2 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 2.ts
ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc %3

del 1.ts
del 2.ts

最后呢,就是按照需要去裁剪那些因为不断失误而录下来的错误。参考了这篇这篇文章。他们的一个思路都是利用ffmpeg -ss <Start time> -t <Duration>的选项去做裁剪输出。但是直接对H.264和AAC等编码的码流使用会有两大问题:1、视频裁剪只能对关键参考帧动刀子,如果需要裁切的时间落在了P帧或者B帧最后输出的视频片断肯定有偏差。2、比较明显的音画不同步问题。

那么为了解决上述问题,思路则为:针对问题1,首先将码流转换为仅帧内预测编码(Intra Prediction),另外将AAC等压缩的音频流还原成PCM也对问题2有帮助。参考文章之一选择了MJPEG作为“无损”的视频编码格式,并且提到不使用RAW的理由。而在我的实际使用步骤并不绝对符合。我使用h264的纯帧内编码和PCM音频。

ffmpeg -i demo3-1_1.avi -vcodec h264 -intra -acodec pcm_s16e demo3-1_out.avi

接下来,想要将一段25秒长的错误之处去掉。这里利用MPlayer播放暂停后使用Goto(Ctrl+G)得到比较精确的时间:2’59.121” ~ 3’24.638”。那么用FFmpeg裁剪,就等价于截取0’0”~2’59.121”和3’24.638”这段,抛弃不要的,用上面讲的方法合并前后。为了计算Duration方便,我将分秒格式的时间(1:2.30)换算成秒钟浮点数(62.30)——这两种格式都被FFmpeg支持。

ffmpeg -ss 0.00 -t 179.121 -i demo3-1_out.avi -vcodec libx264 -acodec libvo_aacenc
-ab 320k demo3-1_1.mp4
ffmpeg -ss 204.638 -t 80.372 -i demo3-1a.avi -vcodec libx264 -acodec libvo_aace
nc -ab 320k demo3-1_2.mp4

join_mp4.bat demo3-1_1.mp4 demo3-1_2.mp4 demo3-1.mp4

好了,烦恼我一个月的视频编辑做完啦。