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>