复制视频编解码器导致BrokenPipeError:[Errno 32]管道中断Python ImageIO

y3bcpkx1  于 2023-03-04  发布在  Python
关注(0)|答案(1)|浏览(334)

我尝试使用ImageIO从3个PNG的序列创建视频。我需要视频的帧与3个PNG的完全相同,所以我使用copy视频编解码器。如果我使用压缩的编解码器(如H.264),代码工作正常,但视频中的帧不同。
我使用的是ImageIO版本2.26.0,并安装了FFMpeg版本5.1.2,尽管代码似乎使用的是版本4.2.2。
下面是我的代码:

from imageio import get_writer, imread
 
video = get_writer('encoded.mp4',fps=60,codec='copy')

for i in range(3):

    video.append_data(imread(f'image{str(i)}.png'))

video.close()

但出现错误:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/imageio_ffmpeg/_io.py", line 615, in write_frames
    p.stdin.write(bb)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/Raine/Documents/FileEnconderInVideo/main.py", line 7, in <module>
    video.append_data(imread(f'image{str(i)}.png'))
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/imageio/core/format.py", line 590, in append_data
    return self._append_data(im, total_meta)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/imageio/plugins/ffmpeg.py", line 600, in _append_data
    self._write_gen.send(im)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/imageio_ffmpeg/_io.py", line 622, in write_frames
    raise IOError(msg)
OSError: [Errno 32] Broken pipe

FFMPEG COMMAND:
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/imageio_ffmpeg/binaries/ffmpeg-osx64-v4.2.2 -y -f rawvideo -vcodec rawvideo -s 3840x2160 -pix_fmt rgb24 -r 60.00 -i - -an -vcodec bmp -pix_fmt yuv420p -v warning /Users/Raine/Documents/FileEnconderInVideo/video.mp4

FFMPEG STDERR OUTPUT:

怎么了?
谢谢大家!

1l5u6lss

1l5u6lss1#

怎么了?
简短的回答是:基本原理。
长长的回答:(1)copy "编解码器"不是用于转码,而是用于多路转换,即,它将存储在一个视频容器中的压缩分组复制到另一个视频容器中,而不将它们转换为中间的帧,当从图像容器到视频容器时没有办法这样做;你必须转换代码。(2)视频编解码器是有损的,这就是它们实现如此高压缩比的原因。无损编解码器确实存在,但它们是独角兽,只有非常有限的/利基用例。在大多数情况下,如果你发现自己需要无损编码,最好使用WEBP或TIFF。(3)视频的默认颜色格式是(二次采样)YUV,而不是RGB(A)。同样,支持RGB(A)的编解码器是存在的,但它们也是利基的。
无论出于什么原因,如果您仍然必须创建一个使用无损8位RGB存储帧的视频,您可以通过我们的pyav插件来实现:

import imageio.v3 as iio
import numpy as np

frames = iio.imread("imageio:newtonscradle.gif", mode="RGB")

with iio.imopen("unicorn.mp4", "w", plugin="pyav") as file:
    file.init_video_stream(
        "png", fps=60, pixel_format="rgb24", max_keyframe_interval=1
    )
    for frame in frames:
        file.write_frame(frame)

re_read = iio.imread("unicorn.mp4", plugin="pyav")
np.allclose(frames, re_read)

(For要使其工作,您需要安装ImageIO和PyAV的最新版本。)
虽然上面产生了一个有效的视频,你可以在python中阅读和测试对png,它将不会播放的大多数媒体播放器在那里,因为结果是非常利基和没有得到广泛的支持。
我使用的是ImageIO版本2.26.0,并安装了FFMpeg版本5.1.2,尽管代码似乎使用的是版本4.2.2。
如果你使用的是imageio-ffmpeg,那么它会使用一个内部版本的ffmpeg,除非你把它指向你的系统安装。

相关问题