суббота, 12 января 2019 г.

Захват изображения с web камеры и отображение на веб странице


Нам потребуется nginx, модуль для nginx https://github.com/arut/nginx-rtmp-module, ffmpeg и сама web камера. В качестве плейера будем использовать https://videojs.com/ Я перепробовал довольно много вариантов, но только этот захотел работать одновременно в firefox, chrome, safari ipad/iphone/macbook.

Я опишу сам процесс, как понял его я. 
rtmp модуль запускает ffmpeg, который берет поток из /dev/video0 используя плагин video4linux и записывает в rtmp канал hls/movie. Модуль nginx rtmp принимает данные и раскладывает данные по файликам, параллельно обновляя файл movie.m3u8 в папке /mnt/hls. Потом nginx отдает содержимое папки /mnt/hls по протоколу http, что он умеет делать очень хорошо.

Надо отметить, что этот метод не лишен недостатков. С текущими настройками, есть временной лаг и довольно приличный. Данные пишутся на диск (от этого диск будет деградировать), создатель плагина рекомендует располагать данные в tmpfs или в оперативной памяти.

Конфиг для nginx
http {
    ....
    server {
        listen 8080;
        root /mnt;
        index index.html;

        location / {
        }

        location /stat {
            rtmp_stat all;

            # Use this stylesheet to view XML as web page
            # in browser
            # https://github.com/arut/nginx-rtmp-module/blob/master/stat.xsl
            rtmp_stat_stylesheet stat.xsl;
        }

        location /hls {
            # Serve HLS fragments
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            add_header Cache-Control no-cache;
        }
    }
}

rtmp {
    server {
        listen 1935;

        chunk_size 4000;

        application hls {
            live on;
            hls on;
            hls_path /mnt/hls;
            exec_static ffmpeg -re -f video4linux2 -i /dev/video0 -vcodec libx264 -pix_fmt yuv420p -vprofile baseline -f flv rtmp://localhost:1935/hls/movie;
        }
    }
}

Создаем /mnt/index.html со следующим содержанием
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Live Streaming</title>
    <link href="//vjs.zencdn.net/7.3.0/video-js.min.css" rel="stylesheet">
    <script src="//vjs.zencdn.net/7.3.0/video.min.js"></script>
    <script src="https://unpkg.com/@videojs/http-streaming@1.8.0/dist/videojs-http-streaming.min.js"></script>
</head>
<body>
    <video-js id="vid1" width=600 height=300 class="vjs-default-skin" controls>
        <source src="http://127.0.0.1:8080/hls/movie.m3u8" type="application/x-mpegURL">
    </video-js>
    <script>
        var player = videojs('vid1');
        player.play();
    </script>
</body>
</html>