python - 使用 PyAV 创建的视频长度

标签 python video computer-vision bitrate pyav

使用 PyAV 以指定的帧速率从帧列表创建视频时,视频最终会比预期短几秒,而视频元数据中的帧速率是正确的。 以下是保存视频功能的示例代码:

def save_video(video_name,imlist,framerate,bitrate):
    container = av.open(video_name, mode='w')
    stream = container.add_stream('h264', framerate)
    stream.codec_context.bit_rate = bitrate*1e3 # Bitrate in kbps
    stream.width = image_width
    stream.height = image_height    
    stream.pix_fmt = 'yuv420p'
    for image in imlist:
            image = av.VideoFrame.from_ndarray(image)
            packet = stream.encode(image)
            container.mux(packet)
    container.close()

例如,当以 30fps 制作 600 帧的视频时,结果是 18 秒的视频而不是 20 秒。再次加载视频,看起来有些帧掉了。

我想坚持使用 PyAV,因为我可以轻松设置比特率。我尝试过使用 OpenCV,它可以工作,但会生成非常大的视频文件。

我错过了什么?

最佳答案

在关闭容器之前,我们必须清除编码器中剩余的数据包。

刷新编码器是通过编码None并混合输出数据包来完成的。
container.close()之前添加以下代码:

remain_packets = stream.encode(None)
container.mux(remain_packets)

用于测试的代码示例:

import av
import numpy as np
import cv2

def save_video(video_name, imlist, framerate, bitrate):
    image_height, image_width, ch = imlist[0].shape
    container = av.open(video_name, mode='w')
    stream = container.add_stream('h264', framerate)
    stream.codec_context.bit_rate = bitrate*1e3 # Bitrate in kbps
    stream.width = image_width
    stream.height = image_height
    stream.pix_fmt = 'yuv420p'
    for image in imlist:
        image = av.VideoFrame.from_ndarray(image)
        packet = stream.encode(image)
        container.mux(packet)

    # Flush the encoder
    remain_packets = stream.encode(None)
    container.mux(remain_packets)

    container.close()


def make_sample_image(i, width, height):
    """ Build synthetic "raw RGB" image for testing """
    p = width//60
    img = np.full((height, width, 3), 60, np.uint8)
    cv2.putText(img, str(i+1), (width//2-p*10*len(str(i+1)), height//2+p*10), cv2.FONT_HERSHEY_DUPLEX, p, (30, 30, 255), p*2)  # Blue number (going to be blue when treated as RGB instead of BGR).
    return img


# Build a list of 100 images with sequential frame counter for testing:
imlist = []
for n in range(100):
    img = make_sample_image(n, 192, 108)
    imlist.append(img)

save_video("output_vid.mp4", imlist, 1, 1000)

关于python - 使用 PyAV 创建的视频长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76131465/

相关文章:

matlab - 如何使用 MATLAB 校正图像中的不均匀光照?

Tensorflow 对象检测 API : Train from exported model checkpoint

python - 如何从图像中裁剪和保存分割对象?

python - isdecimal 和 isdigit 之间的区别

python - 当类实例由构造函数或 __new__ 创建时,确保 __init__ 只被调用一次

python - 在 python 中通过文件传递命令行参数的最佳方法

Java JMF不会播放任何视频文件

javascript - 被屏蔽的 HTML 视频元素源无法触发错误事件

python - 如何检查数字是否为 1、14 或 144 的串联

javascript - HTML5 视频、提示点和停止点