I'm using Python to create a video using ffmpeg. The following code is what I'm using...
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()
After running the above code, I get an output video with a data rate of 214 kbps. This video won't play in Windows Media Player. At first I was at a loss of how to get the video to play, so I compared it to another video that I downloaded. I noticed the only real difference was in the bit rates/data rates. I ran this command from the command line...
ffmpeg -i fire.mp4 -b:v 250k -bufsize 250k water.mp4
which as I understand it takes fire.mp4 and simply outputs a new video with a modified bit rate. This new output works when I open it in Windows Media Player.
The question I'm asking is how can I do this straight from Python? I've tried adding a -b option to commandWriter (as shown) but this does not work. I've also added a bufsize = 10**8 in my pipeWriter but that does not work either.
Overall what I'm trying to accomplish is taking a video input.mp4, modifying each frame as I load it in memory, and then writing that frame to a new file output.mp4. So far ffmpeg is looking like the best tool 'cause I can't get OpenCV to work at all.
So if anyone has a way to have a water.mp4 output file be able to run in Windows Media Player without needing to have that additional command line code run or a better way to complete my overall task, I would much appreciate that.
If your question is how to get a video that plays, as your title suggests, then I found removing some of the redundant parameters worked fine. Code below (other changes in there for personal preference and readability):
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.
However, I think the question is really about specifying bitrate. I'm not sure what error you got when you modified python, but adding this to the args worked fine for me:
'-b:v', '64k',
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.