← Blog
Streaming15 min czytania

OvenMediaEngine — streaming sub-sekundowy przez LLHLS i WebRTC

OvenMediaEngine dowozi obraz z opóźnieniem poniżej sekundy przez WebRTC i LLHLS, z wbudowanym transkoderem i klastrowaniem. Wyjaśniamy, co licencja AGPL-3.0 znaczy dla serwera streamingowego i jakie koszty leżą poza samym oprogramowaniem.

Opóźnienie w transmisji na żywo jest jedną z tych rzeczy, które nie przeszkadzają, dopóki nie zaczną przeszkadzać krytycznie. Klasyczne HLS albo DASH dowożą obraz z opóźnieniem rzędu kilku do trzydziestu sekund i przy transmisji koncertu nikomu to nie robi różnicy. Ale przy aukcji na żywo, zakładach, teleturnieju z udziałem publiczności, sterowaniu maszyną przez kamerę albo transmisji, pod którą ludzie piszą komentarze — trzydzieści sekund opóźnienia oznacza, że produkt nie działa.

Zejście poniżej sekundy wymaga zupełnie innych protokołów: WebRTC, przeznaczonego pierwotnie do rozmów, albo LLHLS, czyli wariantu HLS z krótkimi, częściowymi segmentami. OvenMediaEngine jest serwerem zbudowanym wprost pod ten scenariusz — przyjmuje transmisję kilkoma protokołami, przekodowuje ją i wypuszcza do widzów właśnie przez WebRTC i LLHLS.

Zanim jednak przejdziemy do możliwości, trzeba omówić licencję, bo przy serwerze streamingowym jest to pytanie pierwsze, nie ostatnie.

AGPL-3.0 na serwerze, z którym łączą się twoi widzowie

OvenMediaEngine jest wydany na AGPL-3.0-only — i to nie jest to samo co GPL. Kluczową różnicą jest paragraf trzynasty, który rozszerza obowiązek udostępnienia źródeł na sytuację, w której użytkownicy korzystają z oprogramowania zdalnie przez sieć komputerową. Klasyczna GPL uruchamia obowiązek przy dystrybucji programu; AGPL uruchamia go również przy udostępnianiu go jako usługi.

Przy serwerze streamingowym to pytanie staje się bardzo konkretne, bo interakcja przez sieć to dokładnie to, co robi każdy widz twojej transmisji. Jeżeli więc bierzesz OvenMediaEngine, modyfikujesz go i budujesz na tym płatną usługę, warunki AGPL trzeba przeanalizować, zanim ta usługa ruszy — z prawnikiem, nie na podstawie wpisu na blogu, także tego.

Autorzy zdają sobie z tego sprawę i rozwiązali to w sposób, który wypada uznać za uczciwy. Sekcja licencyjna README kończy się zdaniem: jeśli potrzebujesz innej licencji, napisz do nas, wraz z adresem. Innymi słowy: istnieje ścieżka licencji komercyjnej i nie trzeba jej wypatrywać w domysłach.

Potwierdza to umowa dla kontrybutorów. Punkt czwarty, nazwany wprost „Commercial Licensing Grant", stanowi, że przekazując wkład udzielasz projektowi prawa do sublicencjonowania go i rozpowszechniania jako część produktu lub usługi komercyjnej na innej, własnościowej licencji. Zdanie następne mówi bez ogródek, że pozwala to projektowi włączać twój wkład do komercyjnych produktów pochodnych, rozpowszechnianych na licencji komercyjnej odrębnej od licencji AGPL.

To klasyczny i całkowicie legalny układ podwójnego licencjonowania: kod jest otwarty na warunkach kopyleftowych, a kto tych warunków nie chce, kupuje licencję. Warto tylko wiedzieć, że przekazując wkład do tego projektu zgadzasz się na wykorzystanie go również w produktach zamkniętych.

Przy okazji drobna nieścisłość w ich dokumentacji, warta odnotowania, bo dotyczy właśnie tej klauzuli: umowa dla kontrybutorów mówi o licencji odrębnej od „AGPLv2", a taka licencja w tym kontekście nie istnieje — plik licencji zawiera pełny tekst AGPL w wersji trzeciej, a README podaje AGPL-3.0-only. To zapewne przeoczenie redakcyjne, ale w dokumencie o skutkach prawnych literówka w numerze wersji licencji jest rzeczą, którą warto zgłosić.

Stan projektu

Repozytorium: OvenMediaLabs/OvenMediaEngine. 3274 gwiazdki i — co ciekawsze — 1137 forków. Taki stosunek forków do gwiazdek jest nietypowy i mówi coś użytecznego: to nie jest projekt, który ludzie zapisują na później, a taki, który biorą i modyfikują pod własne wdrożenie.

Start w czerwcu 2018, napisany w C++. Otwartych zgłoszeń jest 22. Wydania idą w rytmie kilku miesięcy: v0.21.0 z 13 sierpnia 2026, v0.20.5 z marca 2026, v0.20.0 z grudnia 2025, v0.19.0 z sierpnia 2025. Commity na gałęzi master pochodzą z 5 września 2026 i — co warto zauważyć — podpisuje je kilka różnych osób, a nie jedna. Ich treść to typowa praca utrzymaniowa poważnego projektu: poprawki w kodowaniu długości pakietów WebSocketu, zabezpieczenie dzielenia przy odczycie liczby klatek z SPS, zwalnianie mechanizmu epoll dla SRT.

Jedna uwaga porządkowa: organizacja zmieniła nazwę. Wcześniej projekt żył pod szyldem AirenSoft, dziś to OvenMedia Labs — README podaje przy tym oba adresy obrazów w Docker Hubie, aktualny i „legacy", więc migracja jest udokumentowana.

Co przyjmuje i co wypuszcza

Zakres protokołów jest szeroki i to główna praktyczna zaleta tego serwera — nie zmusza nadawcy do zmiany narzędzi.

Wejście przez wypychanie: WebRTC, WHIP (wraz z simulcastem), SRT, RTMP, E-RTMP oraz MPEG-2 TS po UDP. Wejście przez pobieranie: RTSP i własny protokół OVT. Do tego dwa tryby, które nie są transmisją w klasycznym sensie: kanał zaplanowany, czyli nadawanie nagranego wcześniej materiału tak, jakby był transmisją na żywo, oraz kanał multipleksowany, pozwalający zdublować strumień albo złożyć ścieżki.

Ten pierwszy tryb jest wart uwagi przy zastosowaniach firmowych: pozwala prowadzić „transmisję" szkolenia albo prezentacji z nagrania, z pełną obsługą czatu i tego samego potoku technicznego co przy nadawaniu na żywo.

Wyjście to przede wszystkim LLHLS i WebRTC, oba z adaptacyjną przepływnością (ABR). Obok nich jest klasyczne HLS w wersji trzeciej — do zgodności ze starszymi odbiornikami — oraz SRT. Serwer potrafi też wypychać strumień dalej przez SRT, RTMP i MPEG-2 TS, czyli działać jako retransmiter do innych platform.

WebRTC bez zewnętrznych klocków

Uruchomienie WebRTC w produkcji zwykle wymaga złożenia kilku elementów: serwera sygnalizacyjnego, serwera TURN dla widzów za restrykcyjnymi zaporami, obsługi retransmisji. OvenMediaEngine dowozi to w środku i to jest jego mocna strona.

Jest wbudowany serwer sygnalizacyjny oparty o WebSocket oraz wbudowany serwer TURN, dzięki któremu działa WebRTC po TCP — czyli dla widzów w sieciach, w których UDP jest zablokowane, a to w korporacjach i szkołach norma. Do odporności na stratę pakietów służą retransmisje NACK, korekcja błędów ULPFEC dla VP8, H.264 i H.265 oraz wewnątrzpasmowa korekcja błędów dla Opusa.

To nie są funkcje ozdobne. Przy transmisji sub-sekundowej nie ma czasu na duże bufory, więc każda strata pakietu jest widoczna natychmiast — i właśnie te mechanizmy decydują, czy obraz jest użyteczny.

LLHLS z tym, czego zwykle brakuje

Po stronie LLHLS lista jest równie konkretna: DVR, czyli możliwość przewinięcia transmisji do tyłu; zrzut strumienia do materiału na żądanie, więc nagranie powstaje bez osobnego potoku; metadane czasowe w formacie ID3v2, którymi wstrzykuje się do strumienia zdarzenia zsynchronizowane z obrazem; napisy w formacie WebVTT; oraz DRM w trzech systemach — Widevine, FairPlay i PlayReady.

Metadane czasowe zasługują na osobne zdanie, bo rozwiązują konkretny problem produktowy. Jeśli chcesz, by w momencie pokazania produktu na ekranie u widza pojawił się przycisk zakupu, potrzebujesz zdarzenia dowiezionego razem z klatką, a nie osobnym kanałem, który się rozjedzie. Do tego służy właśnie ID3v2 w strumieniu.

Transkoder i pierwsze twarde ograniczenie

Wbudowany transkoder obsługuje w obrazie VP8, H.264, H.265, AV1 oraz tryb przepuszczania bez przekodowania, a w dźwięku Opusa, AAC i również przepuszczanie.

Przy H.265 jest jednak zapis, który trzeba zauważyć: tylko sprzętowo. Nie ma programowego kodowania do H.265 — potrzebny jest sprzęt z odpowiednim akceleratorem. To istotne przy planowaniu maszyn: jeśli twoja architektura zakłada H.265 na zwykłych instancjach obliczeniowych w chmurze, trzeba to zweryfikować przed wyborem typu instancji, nie po.

Tryb przepuszczania warto z kolei potraktować jako pierwszy wybór wszędzie, gdzie się da. Przekodowanie jest najdroższą operacją w całym potoku i jednocześnie tą, która dokłada opóźnienia — a przy transmisji sub-sekundowej każda milisekunda jest widoczna.

Koszty, które leżą poza licencją oprogramowania

To sekcja, której w opisach serwerów streamingowych zwykle brakuje, a która przy wdrożeniu komercyjnym potrafi zaskoczyć bardziej niż sama licencja.

Po pierwsze, kodeki H.264 i H.265 są obłożone patentami, a licencje na nie udzielają pule patentowe — odrębne od licencji na oprogramowanie. To, że serwer jest otwarty, nie zwalnia z ustalenia, czy i jakie zobowiązania powstają przy komercyjnym nadawaniu w tych formatach i przy waszej skali. Warto przy okazji zauważyć, że w repozytorium leży osobny plik z licencjami komponentów zewnętrznych o wielkości ponad siedemdziesięciu kilobajtów — to daje pojęcie o liczbie zależności, które taki serwer wciąga.

Po drugie, DRM nie jest funkcją, którą się po prostu włącza. Widevine, FairPlay i PlayReady to systemy trzech różnych firm, a korzystanie z każdego z nich wymaga umowy z jego właścicielem i zwykle dostępu do usługi wydawania licencji. Obecność DRM na liście funkcji znaczy, że serwer potrafi z tymi systemami współpracować — nie że dostajesz je w pakiecie.

Po trzecie, AV1 i VP8 są w tym kontekście formatami o wyraźnie prostszej sytuacji patentowej, więc jeśli wasz odbiorca jest wyłącznie przeglądarkowy, warto sprawdzić, czy nie da się w ogóle uniknąć tematu.

Klastrowanie i praca produkcyjna

Serwer obsługuje strukturę origin-edge, czyli klasyczny układ, w którym maszyny źródłowe przyjmują transmisję, a maszyny brzegowe obsługują widzów — i to jest właściwy sposób dojścia do „setek tysięcy widzów", o których mówi opis projektu. Do tego dochodzi monitorowanie, API REST do zarządzania, nagrywanie do plików, generowanie miniatur oraz wspomniane wypychanie strumienia dalej.

Kontrola dostępu jest rozwiązana dwoma mechanizmami i oba warto znać. Signed Policy to podpisane adresy z ograniczonym czasem ważności — standardowa metoda ochrony treści przed rozdawaniem odnośników. Admission Webhooks idą dalej: przy każdej próbie nadawania albo odbioru serwer odpytuje twój endpoint, który decyduje o dopuszczeniu. To pozwala oprzeć autoryzację na własnym systemie kont bez wpychania jego logiki do konfiguracji serwera, i przy usłudze płatnej jest to mechanizm, którego się właśnie chce.

Uruchomienie i sprawa portów

Najprostsza droga to obraz Dockera, ale polecenie z README pokazuje przy okazji rzecz, o której trzeba pomyśleć wcześniej niż zwykle:

docker run --name ome -d -e OME_HOST_IP=Twoj.ADRES.IP \
  -p 1935:1935 -p 9999:9999/udp -p 9000:9000 -p 3333:3333 \
  -p 3478:3478 -p 10000-10003:10000-10003/udp -p 10000:10000/tcp \
  ovenmedialabs/ovenmediaengine:latest

To osiem wpisów obejmujących TCP i UDP, w tym zakres portów dla WebRTC oraz port 3478 dla wbudowanego TURN-a. Zmienna OME_HOST_IP nie jest ozdobą — WebRTC potrzebuje znać adres, który ma rozgłaszać kandydatom połączeń, i przy adresie za translacją NAT jest to najczęstsza przyczyna transmisji, która „prawie działa".

Praktyczny wniosek: ten serwer wymaga rozmowy z osobą odpowiedzialną za sieć przed wdrożeniem, nie po.

Dołączony plik docker-compose.yml jest przy tym lepszą dokumentacją niż README, bo pokazuje gotowy układ dwóch usług — źródłowej i brzegowej — z opisanym przeznaczeniem każdego portu. Wynika z niego kilka rzeczy wartych zapamiętania.

Po pierwsze, rola serwera wybierana jest katalogiem konfiguracji przekazanym skryptowi startowemu: -c origin_conf albo -c edge_conf. To ta sama binarka w dwóch trybach. Po drugie, serwer brzegowy wskazuje źródłowy zmiennymi z adresem i portem 9000 — czyli wewnętrzną komunikację w klastrze obsługuje własny protokół OVT, ten sam, który jest na liście wejść „przez pobieranie".

Po trzecie, zakres czterech portów UDP dla kandydatów WebRTC ma w komentarzu wyjaśnienie: cztery porty dla rozdzielenia wątków. To nie jest zapas na przyszłość, a decyzja wydajnościowa — ruch jest rozkładany między porty, żeby nie wąskim gardłem nie stał się jeden wątek obsługi.

I po czwarte, pułapka konfiguracyjna zapisana w komentarzu przy dwóch zmiennych: port sygnalizacji WebRTC i port strumienia LLHLS muszą być różne, jeśli włączone są oba mechanizmy — a w przykładzie oba mają domyślnie 3333. Ponieważ typowe wdrożenie chce jednego i drugiego, jest to zmiana, którą trzeba wykonać niemal zawsze, a objawem jej pominięcia będzie działanie tylko jednej ścieżki dostarczania. Warto też odnotować, że dla wariantu z TLS jest osobny port sygnalizacji.

Konfigurację trzyma się na hoście przez wolumeny, z osobnymi katalogami dla roli źródłowej i brzegowej oraz osobnym katalogiem na certyfikaty — w dołączonym pliku wpisy są zakomentowane i to jest pierwsza rzecz do odkomentowania przy jakimkolwiek poważnym użyciu.

Obsługiwane platformy to Docker oraz Ubuntu 18 i nowsze, Rocky Linux i AlmaLinux 8 i nowsze oraz Fedora 28 i nowsze.

Sygnał jakości, którego nie widać z zewnątrz

Serwer mediów w C++ obsługujący tysiące jednoczesnych połączeń to program, w którym najgroźniejsze błędy to wyścigi między wątkami — objawiające się raz na tydzień, na produkcji, w sposób nie do odtworzenia. Warto więc odnotować, co ten projekt z tym robi.

W drzewie źródeł leży pełny przewodnik analizy bezpieczeństwa wątków, przeznaczony dla osób piszących kod, wraz z własnymi opakowaniami muteksów, strażników i zmiennych warunkowych oraz zestawem makr adnotacji. Analiza tego rodzaju polega na tym, że kompilator dostaje informację, który muteks chroni które pole, i sam zgłasza dostęp bez trzymanej blokady — czyli klasa błędów jest wyłapywana przy kompilacji, nie w logach.

Najbardziej przekonuje jednak to, jak ten mechanizm jest testowany. Obok zwykłych testów zachowania w czasie działania leży plik testów negatywnych, którego zadaniem jest sprawdzenie, czy kompilator faktycznie zgłasza ostrzeżenia tam, gdzie powinien. Testowanie samych diagnostyk narzędzia analizy jest poziomem staranności, jakiego się na co dzień nie spotyka — a przy oprogramowaniu, które ma stać pod obciążeniem bez restartu, jest dokładnie tym, czego się chce.

Dla oceny projektu ma to konkretne znaczenie. Przewodnik ma osobne rozdziały o regułach dla kontrybutorów, migracji z typów standardowych na własne, ograniczeniach samej metody i rozwiązywaniu problemów. To nie jest notatka wewnętrzna, a dokument napisany po to, by nowa osoba dołożyła kod bez wprowadzenia wyścigu.

Ekosystem

Warto wiedzieć, że projekt nie stoi sam. Ta sama organizacja rozwija OvenPlayer — odtwarzacz w JavaScripcie obsługujący WebRTC i LLHLS, czyli dokładnie te dwa wyjścia — oraz OvenLiveKit, enkoder nadający z przeglądarki. Jest też publiczne demo, na którym można sprawdzić realne opóźnienie bez stawiania czegokolwiek u siebie.

To istotna informacja praktyczna: WebRTC po stronie odbiorcy nie jest tak prosty jak wstawienie znacznika wideo, więc gotowy odtwarzacz od tych samych autorów oszczędza sporo pracy. Odtwarzacz ma osobne repozytorium i osobną licencję, którą przy wdrożeniu należy sprawdzić niezależnie od serwera.

Pułapki w jednym miejscu

  • AGPL-3.0 przy usłudze sieciowej. Paragraf trzynasty obejmuje korzystanie zdalne — przy komercyjnej usłudze przeanalizuj to przed startem, a licencja komercyjna jest dostępna na zapytanie.
  • Umowa dla kontrybutorów zawiera zgodę na użycie wkładu w produktach zamkniętych. Warto o tym wiedzieć przed wysłaniem pull requesta.
  • Kodowanie H.265 tylko sprzętowo. Sprawdź to przed wyborem typu instancji.
  • DRM wymaga umów z Google, Apple i Microsoftem osobno. Obecność na liście funkcji to zdolność współpracy, nie gotowa usługa.
  • Licencje patentowe na H.264 i H.265 są odrębne od licencji oprogramowania i przy komercyjnym nadawaniu trzeba je ustalić.
  • Osiem grup portów, TCP i UDP, w tym zakres dla WebRTC i port TURN. To zadanie dla osoby od sieci.
  • OME_HOST_IP trzeba ustawić poprawnie. Przy adresie za NAT to najczęstsza przyczyna niedziałającego WebRTC.
  • Organizacja zmieniła nazwę z AirenSoft na OvenMedia Labs — starsze obrazy Dockera są oznaczone jako „legacy".
  • Port sygnalizacji WebRTC i port LLHLS muszą być różne, a w dołączonym przykładzie oba mają 3333. Przy obu mechanizmach włączonych to zmiana konieczna.
  • Odtwarzacz ma osobną licencję. Sprawdź ją niezależnie od serwera.
  • Nieścisłość w umowie dla kontrybutorów — mówi o „AGPLv2", choć licencją projektu jest AGPL-3.0-only.

Podsumowanie

OvenMediaEngine jest jednym z niewielu otwartych projektów, które rozwiązują problem opóźnienia poniżej sekundy kompletnie — od przyjęcia transmisji, przez przekodowanie, po dowiezienie jej do widza w przeglądarce, wraz z serwerem TURN i sygnalizacją w środku. Osiem lat rozwoju, kilkoro czynnych opiekunów i tysiąc sto forków mówią, że to narzędzie faktycznie stoi w produkcji u ludzi.

  • Sub-sekundowe opóźnienie dwiema drogami — WebRTC dla najniższego opóźnienia i LLHLS dla zasięgu, oba z adaptacyjną przepływnością.
  • Szeroki wybór wejść — WebRTC, WHIP, SRT, RTMP, E-RTMP, MPEG-2 TS, RTSP — więc nadawca nie musi zmieniać narzędzi.
  • Wbudowana sygnalizacja i TURN, dzięki którym WebRTC działa również po TCP, dla widzów za restrykcyjnymi zaporami.
  • Kontrola dostępu przez webhooki, pozwalająca oprzeć autoryzację na własnym systemie kont.
  • Klastrowanie origin-edge, API REST, nagrywanie i miniatury — wyposażenie serwera produkcyjnego, nie dema.
  • Gotowy odtwarzacz i enkoder przeglądarkowy od tych samych autorów, obsługujące dokładnie te protokoły.

Projekt jest wydany na licencji AGPL-3.0-only i jest to najważniejsza informacja w całym wpisie. Do wdrożenia wewnętrznego, do transmisji własnych zdarzeń, do prototypu i do nauki nie stanowi to problemu. Do zbudowania na tym płatnej usługi udostępnianej klientom — jest to pytanie, na które trzeba znaleźć odpowiedź przed premierą, bo klauzula sieciowa AGPL sięga dalej niż zwykła GPL. Dobra wiadomość jest taka, że autorzy przewidzieli ten scenariusz i wprost zapraszają do rozmowy o innej licencji. Zła — że koszt kodeków, DRM i licencji patentowych to osobna rozmowa, którą trzeba odbyć niezależnie od tej pierwszej.