Popen.write - 在关闭文件上操作 | 使用FFmpeg将图像转换为视频

1 投票
2 回答
1233 浏览
提问于 2025-04-18 06:50

我正在尝试用我的摄像头拍的图片创建一个视频文件(使用SimpleCV),这些图片会转换成PIL格式,然后用tostring()方法转成原始格式。

我使用Python的subprocess和Popen来通过FFmpeg创建视频。

我可以把一张图片传给FFmpeg,然后把它做成视频,但当我尝试处理多张图片时,就出现了错误:

ValueError: I/O operation on closed file

这是我的代码。

import subprocess as sp
from SimpleCV import *
from Image import Image

FFMPEG_BIN = "ffmpeg.exe"

img = Camera().getImage().toRGB()


command = [FFMPEG_BIN, '-y',  # (optional) overwrite output file if it exists
           '-f', 'rawvideo', '-vcodec', 'rawvideo', '-s', '%sx%s'%(img.width,img.height),  # size of one frame
           '-pix_fmt', 'rgb24', '-r', '24',  # frames per second
           '-i', '-',  # The imput comes from a pipe
           '-an',  # Tells FFMPEG not to expect any audio
           '-vcodec', 'libx264rgb',
           'my_output_videofile.mp4']


pipe = sp.Popen(command, stdin=sp.PIPE)#, stderr=sp.PIPE)


for n in xrange(10):
    img = Camera().getImage().toRGB().getPIL().tostring()
    pipe.stdin.write(img)


pipe.terminate()

这很奇怪,因为pipe.terminate()是在代码的最后,应该会立刻关闭文件。

编辑:去掉了stderr。

  ffmpeg version N-63208-gbe1fbc0 Copyright (c) 2000-2014 the FFmpeg developers
  built on May 17 2014 01:30:26 with gcc 4.8.2 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib 
  --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray 
  --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug 
  --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus 
  --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame 
  --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx 
  --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid 
  --enable-decklink --enable-zlib
  libavutil      52. 83.100 / 52. 83.100
  libavcodec     55. 62.100 / 55. 62.100
  libavformat    55. 38.100 / 55. 38.100
  libavdevice    55. 13.101 / 55. 13.101
  libavfilter     4.  5.100 /  4.  5.100
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, rawvideo, from 'pipe:':
  Duration: N/A, start: 0.000000, bitrate: 44236 kb/s
    Stream #0:0: Video: rawvideo (RGB[24] / 0x18424752), rgb24, 320x240, 44236 kb/s, 24 tbr, 24 tbn, 24 tbc
No pixel format specified, rgb24 for H.264 encoding chosen.
Use -pix_fmt yuv420p for compatibility with outdated media players.
[libx264rgb @ 0000000000359de0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2
[libx264rgb @ 0000000000359de0] profile High 4:4:4 Predictive, level 1.3, 4:4:4 8-bit
[libx264rgb @ 0000000000359de0] 264 - core 142 r2431 ac76440 - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - 
http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 
psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 
chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 
constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 
keyint_min=24 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 
qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'my_output_videofile.mp4':
  Metadata:
    encoder         : Lavf55.38.100
    Stream #0:0: Video: h264 (libx264rgb) ([33][0][0][0] / 0x0021), rgb24, 320x240, q=-1--1, 12288 tbn, 24 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo -> libx264rgb)
frame=    7 fps=0.0 q=0.0 size=       0kB time=00:00:00.00 bitrate=N/A 

2 个回答

0

可能是因为 ffmpeg 这个程序在你试图添加所有图片之前就已经停止运行了。如果你去掉 , stderr=sp.PIPE 这个参数,你就能看到 ffmpeg 打印出的错误信息。

1

我觉得自己真傻……

SimpleCV有一个非常简单好用的功能,正好满足我的需求。

如果有人感兴趣的话。

http://simplecv.org/docs/SimpleCV.html#i/SimpleCV.Stream.VideoStream

撰写回答