I need to grab frames from the webcam of a laptop, transmit them one by one and the receiving side stitch them into a video. I picked ffmpeg-python
as wrapper of choice and the example from the docs works right away:
#!/usr/bin/env python
# In this file: reading frames one by one from the webcam.
import ffmpeg
width = 640
height = 480
reader = (
ffmpeg
.input('/dev/video0', s='{}x{}'.format(width, height))
.output('pipe:', format='rawvideo', pix_fmt='yuv420p')
.run_async(pipe_stdout=True)
)
# This is here only to test the reader.
writer = (
ffmpeg
.input('pipe:', format='rawvideo', pix_fmt='yuv420p', s='{}x{}'.format(width, height))
.output('/tmp/test.mp4', format='h264', pix_fmt='yuv420p')
.overwrite_output()
.run_async(pipe_stdin=True)
)
while True:
chunk = reader.stdout.read(width * height * 1.5) # yuv
print(len(chunk))
writer.stdin.write(chunk)
Now for the compression part.
My reading of the docs is that the input to the reader perhaps needs be rawvideo
but nothing else does. I tried replacing rawvideo
with h264
in my code but that resulted in empty frames. I'm considering a third invocation looking like this but is that really the correct approach?
encoder = (
ffmpeg
.input('pipe:', format='rawvideo', pix_fmt='yuv420p', s='{}x{}'.format(width, height))
.output('pipe:', format='h264', pix_fmt='yuv420p')
.run_async(pipe_stdin=True, pipe_stdout=True)