I want to connect at least one webcamera to RPi3 and record smooth 1080p 30fps video. RPi camera is capable of that even on RPi Zero. But everything I tried on RPi 3 gives maximum 8 fps on 720p. Is there way to achieve same performance as with original RP camera?
Heres is the command I use for recording - ffmpeg -f alsa -i plughw:CARD=HD3000,DEV=0 -f v4l2 -framerate 25 -video_size 1280x720 -input_format mjpeg -i /dev/video0 -preset faster -pix_fmt yuv420p /dev/shm/out.mkv
. As I understand OpenCV is out of question - it is even slower. How could I achieve better performace with webcamera? Is RPi camera somehow special so it gives better performace?
-
raspberrypi.org/forums/viewtopic.php?t=85899– CoderMikeCommented Oct 15, 2020 at 16:39
-
Well, the Raspberry Pi camera uses a special slot that connects directly to the GPU on the Pi. (I think) The bottleneck of a USB camera would probably be the USB 2 bus speed. If you have an RPi 4 and a USB 3 webcam, that might be better.– Unsigned_ArduinoCommented Oct 15, 2020 at 22:22
1 Answer
There are at least two possible bottlenecks limiting your encoding performance.
As was also stated in the comments, a camera transmitting uncompressed raw 1080p30 video would exceed the USB 2 port's bandwidth. In this case your options would narrow down to changing to another camera that uses some sort of internal compression, or upgrade to an RPI4 and a USB 3 camera.
But if your example command above is correct, your camera does use compression, namely mjpeg. In this case, USB 2 should suffice for at least this one cam, maybe even a seccond one. What you (unintenionally?) left out in your command is setting the video encoder, so ffmpeg falls back to the default libx264. Even with the -preset faster
a 1080p30 will be too much for your RPi3 for encoding in real time.
You can switch to -preset ultrafast
for faster encoding with lower compression, or change to a faster codec like the RPI's hardware encoder with:
ffmpeg [all your input parameters go here] -c:v h264_omx -pix_fmt yuv420p /dev/shm/out.mkv
You may also add -b:v 2000k
and fiddle with the bandwidth to get the desired quality.
Additionally you should check your input parameters. You say, you want to record 1080p30 video, but your input is set to be 720p25. So you either need to change your input, or you'd need to upscale the video, even though the latter makes little sense. Plus you seem to use some audio device via Alsa, but do not set any encoder parameters for the audio. You should change that, too.
Your final command might look something like this:
ffmpeg -f alsa -i plughw:CARD=HD3000,DEV=0 -f v4l2 -framerate 25 -video_size 1280x720 -input_format mjpeg -i /dev/video0 -c:v h264_omx -b:v 2000k -pix_fmt yuv420p -c:a aac -b:a 128k -ac 2 /dev/shm/out.mkv
Pleas be aware, that even though the RPI's hardware encoder is capable of encoding 1080p30 in realtime, multiple streams won't do. Two streams of 720p30 should be possible.