2014-10-11 187 views
0

打我使用Python创建使用ffmpeg的视频。下面的代码是我使用的是什么...视频无法在视频播放

import subprocess as sp 
import Image 
FFMPEG_BIN = "ffmpeg" 

commandWriter = [ FFMPEG_BIN, 
       '-y', 
       '-f', 'image2pipe', 
       '-vcodec','mjpeg', 
       '-s', '480x360', # size of one frame 
       '-pix_fmt', 'rgb24', 
       '-r', '29', # frames per second 
       '-i', '-', 
       '-an', # Tells FFMPEG not to expect any audio 
       '-vcodec', 'mpeg4', 
       '-qscale', '5', 
       '-r', '29', 
       '-b', '250', 
       './fire.mp4' ] 

pipeWriter = sp.Popen(commandWriter, stdin=sp.PIPE) 

fps, duration = 24, 10 
for i in range(fps*duration): 
    im = Image.new("RGB",(480,360),(i%250,1,1)) 
    im.save(pipeWriter.stdin, "JPEG") 
pipeWriter.stdin.close() 
pipeWriter.wait() 

pipeWriter.terminate() 

运行上面的代码后,我得到的214 kbps的数据速率输出视频。此视频不会在Windows Media Player中播放。起初我不知道如何让视频播放,所以我将它与另一个我下载的视频进行了比较。我注意到唯一真正的区别在于比特率/数据速率。我从命令行运行这个命令...

ffmpeg -i fire.mp4 -b:v 250k -bufsize 250k water.mp4 

据我了解,它需要fire.mp4,并输出一个新的视频,修改比特率。当我在Windows Media Player中打开它时,此新输出有效。

我要问的问题是,我怎么能做到这一点直接从Python的?我试着给commandWriter添加一个-b选项(如图所示),但这不起作用。我也在我的pipeWriter中添加了bufsize = 10 ** 8,但这也不起作用。

总的来说我想要做到的是拍摄录像input.mp4,修改每个帧,因为我在内存中加载它,然后写一个框架,以一个新的文件output.mp4。到目前为止,ffmpeg看起来是最好的工具,因为我无法让OpenCV工作。

因此,如果任何人有办法让water.mp4输出文件能够在Windows Media Player中运行,而无需额外的命令行代码运行或更好的方式来完成我的整体任务,我将非常感激那。

回答

0

如果你的问题是如何让一个播放视频,你的标题所暗示的,后来我发现去除一些多余的参数的正常工作。下面的代码(在没有其他变化的个人喜好和可读性):

import subprocess 
from PIL import Image 

FFMPEG_BIN = "ffmpeg"  
movie_duration_seconds = 2 
movie_fps = 24 

ffmpeg_command = [ FFMPEG_BIN, 
       '-y', 
       '-f', 'image2pipe', 
       '-vcodec','mjpeg', 
       '-s', '480x360', # size of one frame 
       '-i', 'pipe:0', # take input from stdin 
       '-an', # Tells FFMPEG not to expect any audio 
       '-r', str(movie_fps), 
       #'-pix_fmt', 'yuvj420p', # works fine without this 
       #'-vcodec', 'mpeg4', # not sure why this is needed 
       #'-qscale', '5', # works fine without this 
       #'-b', '250', # not sure why this is needed 
       './fire.mp4' ] 

ffmpeg_process = subprocess.Popen(ffmpeg_command, stdin=subprocess.PIPE) 

for i in range(movie_fps * movie_duration_seconds): 
    # each image is a shade of red calculated as a function of time 
    im = Image.new("RGB",(480,360),(i%255,1,1)) 
    im.save(ffmpeg_process.stdin, "JPEG") 
    ffmpeg_process.stdin.flush() 
ffmpeg_process.stdin.close() 
#ffmpeg_process.wait() 
#ffmpeg_process.terminate() 
ffmpeg_process.communicate() # not sure if is better than wait but 
           # terminate seems not required in any case. 

不过,我认为真正的问题是关于指定比特率。我不确定当你修改python时得到了什么错误,但是将其添加到参数对我来说工作正常:

  '-b:v', '64k', 
+0

这工作很好!我使用了从另一个人使用ffmpeg发现的代码。环顾四周后,我ffmpeg的文档中看到指定-b选项可能是设置数据速率,所以我就不用在命令行(没有工作)重做的方式。我也尝试过使用你提到的变体,'-b:v','64k'在我的commandWriter中没有用。 为了记录在案,我叫我的变量commandWriter因为我有一个commandReader也是我使用相同的代码使用ffmpeg的过程。 – kloudab 2014-10-12 01:57:59

+0

非常好!据我所知,''-b:v 64k''选项有效。或者,具体来说,使用该开关制作的视频显示的比特率为22088;根据ffprobe',没有18783的比特率。我不知道这些比特率是否正确。我在OSX 10.9.4上运行ffmpeg 2.2.3(FWIW)。 – 2014-10-12 08:55:21