Skip to content
Till edited this page Jan 22, 2023 · 5 revisions

creating flash movies using FFmpeg

producer

Pushing in real time (-re) a video test source to the /dev/video1 V4L2 device: ffmpeg -re -i testsrc.avi -f v4l2 /dev/video1

To show a static image, you may need to set the output format: ffmpeg -loop 1 -re -i foo.jpg -f v4l2 -vcodec rawvideo -pix_fmt yuv420p /dev/video1. Note that the -loop parameter is named -stream_loop in newer FFmpeg versions.

If you have an older FFmpeg version, you can rely on GStreamer: this is a dummy producer using GStreamer, forcing the format to I420 (i'm not sure whether this is needed, probably not)
gst-launch -v videotestsrc ! "video/x-raw-yuv,width=640,height=360,framerate=30/1,format=(fourcc)I420" ! v4l2sink device=/dev/video1

consumer

this encodes the v4l2loopback output into a flash video and writes it to /tmp/flash.flv
ffmpeg -f video4linux2 -s 640x360 -i /dev/video1 -r 30 -vcodec libx264 -vpre placebo -b 800k -coder 0 -g 2 -bf 0 -ab 64k -f flv /tmp/flash.flv

FFmpeg also comes with a basic video player, which can be used to view the loopback device's stream:

ffplay /dev/video1

Using the Raspberry PI camera as a network webcam

Your boss wants you in a webex but you have no camera available, but a raspberrypi + camera module (CSI)? No problem. Build up a network webcam in a minute. With ffmpeg + v4l2loopback.

Bring the raspberrypi camera on track (Camera server)

To stream the camera data (raw h264 stream, 1280x720 and 1MBit/s) over network just use the raspivid command:

raspivid -t 0 -hf -fps 30 -w 1280 -h 720 -b 1000000 -l -o tcp://0.0.0.0:5000

So, a tcp server is now ready to deliver our data. If you do not want to limit the h264 data bandwidth, just omit the -b parameter.

Bring up ffmpeg with v4l2loopback (Client which receives video feed)

v4l2loopback config

First, you need to get your /dev/video0 device up which is accepted by firefox:

modprobe v4l2loopback devices=1 max_buffers=2 exclusive_caps=1 card_label="VirtualCam #0"

Be sure to run this command as root. Otherwise no kernel module can be loaded.

ffmpeg stream start

Now comes the final step. We will receive the stream from network and writing it into the /dev/video0 device:

ffmpeg -f h264 -i tcp://RASPICAM:5000 -f v4l2 -pix_fmt yuv420p /dev/video0

Set RASPICAM to your hostname/ip of the raspberrypi with the camera.

BONUS: Let your graphics card do the hard work (NVIDIA with VDPAU)

To offload h264 graphics decoding to your graphics card via VDPAU you can do this:

ffmpeg -f h264 -hwaccel vdpau -i tcp://goldeneye:5000 -f v4l2 -pix_fmt yuv420p /dev/video0

Your graphics card will now do the hard work. Check in top/htop if you have less load on your ffmpeg task.

Conclusion

For me this works with both firefox (74.0.1 (64-bit)) and chromium (80.0.3987.149 (Official Build) Arch Linux (64-Bit)). To test if the virtual webcam is working in your browser, you can use https://webcamtests.com. By the time of writing there are no browsers available for linux which are doing accelerated video encoding. They (firefox, chromium) use a browser extension named openh264 from Cisco which is doing the h264 encoding in software. Additionally it looks like it is not possible to pass the raw h264 stream from the raspberrypi into the WebRTC framework.

Using an Android device as a webcam

Over Wifi

Similar to the RPI above also an Android device can be used a source for a network stream. Install IP Webcam and start it. Then you can connect to the IP address on port 8080:

ffmpeg -i http://<Android-IP>:8080/video -vf format=yuv420p -f v4l2 /dev/video0

Over a USB cable

Depending on the network connection, the IP Webcam might have a lot of latency an be quite choppy. If you activate ADB on the device, it is possible to tunnel the IP Webcam stream over a USB cable, which provides a more stable connection:

adb wait-for-usb-device && adb forward tcp:8080 tcp:8080 && ffmpeg -i http://127.0.0.1:8080/video -vf format=yuv420p -f v4l2 /dev/video0

Search online how to enable ADB for your specific Android version. Use adb devices -l to check for connected ADB devices.

Cast your screen as a virtual webcam

If you are running X11 you can also use FFmpeg to to select a region on the screen and then stream it to a v4l2 device (ffmpeg version needs to be somewhat recent):

ffmpeg -f x11grab -select_region 1 -show_region 1 -framerate 25 -i $DISPLAY -vf format=yuv420p -f v4l2 /dev/video0

See the FFmpeg documentation.