Video 如何使用FFMPEG分割视频,使每个块以关键帧开始?
我们需要将一个大的WMV直播视频源分成大小相同的小块。我们制作了一个脚本,它可以很好地完成这项工作,除了一件事:视频块不是从关键帧开始的,所以在播放大多数视频块时,它们不会显示任何图像,直到最终达到原始视频的关键帧 有没有办法告诉ffmpeg使输出视频以关键帧开始 下面是我们的命令行现在的样子:Video 如何使用FFMPEG分割视频,使每个块以关键帧开始?,video,ffmpeg,split,keyframe,Video,Ffmpeg,Split,Keyframe,我们需要将一个大的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: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"
以此类推……如果您愿意编写一些脚本,并且希望以特定的间隔生成I帧,那么一种方法就是
另一种方法是使用gstreamer的multifilesink并将模式设置为key frame[但是这会在每个关键帧处分块,因此可能不理想]使用
ffprobe-show\u frames-pretty
来识别关键帧。以下是我可以使用的解决方案:
根据av501和d33pika的建议,我使用ffprobe查找关键帧的位置。由于ffprobe非常冗长,可能需要几秒钟甚至几分钟才能输出所有关键帧,并且无法确定我们希望从一个长视频中获得的帧范围,因此我将分为5个步骤:
ffmpeg -i source.wmv -ss 00:00:00 -t 00:00:06 -acodec copy -vcodec copy -async 1 -y 0001.wmv
ffprobe -show_frames -select_streams v -print_format json=c=1 0001.wmv
ffmpeg -i source.wmv -ss 00:00:00 -t 00:00:06 -acodec copy -vcodec copy -async 1 -y 0001.wmv
ffprobe -show_frames -select_streams v -print_format json=c=1 0001.wmv
pkt\u dts\u time
-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
-ss
[在迭代过程中在步骤3中找到的值的累积和]通过这种方式,我能够有一种高效而健壮的方法在关键帧分割视频。使用较新版本的
ffmpeg
,可以通过使用ffprobe
和ffmpeg
段muxer
来实现这一点
ffprobe
和awk尽可能近距离地识别关键帧
到所需的块长度ffprobe-显示帧-选择流v:0\
-打印格式csv[源视频]2>&1|
grep-n帧,视频,1|
awk'BEGIN{FS=“,”}{print$1”“$5}'|
sed's/:frame//g'|
awk'开始{previous=0;frameIdx=0;size=0;}
{
拆分($2,时间,“.”);
电流=时间[1];
如果(当前上一个>=[持续时间(单位:秒)]){
a[frameIdx]=1美元;frameIdx++;大小++;上一个=当前;
}
}
结束{
str=a[0];
对于(i=1;iFFMPEG的最新版本包括一个新选项“segment”,它完全符合我认为您需要的功能
ffmpeg-i INPUT.mp4-acodec copy-f段-vcodec copy-reset\u时间戳1-map 0输出%d.mp4
这将生成一系列编号的输出文件,这些文件根据关键帧分为若干段。在我自己的测试中,它工作得很好,尽管我没有在超过几分钟的时间内使用它,而且只使用MP4格式。正如官方声明的那样,在-ss timestart
对我来说效果更好g> -我输入了_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
文件上测试了这种方法。您使用的是最新的ffmpeg版本吗?是的,最新的:ffmpeg版本N-47062-g26c531c。我们还尝试了使用-force_key_frames:v 00:00:00或-force_key_frames:v 00:00:05,但这对输出没有影响。我相信使用-vcodec copy实际上意味着它只是将图片组复制到新文件中,但不会进行任何形式的重新编码来添加关键帧。是这样吗?-vcodec copy
不会重新编码:它只执行解组和muxing。有没有办法将我的文件分割成块,以便每个块都以关键帧开始?它们的持续时间不必完全相同。但是它们必须是完全连续的。如果我在输入文件中指定-ss,它会在关键帧处剪切,但随后我看到我的视频重叠,将相同的GOP重新包含在两个连续的块中。看起来是一个很有希望的解决方案。将进行调查。我查阅了文档,但无法轻松找到方法来探测视频的一小部分(例如,仅前10秒)。因为视频相当长,它会生成几MB的输出,需要几秒钟才能生成。ffprobe中是否有选项仅输出特定流的帧,并且在特定范围内?ffprobe-show_frames-select_streams v filtered to only video frames。现在,我只需要能够指定帧的范围或时间范围。我浏览了文档,没有找到任何关于限制到视频特定时间范围的内容。因此我想我将使用ffmpeg获取块,然后调用ffprobe获取关键帧,然后调用ffmpeg在关键帧之前进行最后分割。@sboisse,-read\u interval
现在允许您需要指定探测的时间或数据包间隔。例如,ffprobe-显示帧-读取间隔10%+20,01:30%01:45-i
从10-30秒开始探测,然后从1:30-1:45开始探测。在您的帮助下,我也可以这样做,但是,初始dts/pts稍微移动了一点(此处为500毫秒)。文档显示