【问题标题】:Using avconv to get a single frame from h264 video at set time使用 avconv 在设定的时间从 h264 视频中获取单帧
【发布时间】:2014-08-14 12:56:20
【问题描述】:

我想使用 avconv 在指定时间从视频文件中获取单个图像。

我对 libav 的了解足以认为我知道自己在做什么,但还不足以真正知道。

我试过了:

avconv -ss 00:00:01.786 -r 25 -i input_video.h264 -frames 1 output_image.jpg

以及使用 t 来避免 'frames' 参数:

avconv -ss 00:00:01.786 -r 25 -i input_video.h264 -t 0.01 output_image.jpg

并在几秒钟内传递而不是使用 hh:mm:ss.xxx 格式:

avconv -ss 1.786 -r 25 -i input_video.h264 -t 0.01 output_image.jpg

我看到的是当 ss 设置为 0(即“0”、“00:00:00.000”、“0.0”等)时,output_image 只是视频的第一帧。正如预期的那样。

ss 的任何其他值 - 甚至 0.0001 - 都会给我视频的最后一帧。

我正在使用来自 Raspbian wheezy repo 的最新 avconv。这种行为对我来说就像一个错误,但我不太了解视频流的其他复杂性,无法确定。

有人知道我做错了什么吗?



额外问题:我实际上想从同一个视频中获得一大堆这些图像。将命令串在一起似乎以前可以工作,即:

avconv -ss 1.786 -r 25 -i input_video.h264 -t 0.01 output_image1.jpg 
-ss 3.454 -r 25 -i input_video.h264 -t 0.01 output_image2.jpg
-ss 5.823 -r 25 -i input_video.h264 -t 0.01 output_image3.jpg
-ss etc,etc.

但我切换回单个图像来调试这个问题。假设第一个问题得到解决,这是构建此命令的最佳方式还是有更好的方式?

【问题讨论】:

  • 好的,我搬到笔记本电脑上,并使用全长电影作为输入运行相同的命令。我看到了一种效果,当我逐秒增加搜索点时,输出图像不会像您期望的那样跨镜头前进。相反,输出在几秒钟内保持不变,然后跳转到完全不同的画面。就好像 -ss seek 缺乏跳到精确点的能力,而是必须在关键帧之间跳转。
  • 可能你已经成为“快速”与“精确”寻求trac.ffmpeg.org/wiki/Seeking%20with%20FFmpeg的牺牲品
  • 可能,但我已经阅读了该页面并且我知道快速搜索(-ss before -i)现在是框架准确的(我理解这一点是因为我在该页面以及其他几个页面上阅读过它) - 虽然如果它不是真的那肯定会解释这种行为。
  • 也许这是 FFmpeg 中的修复,但不是 avconv?

标签: video ffmpeg raspberry-pi raspbian avconv


【解决方案1】:

编辑: 正如 Mulvya 所指出的,ffmpeg 将始终使用 -ss 进行准确搜索。此问题是 avconv 独有的。

如果您在-i 选项之前指定-ss 选项,那么avconv 将不准确地计算帧位置。

您需要先指定 -i 选项,以便 avconv 知道它需要在流中“寻找”直到准确找到正确的时间戳。

此外,您的示例时间 1.786 与您在示例中指定的每秒帧数 -r 25 不一致。

由于1/25=0.04-ss 的任何值都应能被0.04 整除,以便精确指定单个帧。

以下内容应获得视频的第 46 帧:

avconv -i input_video.h264 -r 25 -ss 1.8 -frames:v 1 output_image.jpg

如果您想通过索引获取特定帧,则需要使用bc

avconv -i input_video.h264 -r 25 -ss 0$(echo "scale=2;1000/25" | bc -l) -frames:v 1 output_image.jpg

1000 是视频的第 1001 帧(因为 0/25 是第 1 帧)。

请注意,与@hamboy75 的示例不同,我们将-l(小写L)传递给bc,以便它执行浮点计算(并且不会四舍五入到最接近的整数)。 scale=2 用于生成精确到 2dp 的数字。

还请注意,bc 具有输出小于 1 的数字而没有前导零(即.04)的“功能”,这是 avconv 无法理解的。因此我们还需要在计算0$()前面插入一个前导零@

使用此命令时,您将获得如下所示的输出

frame=    0 fps=  0 q=0.0 size=       0kB time=10000000000.00 bitrate=   0.0kbit
frame=    0 fps=  0 q=0.0 size=       0kB time=10000000000.00 bitrate=   0.0kbit
frame=    0 fps=  0 q=0.0 size=       0kB time=10000000000.00 bitrate=   0.0kbit
frame=    0 fps=  0 q=0.0 size=       0kB time=10000000000.00 bitrate=   0.0kbit
frame=    0 fps=  0 q=0.0 size=       0kB time=10000000000.00 bitrate=   0.0kbit

这是因为 avconv 正在通过文件查找您准确请求的特定帧。因此,具有较大索引的帧将需要更长的时间来提取,因为 avconv 将始终从流的开头“搜索”流。

因此可能更需要提取一系列帧:

avconv -i input_video.h264 -r 25 -ss 0$(echo "scale=2;7500/25" | bc -l) -t 0$(echo "scale=2;250/25" | bc -l) output_image_%04d.jpg

此示例从视频中的 5 分钟中提取 10 秒的帧。当然你也可以只使用:

avconv -i input_video.h264 -r 25 -ss 300.0 -t 10.0 | bc -l) output_image_%04d.jpg

但是,请记住,对于任何小于一秒的持续时间,该值都应该可以被视频的帧速率整除(即 0.04 表示 25 fps)。

每个帧的图像将命名为output_image_0001.jpgoutput_image_0002.jpgoutput_image_0003.jpg 等。如果您希望对提取的帧执行图像比较,您可能需要考虑使用png 而不是jpg以获得更高的保真度。

请注意,如果您指定的帧索引大于视频中存在的帧数,avconv 将简单地提取它找到的最后一帧。您可能想通过查看avconv -i input_video.h264 输出的Duration: 部分来计算视频中的帧数。

【讨论】:

  • ffmpeg 可以在 ss 用作输入选项时准确查找 - 请参阅 entry 以了解 -ss。这已经有一段时间了。
【解决方案2】:

在我的情况下,前 3 分钟每 60 秒我想要一张图像...

对于 {0..3} 中的 i ;做 avconv -ss echo $i*60.0 | bc -i input_video.h264 -frames:v 1 -y out$i.jpg ;完成

如果您在某些时候需要它,您可以稍微更改一下:9。

【讨论】:

    猜你喜欢
    • 2015-11-24
    • 2016-02-13
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 2018-04-12
    • 2010-11-07
    • 2017-05-01
    • 2013-10-12
    相关资源
    最近更新 更多