如何使每块有一个关键帧开始分割使用FFMPEG的视频?(How to split a video u

2019-07-17 12:03发布

我们需要在一小块一小块大小相同的拆分大型直播WMV视频饲料。 我们做了一个脚本,它正常工作这样做,除了一两件事:在视频块不以关键帧开始,所以玩的大多数视频块,当他们不显示任何图像,直到从原始视频关键帧是最终到达。

是不是有一种方法来告诉ffmpeg的,使输出的视频开始与关键帧?

这里是我们的命令行怎么看现在:

ffmpeg.exe -i "C:\test.wmv" -ss 00:00:00 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0000.wmv"
ffmpeg.exe -i "C:\test.wmv" -ss 00:00:05 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0001.wmv"

等等...

Answer 1:

最新建立的ffmpeg包括一个新的选项“段”,这不正是我想你需要。

ffmpeg -i INPUT.mp4 -acodec copy -f segment -vcodec copy -reset_timestamps 1 -map 0 OUTPUT%d.mp4

这产生了一系列编号的输出文件,其被分成基于关键帧段。 在我自己的测试,它的工作好,虽然我没有任何东西用它超过几分钟,只在MP4格式更长的时间。



Answer 2:

作为官方声明FFMPEG文档 ,它一直更好地为我指定-ss timestart -i input_file.ext ,因为它设置(或让我明白了)所产生的视频到最近关键帧您指定的时间戳之前发现的开端。

更改您的例子:

ffmpeg.exe -ss 00:00:00 -i "C:\test.wmv" -t 00:00:05 -acodec copy -vcodec copy -async 1 -y  "0000.wmv"

我已经测试这种方法的工作.flv.mp4文件。



Answer 3:

下面是我能得到工作的解决方案:

正如AV501和d33pika建议,我用ffprobe找到其中关键帧。 由于ffprobe是非常冗长,可能需要几秒钟甚至几分钟才能输出的所有关键帧,也没有办法范围内,我们从一个漫长的视频要帧的范围,我继续进入5个步骤:

  1. 从原始文件导出视频块,围绕所需块大小的两倍。

     ffmpeg -i source.wmv -ss 00:00:00 -t 00:00:06 -acodec copy -vcodec copy -async 1 -y 0001.wmv 
  2. 使用ffprobe找到其中关键帧。 选择所需的块大小后最接近的关键帧。

     ffprobe -show_frames -select_streams v -print_format json=c=1 0001.wmv 
  3. 从ffprobe的输出得到pkt_dts_time只是关键帧之前的帧。

  4. FFMPEG的步骤1的导出块,并指定相同的输入和输出文件,并指定-ss 00:00:00-t [在步骤3中找到的值]。

     ffmpeg -i 0001.wmv -ss 00:00:00 -t 00:00:03.1350000 -acodec copy -vcodec copy -async 1 -y 0001.wmv 
  5. 重新启动,在步骤1,使用-ss [在步骤3中在迭代中找到的值的累积总和。

出发这样,我能有一个高效和稳健的方式在关键帧拆分视频。



Answer 4:

使用的ffmpeg新的构建,可以通过使用ffprobe和ffmpeg的段复用器实现这一目标。

1.使用ffprobe和awk找出尽可能接近到所需块长度的关键帧。

ffprobe -show_frames -select_streams v:0 -print_format csv **[SOURCE_VIDEO]** 2>&1 | grep -n frame,video,1 | awk 'BEGIN { FS="," } { print $1 " " $5 }' | sed 's/:frame//g' | awk 'BEGIN { previous=0; frameIdx=0; size=0; } { split($2,time,"."); current=time[1]; if (current-previous >= **[DURATION_IN_SECONDS]**){ a[frameIdx]=$1; frameIdx++; size++; previous=current;} } END { str=a[0]; for(i=1;i<size;i++) { str = str "," a[i]; } print str;}'

哪里

  • [SOURCE_VIDEO] =路径视频要细分
  • [DURATION_IN_SECONDS] =期望的段长度在几秒钟内

输出是关键帧的逗号分隔的字符串。

2.使用关键帧输出上述作为输入的ffmpeg。

FFMPEG -i [SOURCE_VIDEO] -codec拷贝-map 0 -f段-segment_frames [OUTPUT_OF_STEP_1] [SEGMENT_PREFIX] _%03D。 [SOURCE_VIDEO_EXTENSION]

哪里

  • [SOURCE_VIDEO] =路径视频要细分
  • 关键帧[OUTPUT_OF_STEP_1] =逗号分隔的字符串
  • 段输出的[SEGMENT_PREFIX] =名
  • [SOURCE_VIDEO_EXTENSION] =延伸的源视频(例如,MP4,MKV)


Answer 5:

使用ffprobe -show_frames -pretty <stream>找出关键帧。



Answer 6:

如果你愿意做一些脚本,并希望我帧在一个特定的时间间隔做是单向

  1. 运行ffprobe和收集位置的我从输出帧

    ffprobe -show_streams

  2. 运行一系列使用相同的脚本,让你的愿望块-ss -t命令。

然后,您可以让您的脚本决定帧的最小号[说,有相互的10帧中的两个我的照片,你真的不希望被分块有它。

另一种方式来做到这一点是使用的GStreamer的multisfilesink和将模式设置为关键帧[但是这种意愿块在每个关键帧,这样可能不是很理想]



文章来源: How to split a video using FFMPEG so that each chunk starts with a key frame?