Jak streamować kamerę IP na żywo z FFMPEG – Kompletny poradnik do transmisji HLS

FFMPEG to potężne narzędzie umożliwiające przetwarzanie multimediów, w tym transmisje strumieniowe na żywo. W tym wpisie pokaże jak skonfigurować FFMPEG do strumieniowania wideo na żywo z kamery IP i stworzyć transmisję na żywo w formacie HLS (HTTP Live Streaming), który jest szeroko wspierany przez przeglądarki internetowe i odtwarzacze multimedialne.

Przykładowa konfiguracja kamery IP

Zanim przejdziemy do FFMPEG, warto poznać szczegóły techniczne kamery, z której będziemy pobierać obraz. Poniżej przykładowa specyfikacja kamery IP:

  • Rozdzielczość: 4MP (2688×1520)
  • Obiektyw: f = 2.8 ~ 12 mm
  • Kąt widzenia:
    • Poziomy: 33° ~ 105°
    • Pionowy: 18° ~ 54°
    • Przekątny: 38° ~ 125°
  • Zasięg IR: 30m (idealny do monitoringu nocnego)
  • Funkcje dodatkowe: WDR Pro, kompresja H.264

Pobranie strumienia RTSP z kamery IP

Większość kamer IP dostarcza strumień wideo za pośrednictwem protokołu RTSP (Real-Time Streaming Protocol). Możesz pobrać ten strumień za pomocą FFMPEG. W tym przykładzie zakładamy, że strumień kamery jest dostępny pod adresem:

rtsp://admin:admin@192.168.1.176/onvif2

Konfiguracja FFMPEG do streamowania na żywo

Do rozpoczęcia transmisji na żywo z kamery IP, musimy skonfigurować FFMPEG. W tym przykładzie wykorzystujemy kodek H.264, aby zoptymalizować jakość obrazu oraz przepustowość. Strumień zostanie przekonwertowany na format HLS, który umożliwia łatwe dostarczenie wideo do przeglądarek i odtwarzaczy.

Przykładowa komenda FFMPEG, którą możesz uruchomić w terminalu:

ffmpeg -i "rtsp://admin:admin@192.168.1.176/onvif2" \
  -c:v libx264 \
  -preset faster \
  -crf 20 \
  -maxrate 3M \
  -bufsize 6M \
  -r 30 \
  -g 120 \
  -c:a copy \
  -hls_time 10 \
  -hls_list_size 10 \
  -hls_flags delete_segments \
  -start_number 1 \
  camera-001.m3u8 \
  1> camera-001.log1 \
  2> camera-001.log2 &

-i „rtsp://…”: Ścieżka do strumienia RTSP z kamery IP. W tym przykładzie adres RTSP zawiera dane logowania do kamery
-c libx264: stawienie kodeka wideo na H.264, co pozwala na efektywną kompresję strumienia
-preset faster: Ustawia szybkość kodowania wideo. Możesz wybrać inne ustawienia, takie jak „medium” lub „slow”, zależnie od dostępnych zasobów
-crf 20: Określa jakość wideo, gdzie niższa wartość oznacza lepszą jakość (0 to bezstratna jakość)
-maxrate 3M: Maksymalna przepustowość strumienia (3 megabity na sekundę).
-bufsize 6M: Bufor dla przepustowości strumienia
-r 30: Liczba klatek na sekundę (30 FPS)
-g 120: Odstęp między klatkami kluczowymi (Keyframes). Wartość 120 oznacza, że klatka kluczowa jest ustawiana co 4 sekundy (30 FPS * 4 sekundy)
-c copy: Kopiowanie ścieżki audio bez transkodowania
-hls_time 10: Długość segmentu HLS w sekundach (10 sekund)
-hls_list_size 10: Liczba segmentów w pliku listy odtwarzania (m3u8).
-hls_flags delete_segments: Automatyczne usuwanie starszych segmentów, aby zmniejszyć obciążenie dysku
camera-001.m3u8: Nazwa wygenerowanego pliku listy odtwarzania HLS.
1> camera-001.log1 2> camera-001.log2: Zapisuje logi do plików tekstowych (osobno dla standardowego wyjścia i błędów)
&: Uruchamia proces w tle

Odtwarzanie strumienia HLS

Po uruchomieniu powyższej komendy, FFMPEG rozpocznie przesyłanie strumienia na żywo i zapisze go w formacie HLS. Plik camera-001.m3u8 będzie dostępny do odtwarzania np. za pomocą odtwarzacza wideo VLC lub bezpośrednio w przeglądarce (np. za pomocą HTML5 video tag).

Do odtworzenia strumienia na żywo w przeglądarce, wystarczy stworzyć prostą stronę HTML:

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Stream na żywo</title>
</head>
<body>
    <video controls autoplay>
        <source src="camera-001.m3u8" type="application/x-mpegURL">
        Twój odtwarzacz nie obsługuje HLS!
    </video>
</body>
</html>

Umieść plik camera-001.m3u8 w katalogu dostępnym publicznie, aby można było go odtworzyć w przeglądarce.

Testowy serwer node js do wyświetlania kamer online

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 9000;

const server = http.createServer((req, res) => {
    if(req.url === '/') {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(`
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <style>
    #videoPlayer {
      width: 650px; /* Szerokość odtwarzacza */
      height: 310px; /* Wysokość odtwarzacza */
    }
  </style>
</head>
<body>
  <h4>Kamera 1</h4>
  <video id="videoPlayer" controls></video>
  <script>
    if(Hls.isSupported()) {
      var video = document.getElementById('videoPlayer');
      var hls = new Hls();
      hls.loadSource('camera-001.m3u8');
      hls.attachMedia(video);
      hls.on(Hls.Events.MANIFEST_PARSED,function() {
        video.play();
      });
    }
  </script>
</body>
</html>
    `);
    } else if(req.url.endsWith('.m3u8') || req.url.endsWith('.ts')) {
        const filePath = path.join(__dirname, req.url);
        const ext = path.extname(req.url);
        const contentType = ext === '.m3u8' ? 'application/x-mpegURL' : 'video/MP2T';

        fs.readFile(filePath, (error, content) => {
            if(error) {
                if(error.code == 'ENOENT'){
                    res.writeHead(404);
                    res.end('Not Found');
                } else {
                    res.writeHead(500);
                    res.end('Internal Server Error');
                }
            } else {
                res.writeHead(200, {'Content-Type': contentType});
                res.end(content, 'utf-8');
            }
        });
    } else {
        res.writeHead(404);
        res.end("Not Found");
    }
});

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);
});

FFMPEG zapisuje logi procesu streamowania do plików camera-001.log1 oraz camera-001.log2. Możesz regularnie sprawdzać te logi, aby monitorować, czy strumień działa prawidłowo, oraz diagnozować ewentualne błędy.

Dzięki FFMPEG możesz łatwo przekształcić strumień RTSP z kamery IP na format HLS, co umożliwia jego oglądanie na żywo w przeglądarkach internetowych i odtwarzaczach multimedialnych. Użycie kodeka H.264 zapewnia efektywne kodowanie, a format HLS sprawia, że transmisja jest zoptymalizowana dla różnych urządzeń.