gpt4 book ai didi

python - 有没有办法在压缩视频并使用 ffmpeg 提取其帧时计算输出帧尺寸

转载 作者:行者123 更新时间:2023-12-04 22:46:55 25 4
gpt4 key购买 nike

我使用以下代码压缩视频并提取其帧。请注意,我不想保存生成的视频。

        output_args = {
"vcodec": "libx265",
"crf": 24,
}
out, err = (
ffmpeg
.input(in_filename)
.output('pipe:', format='rawvideo', pix_fmt='rgb24',**output_args)
.run(capture_stdout=True)
)
frames = np.frombuffer(out, np.uint8).reshape(-1,width,height,3)

当我尝试将输出缓冲区 reshape 为原始视频尺寸时,出现以下错误: cannot reshape array of size 436567 into shape (1920,1080,3)这是意料之中的,因为生成的视频具有较小的尺寸。有没有办法计算压缩视频的帧数、宽度和高度,以便从缓冲区 reshape 帧?

此外,如果我保存压缩视频,而不是加载其帧,然后从压缩视频中加载视频帧,这些将具有与原始视频相同的尺寸。我怀疑引擎盖下发生了某种插值。有没有办法在不保存视频的情况下应用它?

最佳答案

我找到了使用 ffmpeg-python 的解决方案.

假设:

  • out将整个 h265 编码流保存在内存缓冲区中。
  • 您不想将流写入文件。

  • 该解决方案适用以下内容:
  • 执行FFmpeg在带有 sdtin 的子流程中作为输入 pipestdout作为输出 pipe .
    输入将是视频流(内存缓冲区)。
    输出格式是 BGR 像素格式的原始视频帧。
  • 将流内容写入 pipe (至 stdin)。
  • 读取解码视频(逐帧),并显示每一帧(使用 cv2.imshow )

  • 为了测试解决方案,我创建了一个示例视频文件,并将其读入内存缓冲区(编码为 H.265)。
    我使用内存缓冲区作为上述代码的输入(您的 out 缓冲区)。

    这是完整的代码,包括测试代码:
    import ffmpeg
    import numpy as np
    import cv2
    import io

    in_filename = 'in.mp4'

    # Build synthetic video, for testing begins:
    ###############################################
    # ffmpeg -y -r 10 -f lavfi -i testsrc=size=192x108:rate=1 -c:v libx265 -crf 24 -t 5 in.mp4

    width, height = 192, 108

    (
    ffmpeg
    .input('testsrc=size={}x{}:rate=1'.format(width, height), r=10, f='lavfi')
    .output(in_filename, vcodec='libx265', crf=24, t=5)
    .overwrite_output()
    .run()
    )
    ###############################################


    # Use ffprobe to get video frames resolution
    ###############################################
    p = ffmpeg.probe(in_filename, select_streams='v');
    width = p['streams'][0]['width']
    height = p['streams'][0]['height']
    n_frames = int(p['streams'][0]['nb_frames'])
    ###############################################


    # Stream the entire video as one large array of bytes
    ###############################################
    # https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md
    in_bytes, _ = (
    ffmpeg
    .input(in_filename)
    .video # Video only (no audio).
    .output('pipe:', format='hevc', crf=24)
    .run(capture_stdout=True) # Run asynchronous, and stream to stdout
    )
    ###############################################


    # Open In-memory binary streams
    stream = io.BytesIO(in_bytes)

    # Execute FFmpeg in a subprocess with sdtin as input pipe and stdout as output pipe
    # The input is going to be the video stream (memory buffer)
    # The output format is raw video frames in BGR pixel format.
    # https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md
    # https://github.com/kkroening/ffmpeg-python/issues/156
    # http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/
    process = (
    ffmpeg
    .input('pipe:', format='hevc')
    .video
    .output('pipe:', format='rawvideo', pix_fmt='bgr24')
    .run_async(pipe_stdin=True, pipe_stdout=True)
    )


    # https://stackoverflow.com/questions/20321116/can-i-pipe-a-io-bytesio-stream-to-subprocess-popen-in-python
    # https://gist.github.com/waylan/2353749
    process.stdin.write(stream.getvalue()) # Write stream content to the pipe
    process.stdin.close() # close stdin (flush and send EOF)


    # Read decoded video (frame by frame), and display each frame (using cv2.imshow)
    while(True):
    # Read raw video frame from stdout as bytes array.
    in_bytes = process.stdout.read(width * height * 3)

    if not in_bytes:
    break

    # transform the byte read into a numpy array
    in_frame = (
    np
    .frombuffer(in_bytes, np.uint8)
    .reshape([height, width, 3])
    )

    # Display the frame
    cv2.imshow('in_frame', in_frame)

    if cv2.waitKey(100) & 0xFF == ord('q'):
    break

    process.wait()
    cv2.destroyAllWindows()

    注意:我使用了 stdinstdout而不是名称管道,因为我希望代码在 Windows 和 Linux 中都可以工作。

    关于python - 有没有办法在压缩视频并使用 ffmpeg 提取其帧时计算输出帧尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59965990/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com