使用avconv在设定的时间从h264视频获取单个帧 [英] Using avconv to get a single frame from h264 video at set time

查看:536
本文介绍了使用avconv在设定的时间从h264视频获取单个帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 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。这个行为对我来说感觉就像一个错误,但我不知道视频流的其他复杂性足以确定。



有没有人知道我' m做错了?







奖金问题我实际上想从同一个视频中获取大量这些图像。一致的命令在一起似乎在以前工作,即:

  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等等,等等。

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

解决方案


编辑:正如Mulvya所说,ffmpeg将始终以-ss精确地寻求。这个问题是avconv所独有的。


如果你指定了 -ss -i 选项之前,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 $(echoscale = 2; 1000/25| bc -l)-frames:v 1 output_image.jpg



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



请注意,不像@ hamboy75的例如,我们将 -l <​​/ code>(小写L)传递给 bc ,以便它执行浮点计算(而不是' t到最接近的整数)。 scale = 2 用于产生精确到2dp的数字。



另请注意, bc 具有输出小于1的数字的特征,而没有avconv不明白的前导零(即 .04 )。因此,我们还需要在计算中插入前导零前缀 0 $()



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

  frame = 0 fps = 0 q = 0.0 size = 0kB time = 10000000000.00 bitrate = 0.0 kbit 
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 $(echoscale = 2; 7500/25| bc -l)-t 0 $(echoscale = 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.jpg output_image_0002.jpg output_image_0003.jpg 等如果你想对提取的框架进行图像比较,你可能需要考虑使用 png 超过 jpg 请注意,如果您指定的帧索引大于视频中存在的帧数,则avconv将简单地提取其找到的最后一帧。您可能需要通过查看持续时间来计算视频中的帧数:部分输出的 avconv -i input_video.h264


I want to use avconv to get a single image at a specified time out of a video file.

I've read just enough about libav to think I know what I'm doing, but not enough to actually know.

I've tried:

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

as well as using t to avoid the 'frames' parameter:

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

and passing in seconds rather than using the hh:mm:ss.xxx format:

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

What I see is when ss is set to 0 (that's '0', '00:00:00.000', '0.0', etc.) the output_image is just the first frame of the video. As expected.

Any other value for ss - even 0.0001 - gives me the last frame of the video.

I'm using the latest avconv from the Raspbian wheezy repo. This behaviour feels like a bug to me, but I don't know the other intricacies of video streaming well enough to be sure.

Does anyone have any idea what I'm doing wrong?



Bonus question: I'd actually like to get a whole bunch of these images out of the same video. Stringing commands together seemed to work before, ie:

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.

but I switched back to single images to debug this problem. Assuming the first issue gets solved, is that the best way to structure this command or is there a better one?

解决方案

Edit: As Mulvya noted, ffmpeg will always seek accurately with -ss. This issue is exclusive to avconv.

If you specify the -ss option before the -i option then avconv will inaccurately calculate the frame position.

You need to specify the -i option first so that avconv knows it needs to "seek" through the stream until it accurately finds the correct timestamp.

Also, your example time 1.786 is not aligned to the frames per second -r 25 that you specify in your example.

Since 1/25=0.04 any value for -ss should be divisible by 0.04 in order to specify an individual frame precisely.

The following should get the 46th frame of your video:

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

If you want to get a specific frame by it's index then you will need to employ bc:

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

Where 1000 is the 1001st frame of the video (since 0/25 is the 1st frame).

Note that unlike @hamboy75's example we pass -l (lower case L) to bc so that it performs a floating point calculation (and doesn't round to the nearest integer). scale=2 is used to produce a number accurate to 2dp.

Also note that bc has the "feature" of outputting numbers less than 1 without the leading zero (i.e. .04) which avconv does not understand. Therefore we also need to insert a leading zero prefixed to the calculation 0$()

When using this command you will get output that looks like the following

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

This is because avconv is seeking through the file to find the specific frame you requested accurately. So frames with a larger index will take longer to extract because avconv will always "seek" through the stream from the stream's beginning.

It may therefore be more desirable to extract a range of frames:

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

This example extracts 10 seconds worth of frames from 5 minutes within the video. Of course you could also just use:

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

However, remember that for any duration less than a second the value should be divisible by the frame rate for the video (i.e. 0.04 for 25 fps).

The images for each frame will be named output_image_0001.jpg, output_image_0002.jpg, output_image_0003.jpg, etc. If you are looking to perform image comparison on the extracted frames you may want to consider using png over jpg for greater fidelity.

Note that if you specify a frame index larger than the number of frames present in the video, avconv will simply extract the last frame it finds. You may want to calculate the number of frames in a video by looking at the Duration: part of the output of avconv -i input_video.h264.

这篇关于使用avconv在设定的时间从h264视频获取单个帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆