出于科学目的,我试图从视频中提取“每 10 帧中的 1 帧”(即提取 1 帧,保留 9 帧然后重复)。该视频有 105 帧,3.5 秒,29.97fps(h.264,.mov,由 Nikon D3100 制作)。
我有已上传至此处。
甚高频液晶
下面的命令应该生成 10 帧,但它只生成了 6 张图像。我尝试了不同的场景比例,但它们都没有生成正确的帧数(甚至离正确还差得远)。
vlc 1.mov --video-filter=scene --vout=dummy --scene-ratio=10 --scene-prefix=img- --scene-path=. vlc://quit
有人能告诉我问题出在哪里吗?
FFmpeg
FFmpeg 似乎没有适合我目的的命令。下面的命令每秒提取 3 帧,但由于 FPS 不是正好 30(而是 2.97),因此它不会为我产生正确的结果。
此外,即使使用此命令,FFmpeg 也无法给出正确的帧数。对于 3.5 秒的视频,我最多期望 10 帧,但我得到的却是 12 帧!
ffmpeg -i 1.mov -y -an -sameq -r 3 -f image2 -vcodec mjpeg %03d.jpg
我怎样才能实现我的愿望?
答案1
每 10 帧中选择 1 帧
您可以使用select
视频过滤器ffmpeg
可以做到这一点:
ffmpeg -i input.mov -vf "select=not(mod(n\,10))" -vsync vfr -q:v 2 img_%03d.jpg
对于 JPG 输出,您可以使用 改变质量
-q:v
。有效范围是 2(最佳质量)到 31(最差质量)。如果您想输出为 PNG,则不需要此选项。这将输出,,,
img_001.jpg
等等。img_002.jpg
img_003.jpg
答案2
你的问题中最重要的方面是视频使用每秒 29.97 帧,而不是 30 帧。讨厌的 NTSC。
无论如何,我认为最简单的方法是提取每一帧,然后删除不需要的:
ffmpeg -i 1.mov -y -f image2 -c:v mjpeg %03d.jpg
然后,删除不需要的。由于每十帧都会以 结尾1.jpg
,我们可以将其他所有帧都取下来……
find . -maxdepth 1 -not -iname "*1.jpg"
…一旦你确定这些是你想要删除的:
find . -maxdepth 1 -not -iname "*1.jpg" -exec rm '{}' \;
如果你可以使用mencoder
,你可以尝试framestep
选项,如解释的那样在文档中,就像framestep=10
您的情况一样。但我个人无法安装/尝试它。
答案3
如果您首先将视频转换为一系列原始 rgb24 或 rgb32 图像,那么您可能能够获得正确数量的帧,因为原始形式中似乎包含可能根本不是图像的不寻常的帧类型???
在原始的激光影碟中,整个视频由一系列图像组成,这些图像的各个帧号为 1 到 100,000 或更多,这确实是为未来的转换或操作建立基线的正确方法。
业界采用这种奇怪的压缩理念仅仅是为了减少支出并破坏处理数字的真正科学形式。
您必须先将音频提取为波形文件,以免完全丢失音频。FFMPEG 似乎在每个提取的图像中都放置了识别信息,因为如果您尝试将刚提取的图像串在一起,并且将来自其他来源的具有相同扩展名的图像混合在一起,ffmpeg 将忽略您尝试拼凑到所有图像中间的图像。
对于激光影碟格式来说,帧速率仅由呈现连续图像的速率决定,而不以任何方式由图像本身控制。
FFMPEG 可能从科学而非艺术中汲取教训,以正确处理和显示任何类型的图像。或者可能是整个 AV 行业本身。该行业确实需要提高硬件能力并使用需要大量内存/存储空间的原始数据。没有什么比原始数据的精度和准确性更好。