0

I am trying to create h264 video from webcam image. My problem is when I read images from camera and send to ffmpeg by PIPE, I get to low framerate.

My code:

import cv2
import numpy as np
import subprocess as sp
import shlex
                         # 50 frames, resolution 1280x720, and 25 fps
width, height, n_frames, fps = 1280, 720, 50, 30  
cameraObj = cv2.VideoCapture(0)
cameraObj.set(3, 1280)
cameraObj.set(4, 720)
output_filename = 'video.mp4'

sh = shlex.split(f'./ffmpeg -y -s {width}x{height} -pixel_format bgr24 -f rawvideo '
                 f'-r {fps} -i pipe: -vcodec cedrus264 '
                 f'-pix_fmt nv12 {output_filename}') # ffmpeg command with pipe: input

process = sp.Popen((sh), stdin=sp.PIPE)

lstImage = []

for i in range(0,200): #  read 200 images save to lstImage
    ret, img = cameraObj.read()
    lstImage.append(img.tobytes())

for img in lstImage:

    process.stdin.write(img) #send each image to ffmpeg

process.stdin.close()
process.wait()
process.terminate()

Result:

ffmpeg version git-2015-01-22-f86a076 Copyright (c) 2000-2014 the FFmpeg developers
  built on Aug 17 2016 12:24:21 with gcc 4.8 (Ubuntu/Linaro 4.8.4-2ubuntu1~14.04.3)
  configuration: --prefix=/usr --enable-nonfree --enable-gpl --enable-version3 --enable-vdpau --enable-libx264 --enable-libmp3lame --enable-libpulse --enable-libv4l2 --enable-cedrus264
  libavutil      54.  6.100 / 54.  6.100
  libavcodec     56.  0.101 / 56.  0.101
  libavformat    56.  2.100 / 56.  2.100
  libavdevice    56.  0.100 / 56.  0.100
  libavfilter     5.  0.102 /  5.  0.102
  libswscale      3.  0.100 /  3.  0.100
  libswresample   1.  1.100 /  1.  1.100
  libpostproc    53.  0.100 / 53.  0.100
Input #0, rawvideo, from 'pipe:':
  Duration: N/A, start: 0.000000, bitrate: 442368 kb/s
    Stream #0:0: Video: rawvideo (BGR[24] / 0x18524742), bgr24, 1280x720, 442368 kb/s, 20 tbr, 20 tbn, 20 tbc
[VDPAU SUNXI] VE version 0x1680 opened.
Output #0, mp4, to 'video.mp4':
  Metadata:
    encoder         : Lavf56.2.100
    Stream #0:0: Video: h264 (cedrus264) ([33][0][0][0] / 0x0021), nv12, 1280x720, q=2-31, 200 kb/s, 20 fps, 10240 tbn, 20 tbc
    Metadata:
      encoder         : Lavc56.0.101 cedrus264
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (cedrus264))
frame=  200 fps=6.3 q=30.0 Lsize=     760kB time=00:00:10.00 bitrate= 622.8kbits/s
video:759kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.200271%

Frame rate just is 6.3 fps.

However when FFMPEG input is webcam device(/dev/video0) by command:

sudo ./ffmpeg -f v4l2 -channel 0 -video_size 1280x720 -i /dev/video0 -pix_fmt nv12 -r 30 -b:v 64k -c:v cedrus264 test.mp4

frame rate easy reach to 30 fps

Why is there this difference?

martineau
  • 112,593
  • 23
  • 157
  • 280
  • I suggest that you first profile your script and see where it's spending most of its time — this will tell you what needs to be optimized. See [How can you profile a Python script?](https://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script) – martineau Aug 18 '21 at 18:10

0 Answers0