Opencv ffmpeg将可变帧速率.webm转换为恒定帧速率视频

Opencv ffmpeg将可变帧速率.webm转换为恒定帧速率视频,opencv,image-processing,video,ffmpeg,video-processing,Opencv,Image Processing,Video,Ffmpeg,Video Processing,我有一个.webm文件,记录了一个每秒16帧的游戏。但是,在尝试使用OpenCV处理视频时,似乎视频是以可变帧速率录制的,因此,当我尝试使用OpenCV通过每16帧获取一帧来每秒获取一帧时,由于视频流将过早结束,因此无法工作 因此,我试图将声称帧速率为16 fps的可变frame.webm视频转换为具有恒定帧的视频,因此我可以每秒提取一帧。我已从中尝试了以下ffmpeg命令: 但是,将发生以下错误: [NULL @ 00000272ccbc0c40] [Eval @ 000000bc11bfe2

我有一个.webm文件,记录了一个每秒16帧的游戏。但是,在尝试使用OpenCV处理视频时,似乎视频是以可变帧速率录制的,因此,当我尝试使用OpenCV通过每16帧获取一帧来每秒获取一帧时,由于视频流将过早结束,因此无法工作

因此,我试图将声称帧速率为16 fps的可变frame.webm视频转换为具有恒定帧的视频,因此我可以每秒提取一帧。我已从中尝试了以下ffmpeg命令:

但是,将发生以下错误:

[NULL @ 00000272ccbc0c40] [Eval @ 000000bc11bfe2f0] Undefined constant or missing '(' in 'copy'
[NULL @ 00000272ccbc0c40] Unable to parse option value "copy"
[NULL @ 00000272ccbc0c40] Error setting option b to value copy.

Error setting up codec context options.
下面是我试图每秒处理一帧的代码:

video = cv2.VideoCapture(test_mp4_vod_path)
print("Opened ", test_mp4_vod_path)
print("Processing MP4 frame by frame")

# forward over to the frames you want to start reading from.
# manually set this, fps * time in seconds you wanna start from
video.set(1, 0)
success, frame = video.read()
#fps = int(video.get(cv2.CAP_PROP_FPS))  # this will return 0!
fps = 16  # hardcode fps
total_frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
print("Loading video %d seconds long with FPS %d and total frame count %d " % (total_frame_count/fps, fps, total_frame_count))

count = 1
while video.isOpened():
    success, frame = video.read()
    if not success:
        break

    if count % fps == 0:
        print("%dth frame is %d seconds on video"%(count, count/fps))
    count += 1
代码将在接近视频结尾之前完成,因为视频的帧速率不是恒定的。 如何将可变FPS视频转换为恒定FPS视频?

  • 有关FFmpeg中的webM选项,请阅读:

  • 如果要转换帧速率,请不要使用
    编解码器副本
    选项

可能的解决方案(
2M
是一个测试值,根据您的视频进行调整):


首先,VC的另一个答案,第一个,就是你需要的答案。然而,这并不是你问题的确切答案

您的命令有一个小错误,这就是抛出错误的原因
-b:v
告诉ffmpeg它应该将
v
ideo
b
itrate设置为给定值。在输入中,将其设置为
copy
。这不是此选项的有效值。比特率选项需要一个数字,可能需要一个数量级,如
320k
320000

或者是复制音频编解码器,在这种情况下,它应该是
-c:a copy
,或者是复制视频比特率。对于后者,只需完全删除参数
-c:v copy
生成视频流(选定部分)的精确副本,其中包括比特率、帧数、帧率和时间戳以及所有其他视频数据


要将输出设置为具有与输入相同的视频比特率,而不进行复制,请先使用
ffprobe
检查流比特率。

Hi@RivenSkaye,如果我是
ffmpeg
新手,并且几乎不知道如何读取其文档。编解码器选项:
-c:v[something]
在这里意味着什么?我从不同的答案中注意到,
[something]
的值可能是
copy
libvpx-vp9
mpeg4
,等等。如果我错了,请纠正我,但我真的不知道。如果你愿意,我可以发布不同的问题,如果你的答案很长,我可以复制链接。@DanielKurniadi抱歉,没有尽快看到评论,因为通知我评论可能有点困难。对于
-c:v
,这意味着
c
odec:
v
ideo,因此
copy
生成有效值并精确复制指定的视频。如果使用搜索选项,则不会强制它以关键帧开始,从而使部分视频无法播放。如果您对某些编解码器和选项有特定问题,请随时提出新问题
video = cv2.VideoCapture(test_mp4_vod_path)
print("Opened ", test_mp4_vod_path)
print("Processing MP4 frame by frame")

# forward over to the frames you want to start reading from.
# manually set this, fps * time in seconds you wanna start from
video.set(1, 0)
success, frame = video.read()
#fps = int(video.get(cv2.CAP_PROP_FPS))  # this will return 0!
fps = 16  # hardcode fps
total_frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
print("Loading video %d seconds long with FPS %d and total frame count %d " % (total_frame_count/fps, fps, total_frame_count))

count = 1
while video.isOpened():
    success, frame = video.read()
    if not success:
        break

    if count % fps == 0:
        print("%dth frame is %d seconds on video"%(count, count/fps))
    count += 1
ffmpeg -i input.we -c:v libvpx-vp9 -minrate 2M -maxrate 2M -b:v 2M -pix_fmt yuv420p -r 16 output.webm