首发于Mandal-Art
FFmpeg精确时间截取视频文件

FFmpeg精确时间截取视频文件

最近收到一个项目需求,是我工作以来,见过客户提出的最明确的需求:
将视频讲解切割,每张幻灯的片断一个文件,按幻灯页码命名文件01.mp4,02.mp4,03.mp4……,以此类推;分辨率不超过320*180像素,单声道96kbps音质,控制每个文件尺寸不超过10M,另请发来对应的ppt文档,用来制作成视频与ppt同步翻页的课程。

于是,承接前面一篇,三分屏课件制作教程,我考虑也能自动按照时间轴拆分所有视频文件。于是得到了下面这段分割代码。

ffmpeg -ss [start] -t [duration] -accurate_seek -i [in].mp4 -codec copy [out].mp4
[start]:为需要截取内容的开始时间
[duration]:为需要截取的时长
[in]:为输入视频文件名
[out]:为输出视频文件名

这种截取的好处是特别快,因为它不会对视频重新编码,直接截取相关时间,导出视频,但是这种方式会导致:如果视频结尾不是关键帧,那么视频最后就会出现一段空白。

这个时候,你可以加入[-avoid_negative_ts 1]变成这样:
ffmpeg -ss [start] -t [duration] -accurate_seek -i [in].mp4 -codec copy  -avoid_negative_ts 1 [out].mp4

这样截取视频之后,空白视频是没有了,但是时间不会精确截取,它会找到下一个关键帧,补全这个视频,所以,导致连续分割的视频之间存在细微的交集。


最后详细看了下FFmpeg的文档,如果你需要精确截取视频,避免关键帧的丢失并精确截取时间,这个时候最好是重新编码视频。就变成这样了:
ffmpeg -ss [start] -t [duration] -i [in].mp4  -c:v libx264 -c:a aac -strict experimental -b:a 98k [out].mp4

最后,你可以写一段脚本,把整个视频拆分:

import os
import json

with open("timeline.json") as f:
    times = json.loads(f.read())
    
times = times["timeline"]

for i in range(len(times)):
    start = times[i]["time"]
    try:
        length = times[i+1]["time"] - times[i]["time"]
    except:
        length = 1000
    os.system('ffmpeg -ss %s -i small.mp4 -t %s -c:v libx264 -c:a aac -strict experimental -b:a 96k %s.mp4' % (start,length,str(i+1)))
编辑于 2017-06-12

文章被以下专栏收录