如何用ffmpeg截取视频片段&截取时间不准确的坑

Posted xindoo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用ffmpeg截取视频片段&截取时间不准确的坑相关的知识,希望对你有一定的参考价值。

   之前在工作中,有遇到需要程序化截取视频片段的场景,这里使用ffmpeg命令行就可以很容易实现,这里也记录下我们使用过程中遇到的坑,希望对大家也有所帮助。
   举个例子,当我们要截取视频文件中input.mp4的第15秒到第98秒时,ffmpeg命令行可以这么写:

ffmpeg -ss 15 -to 98 -i input.mp4 -c:v copy output.mp4

   这里的参数-c:v copy 指的是复用原始视频的编码格式,如果想切换视频编码也可以直接指定,比如-c:v libx264 (关于修改视频和音频编码的问题,后续会继续出一篇博客)。另外-ss和-to后面也可以写成时:分:秒的格式,比如要截取视频00:12:01开始到00:15:21的视频,命令行就可以写成如下:

ffmpeg -ss 00:12:01 -to 00:15:21 -i input.mp4 -c:v copy output.mp4

   如果先从某个时间点开始,截取之后的多少秒视频,我们可以将-to参数替换为-t参数,比如我想从视频的00:12:01开始截取之后的60秒视频,命令行就也这么写:

ffmpeg -ss 00:12:01 -t 60 -i input.mp4 -c:v copy output.mp4

  这里需要注意的是如果你同时使用了-t和-to参数,那么ffmpeg会优先使用-t参数的值,也就是说-to参数无效 。

-ss指定起始时间点不准确的问题

   这里再补充一个我们使用中遇到的坑,就是视频截取时间点不准确的问题,以上命令行在我们生产环境中开始还能正常使用,但随着我们输入的视频时长越来越长,我们发现截取出来的视频越来越不对,比如我想从第5分钟截取到第10分钟,结果上面命令行给截出来的是第3分钟到第6分钟的视频。
   后来查阅ffmpeg官网发现,-ss参数有坑,其放在-i前和后的效果不一样,官网是这么介绍-ss参数的:

-ss position (input/output)
When used as an input option (before -i), seeks in this input file to position. Note that in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.
When used as an output option (before an output url), decodes but discards input until the timestamps reach position.
position must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.

   官方还特意提醒了下,当-ss放在-i参数前,其搜索到的时间点位置是不准确的,ffmpeg只能检索到目标时间点之前最近的某个点。当-ss参数在-i参数之后,ffmpeg会将视频重新解码,然后丢弃目标起始时间点之前的视频,这样截取的视频起始时间点才是准确的,但貌似执行速度会慢很多(可能是涉及到视频解码)。
   所以以上几条命令,要想在任何输入下拿到预期结果,就应该这么写:

ffmpeg -i input.mp4 -ss 15 -to 98 -c:v copy output.mp4 
ffmpeg -i input.mp4 -ss 00:12:01 -to 00:15:21 -c:v copy output.mp4  
ffmpeg -i input.mp4 -ss 00:12:01 -t 60 -c:v copy output.mp4

参考资料

  1. ffmpeg 命令行参数

如何利用ffmpeg将一小段视频截取成图片

目前我利用ffmpeg-0.5.1]# ffmpeg -i /mnt/11m夜店_H264.vod -y -f image2 -ss 235 -t 0.001 -s 350x240 /mnt/h264/ffmpeg-0.5.1/picture/11m.jpg 命令可以截取单张的图片,如何实现从设定开始的截取时间同时截取一系列图片。比如说影片开始播放到播放到2分钟的时候,这两分钟的视频一次性全部转化成图片。不知道我的问题说明白了没有,希望大家能踊跃发言。

我给出正解:

ffmpeg -i /mnt/11m夜店_H264.vod /mnt/h264/ffmpeg-0.5.1/picture/1m%04d.jpg -vcodec mjpeg -ss 0:1:2 -t 0:0:1

以上将视频 1分02秒 处开始,持续1秒长的视频输出为jpg的序列
-ss 起始时间
-t 持续时间。

如果你要从片头开始,转换前2分钟为图片序列,则是:
ffmpeg -i /mnt/11m夜店_H264.vod /mnt/h264/ffmpeg-0.5.1/picture/1m%04d.jpg -vcodec mjpeg -ss 0:0:0 -t 0:2:0

另外告诉你,输出的图片数量是25/s的

拿分来。
参考技术A #视频每秒15帧,从31分18秒开始截取三秒内的每一帧为jpg,size:1024*768,保存到e盘wwy目录下,以2m开头+时间序列为命名规范的图片。
ffmpeg -ss 31:18.010 -t 3 -r 15 -i e:/wwy20201125.mp4 -y -f image2 -s 1024x768 e:/wwy/2m%04d.jpg
参考技术B 可以用ae输出TGA序列帧 参考技术C 你是怎么做到的呀 能告诉吗?

以上是关于如何用ffmpeg截取视频片段&截取时间不准确的坑的主要内容,如果未能解决你的问题,请参考以下文章

如何用wireshark截取流媒体视频

使用ffmpeg截取视频第一帧当做背景图

FFmpeg-截取视频图片

java 调用 ffmpeg 进行视频截取

三种方法使用FFmpeg截取视频片断

关于ffmpeg /iis 8.5 服务器下,视频截取第一帧参数配置