Categories
Linux

Live streaming webcam using ffmpeg

First of all we need to list available Video4Linux devices:

linux # v4l2-ctl --list-devices
Integrated Camera: Integrated C (usb-0000:00:14.0-8):
	/dev/video0
	/dev/video1

Followed by their capabilities. This can be done either using v4l2-ctl

linux # v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 424x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 848x480
			Interval: Discrete 0.050s (20.000 fps)
		Size: Discrete 960x540
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.100s (10.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
	[1]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 424x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 848x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 960x540
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)

or with the converter tool ffmpeg itself:

linux # ffmpeg -hide_banner -f video4linux2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0x55e7cd4146c0] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720 640x480
[video4linux2,v4l2 @ 0x55e7cd4146c0] Compressed:       mjpeg :          Motion-JPEG : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720 640x480

Next step: Generate DASH and HLS compatible stream. HLS was created by Apple and is used on their devices – DASH however seems to be the more open standard. As the ffmpeg dash muxer gives us both – why not take them:

linux # ffmpeg -input_format yuyv422 -f video4linux2  -video_size 1280x720 -framerate 30 -i /dev/video0 -c:v libx264 -f dash -window_size 10 -remove_at_exit 1 -hls_playlist 1 manifest.mpd

This will result in the following (temporary) files:

linux # ls -l
<...>
-rw-r--r-- 1 root root      791 Sep 12 16:39 init-stream0.m4s
-rw-r--r-- 1 root root  1974668 Sep 12 16:39 chunk-stream0-00001.m4s
-rw-r--r-- 1 root root      112 Sep 12 16:39 master.m3u8
-rw-r--r-- 1 root root  1768116 Sep 12 16:40 chunk-stream0-00002.m4s
-rw-r--r-- 1 root root  1881099 Sep 12 16:40 chunk-stream0-00003.m4s
-rw-r--r-- 1 root root  1913932 Sep 12 16:41 chunk-stream0-00004.m4s
-rw-r--r-- 1 root root  1938159 Sep 12 16:41 chunk-stream0-00005.m4s
-rw-r--r-- 1 root root  1879398 Sep 12 16:42 chunk-stream0-00006.m4s
-rw-r--r-- 1 root root  1839236 Sep 12 16:42 chunk-stream0-00007.m4s
-rw-r--r-- 1 root root  1878458 Sep 12 16:42 chunk-stream0-00008.m4s
-rw-r--r-- 1 root root  1843304 Sep 12 16:43 chunk-stream0-00009.m4s
-rw-r--r-- 1 root root  1993814 Sep 12 16:43 chunk-stream0-00010.m4s
-rw-r--r-- 1 root root     1093 Sep 12 16:43 media_0.m3u8
-rw-r--r-- 1 root root     1113 Sep 12 16:43 manifest.mpd
-rw-r--r-- 1 root root  1078174 Sep 12 16:43 chunk-stream0-00011.m4s

As this data is volatile it’s a good idea to store it in something like a ramdisk or /dev/shm/.

To include those streams in we web page, we need a little help from video players like videojs or dash.js.

Samples can be found here for videojs and dash.js, or you just start over with a very basic version like these:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Webcam - Video.js</title>
    <link href="https://vjs.zencdn.net/7.8.4/video-js.css" rel="stylesheet" />
    <!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
    <script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
</head>
  <body>

  <div>
          <video class="video-js" id="my-video" preload="auto" controls width="320" height="264" data-setup="{}">
        <source src="master.m3u8" type="video/x-mpegURL" />
    </video>
    <script src="https://vjs.zencdn.net/7.8.4/video.js"></script>
  </div>

  </body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Webcam - Dash.js</title>
    <script src="http://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
  <body>

  <div>
    <video data-dashjs-player="" autoplay src="manifest.mpd" controls="true"></video>
  </div>

  </body>
</html>

Leave a Reply

Your email address will not be published. Required fields are marked *