Własny serwer wideokonferencyjny na VPS: poradnik
Jak obliczyć wymagane pasmo dla Jitsi, BigBlueButton oraz Galène. Analiza zużycia RAM, otwartych portów UDP oraz problemów z NAT przy hostowaniu własnych wideokonferencji.
Własny serwer wideokonferencyjny na VPS a przepustowość łącza
Własne rozwiązanie do wideokonferencji na małych serwerach zawodzi z jednego powodu i rzadko jest nim sam proces instalacji. Każde nowoczesne narzędzie wykorzystuje komponent SFU (Selective Forwarding Unit). Pobiera on jeden strumień wideo od każdego uczestnika i przesyła jego kopię do wszystkich pozostałych osób. W rezultacie ruch wychodzący z serwera rośnie proporcjonalnie do kwadratu liczby uczestników. Serwer VPS z 1 GB lub 2 GB pamięci RAM na współdzielonym łączu uruchomi oprogramowanie bez problemu. Nie obsłuży jednak spotkania dla całego zespołu, które planujesz.
Dlatego należy działać w następującej kolejności. Policz uczestników, oblicz wymagane megabity, a dopiero potem wybierz serwer. Instalacja to dwadzieścia minut kopiowania i wklejania poleceń. To przepustowość łącza decyduje o tym, czy ktokolwiek będzie w stanie Cię usłyszeć.
Dlaczego zapotrzebowanie na pasmo rośnie wraz z kwadratem liczby uczestników?
Zacznijmy od topologii mesh. Każda przeglądarka koduje obraz z kamery i wysyła kopię bezpośrednio do każdej innej przeglądarki, bez udziału serwera mediów. Połączenie mesh dla dwóch osób wymaga jedynie serwera sygnalizacji, dlatego koszt hostowania rozmów jeden na jeden jest niemal zerowy. Topologia mesh przestaje być wydajna przy czterech lub pięciu osobach, ponieważ laptop w sieci domowej musi jednocześnie wysyłać cztery lub pięć oddzielnych kopii własnego strumienia wideo.
SFU działa inaczej. Każda przeglądarka wysyła jedną kopię strumienia do serwera. Serwer odczytuje nagłówki RTP (real-time transport protocol) i przekazuje pakiety do pozostałych uczestników bez dekodowania wideo. Na tym polega cały mechanizm, dlatego SFU charakteryzuje się niskim obciążeniem CPU, ale wysokim zapotrzebowaniem na sieć.
Starszym rozwiązaniem jest MCU (multipoint control unit). Dekoduje ono każdy przychodzący strumień, łączy je w jeden obraz i ponownie go koduje. Pasmo wyjściowe jest minimalne, ale koszt CPU ogromny. Obecnie niemal żadne rozwiązanie wideo nie korzysta z MCU i nie jest ono stosowane w tym przewodniku.
Przejdźmy do obliczeń dla SFU. Załóżmy, że każda osoba wysyła wideo z prędkością 1.2 Mbps i nikt nie wyłącza kamery. Serwer odbiera N razy 1.2 Mbps, co jest wartością liniową i bezpieczną. Serwer wysyła N razy (N minus 1) razy 1.2 Mbps, ponieważ każda z N osób musi otrzymać pozostałe N minus 1 strumieni. Ta druga wartość decyduje o powodzeniu lub porażce projektu.
The data behind this chart
[
{
"label": "4 people",
"sfu_egress_mbps": 14.4,
"egress_gb_per_hour": 6.5,
"monthly_volume_tb": 0.13
},
{
"label": "8 people",
"sfu_egress_mbps": 67.2,
"egress_gb_per_hour": 30.2,
"monthly_volume_tb": 0.6
},
{
"label": "15 people",
"sfu_egress_mbps": 252,
"egress_gb_per_hour": 113.4,
"monthly_volume_tb": 2.3
},
{
"label": "30 people",
"sfu_egress_mbps": "1,044",
"egress_gb_per_hour": 469.8,
"monthly_volume_tb": 9.4
},
{
"label": "50 people",
"sfu_egress_mbps": "2,940",
"egress_gb_per_hour": "1,323",
"monthly_volume_tb": 26.5
}
]Powyższe wiersze przedstawiają obliczenia matematyczne, a nie pomiary konkretnego serwera. Kolumna miesięczna zakłada dwadzieścia godzin rozmów w miesiącu. Warto zacząć od analizy ostatniego wiersza. Pięćdziesiąt osób z włączonymi kamerami wymaga 2,940 Mbps stałego ruchu wychodzącego z pojedynczej maszyny. Trzydzieści osób wymaga 1,044 Mbps. Cztery osoby wymagają 14.4 Mbps, co obsłuży każdy VPS bez zauważalnego obciążenia. Pomiędzy wierszem dla czterech osób a wierszem dla trzydziestu osób liczba uczestników rośnie siedmioipółkrotnie, podczas gdy ruch wychodzący rośnie ponad siedemdziesięciokrotnie.
Rzeczywiste wdrożenia osiągają niższe wartości i warto wiedzieć, w jaki sposób. Zarówno Jitsi, jak i LiveKit wykorzystują simulcast: nadawca publikuje jednocześnie kilka warstw jakości, a SFU przekazuje niższą warstwę osobom, które nie mają aktywnego podglądu danej osoby. Jitsi posiada również ustawienie last-N, które przekazuje wideo tylko dla osób, które mówiły jako ostatnie. Oba rozwiązania znacząco redukują ruch. Żadne z nich nie zmienia jednak charakterystyki krzywej wzrostu i oba przestają pomagać w momencie, gdy wszyscy włączą kamery i przypną widok wszystkich uczestników.
Co faktycznie zapewnia łącze VPS?
Strona z ofertą planu podaje "port 1 Gbps". Jest to prędkość wirtualnej karty sieciowej, a nie gwarancja przepustowości kolejnego przeskoku. Łącze jest współdzielone z innymi użytkownikami na tym samym hoście fizycznym, więc stała przepustowość w godzinach szczytu jest niższa niż prędkość portu, a połączenie konferencyjne stanowi właśnie takie stałe obciążenie. Większość planów zawiera również miesięczny limit transferu, po przekroczeniu którego prędkość jest ograniczana lub naliczane są dodatkowe opłaty.
Ten limit to punkt, w którym pojawiają się koszty na fakturze. Dwadzieścia godzin połączenia dla trzydziestu osób w ciągu miesiąca generuje ruch wychodzący z serwera na poziomie 9.4 TB, przy 469.8 GB na godzinę. Dwadzieścia godzin połączenia dla pięćdziesięciu osób generuje 26.5 TB. Przed sprawdzeniem ilości pamięci RAM należy zweryfikować limit transferu, a jeśli strona z ofertą jest w tej kwestii niejasna, ta niejasność stanowi odpowiedź samą w sobie. Prawidłowe czytanie tanich ofert VPS ma w przypadku tego obciążenia większe znaczenie niż w niemal każdym innym.
Jitsi Meet: domyślny wybór i wymagania
Jitsi Meet to rozwiązanie, od którego większość użytkowników powinna rozpocząć pracę. Instalacja odbywa się z oficjalnego repozytorium Debian projektu, a proces konfiguruje nginx oraz certyfikat automatycznie. Videobridge (JVB) wykorzystuje pojedynczy port UDP, co ogranicza liczbę reguł firewalla. Wymagany jest system Debian 11 lub nowszy, bądź Ubuntu 22.04 lub nowszy.
sudo apt update
sudo apt install -y apt-transport-https curl gnupg
sudo add-apt-repository universe
sudo apt update
sudo curl -sL https://prosody.im/files/prosody-debian-packages.key -o /usr/share/keyrings/prosody-debian-packages.key
echo "deb [signed-by=/usr/share/keyrings/prosody-debian-packages.key] http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/prosody-debian-packages.list
sudo apt install -y lua5.2
curl -sL https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/" | sudo tee /etc/apt/sources.list.d/jitsi-stable.list
sudo apt update
sudo apt install -y jitsi-meetInstalator wymaga podania nazwy hosta, a następnie oferuje wybór certyfikatu. Należy wybrać opcję Let's Encrypt i wskazać domenę, która już wskazuje na publiczny adres IP serwera. Certyfikat jest wydawany poprzez weryfikację HTTP, więc nazwa wskazująca na inny adres spowoduje błąd na tym etapie.
Następnie należy otworzyć porty. Poniżej znajdują się porty udokumentowane w podręczniku; SSH należy otworzyć jako pierwsze, aby ufw enable nie spowodowało utraty dostępu:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 10000/udp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
sudo ufw enablePorty TCP 80 i 443 obsługują aplikację webową oraz umożliwiają odnawianie certyfikatu. Port UDP 10000 przesyła cały ruch audio i wideo; jest to port najczęściej pomijany. Porty UDP 3478 oraz TCP 5349 należą do serwera coturn, który pakiet Jitsi instaluje wraz z mostem. Stanowią one ścieżkę zapasową dla użytkowników, których sieć blokuje ruch UDP.
sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000Pierwsze polecenie powinno wykazać, że usługa jest aktywna. Drugie powinno potwierdzić, że most nasłuchuje na porcie UDP 10000. Jeśli wynik jest pusty, oznacza to, że most nie został uruchomiony, a /var/log/jitsi/jvb.log wskaże przyczynę.
W kwestii doboru zasobów, podręcznik Jitsi publikuje własne wytyczne, podczas gdy BigBlueButton wymaga znacznie większej wydajności:
The data behind this chart
[
{
"label": "Jitsi Meet",
"ram_gb": 8,
"cpu_cores": 4,
"uplink_mbps": "1,000"
},
{
"label": "BigBlueButton 3.0",
"ram_gb": 16,
"cpu_cores": 8,
"uplink_mbps": 250
}
]Podręcznik Jitsi sugeruje 8 GB pamięci RAM oraz 4 dedykowane rdzenie procesora dla serwera produkcyjnego. Przepustowość łącza 1,000 Mbps jest zazwyczaj wystarczająca, przy czym mniejsze instalacje mogą działać na 4 GB lub 2 GB RAM. Warto zapamiętać jeden szczegół z tej dokumentacji: Prosody, serwer XMPP obsługujący sygnalizację, może wykorzystać tylko jeden rdzeń procesora. Dodatkowe rdzenie wspomagają pracę mostu, ale nie wpływają na wydajność sygnalizacji.
Dlaczego wszyscy dołączają do rozmowy, ale nikt nie widzi obrazu?
Jest to typowy błąd Jitsi na serwerze VPS. Lista uczestników zapełnia się, czat działa, a wszystkie okna wideo pozostają czarne. Videobridge ogłasza adresy, które wykrywa na własnych interfejsach. U dostawcy, który przydziela maszynie wirtualnej adres prywatny i mapuje na niego adres publiczny, JVB wykrywa tylko adres prywatny. W rezultacie każdy klient próbuje wysyłać media na adres typu 10.0.0.5, a pakiety nie docierają do celu.
Należy poinformować bridge o obu adresach. Dodaj statyczne mapowanie w /etc/jitsi/videobridge/jvb.conf:
ice4j {
harvest {
mapping {
static-mappings = [
{
local-address = "10.0.0.5"
public-address = "203.0.113.10"
}
]
}
}
}Zrestartuj usługę za pomocą sudo systemctl restart jitsi-videobridge2. Pobierz adres lokalny z ip -4 addr show oraz adres publiczny z panelu sterowania dostawcy. Starsze poradniki zalecają ustawienie tych samych parametrów w /etc/jitsi/videobridge/sip-communicator.properties za pomocą kluczy org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS oraz org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS. Te ustawienia nadal działają, jednak w nowych instalacjach należy użyć powyższego bloku mapowania.
Drugą przyczyną jest nieskonfigurowany firewall. Większość dostawców stosuje sieciowy firewall w panelu sterowania, który działa niezależnie od ufw na serwerze; port UDP 10000 musi być otwarty w obu miejscach. Aby sprawdzić, która warstwa odrzuca pakiety, uruchom sudo tcpdump -ni any udp port 10000 na serwerze podczas dołączania użytkownika z zewnątrz. Brak jakichkolwiek pakietów oznacza, że ruch nie dociera do maszyny, więc blokada znajduje się przed systemem operacyjnym. Jeśli pakiety docierają, a okna wideo pozostają czarne, oznacza to, że bridge odpowiada adresem, do którego klient nie ma dostępu, czyli problem leży w mapowaniu. Jeśli nie masz pewności co do konfiguracji samego ufw, reguły ufw niezbędne dla VPS wyjaśniają kolejność reguł, która często sprawia problemy.
BigBlueButton: zasobożerny, narzucający własne standardy i wymagający całego serwera
BigBlueButton jest zaprojektowany pod kątem edukacji. Posiada tablicę, pokoje podgrup, ankiety oraz obszar prezentacji, a potok nagrywania jest traktowany jako kluczowa funkcja, a nie dodatek. Jest to zdecydowanie najcięższe rozwiązanie w zestawieniu i nie jest to pakiet, który można zainstalować na już działającym serwerze.
Według stanu na sierpień 2026 wspieraną ścieżką jest BigBlueButton 3.0 na Ubuntu 22.04, wybierany za pomocą flagi wersji jammy-300. Deklarowane przez projekt wymagania produkcyjne to 16 GB pamięci z włączonym swapem, 8 rdzeni CPU o wysokiej wydajności jednowątkowej, 250 Mbps symetrycznego łącza oraz 500 GB miejsca na dysku w przypadku przechowywania nagrań (50 GB, jeśli zostaną wyłączone). Wymagane porty to TCP 80 i 443 oraz zakres UDP od 16384 do 32768.
wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v3.0.x-release/bbb-install.sh
less bbb-install.sh
bash bbb-install.sh -w -v jammy-300 -s bbb.example.com -e info@example.com -gPrzykłady dostarczane przez projekt przesyłają skrypt bezpośrednio do bash. Należy go pobrać i najpierw przeczytać, ponieważ nadpisuje on konfigurację nginx, instaluje własny stos multimediów i audio, blokuje wersje pakietów oraz przejmuje nazwę hosta. Jest to założenie projektowe, a nie błąd: BigBlueButton wymaga pełnej kontroli nad maszyną. Flaga -w konfiguruje firewall, -s określa nazwę hosta, -e to adres rejestrowany w Let's Encrypt, a -g dodaje interfejs Greenlight. Jeśli na tej samej maszynie działa również terminacja TLS dla innych usług, należy przenieść BigBlueButton w inne miejsce lub upewnić się, że rozumie się działanie konfiguracji reverse proxy nginx przed uruchomieniem skryptu, który ją zmodyfikuje.
Należy uważnie porównać dwa wiersze w tej tabeli. BigBlueButton wymaga dwukrotnie więcej pamięci i rdzeni niż sugeruje Jitsi, przy jednoczesnym zapotrzebowaniu na jedną czwartą przepustowości. Obie wartości nie są mierzone w ten sam sposób i zakładają różne rozmiary pokoi, dlatego należy traktować je jako punkty wyjścia dla każdego projektu, a nie jako bezpośrednie porównanie. Różnica w zapotrzebowaniu na CPU jest rzeczywista i wynika ze wszystkich zadań, które BigBlueButton wykonuje poza samym przesyłaniem wideo.
Galène: lekka alternatywa
Galène to kompaktowy serwer SFU napisany w języku Go. Kompiluje się do pojedynczego statycznego pliku binarnego, zawiera własnego klienta webowego oraz serwer TURN, dzięki czemu nie wymaga serwera XMPP, środowiska uruchomieniowego Java ani aplikacji Rails. Jeśli wymagane jest niezawodne połączenie dla dziesięciu osób na skromnym serwerze, warto przetestować to rozwiązanie przed podjęciem decyzji o zwiększeniu zasobów sprzętowych.
sudo apt update && sudo apt install -y git golang-go
git clone https://github.com/jech/galene
cd galene
CGO_ENABLED=0 go build -ldflags='-s -w'
mkdir groupsPakiet golang-go w systemie Ubuntu 24.04 zawiera Go 1.22. Jeśli go build zgłasza błąd dotyczący wymaganej nowszej wersji Go, należy zainstalować aktualny zestaw narzędzi ze strony go.dev zamiast polegać na wersji z repozytorium dystrybucji.
Grupa (group) to w terminologii Galène odpowiednik pokoju, a jej definicja znajduje się w pliku JSON:
echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &Otwórz https://your.server:8443/group/night-watch/ i zaloguj się jako vimes. Te dane uwierzytelniające pochodzą bezpośrednio z pliku README projektu, dlatego należy je zmienić, zanim port stanie się dostępny z zewnątrz. W przypadku wdrożenia produkcyjnego projekt udostępnia jednostkę systemd:
[Unit]
Description=Galene
After=network.target
[Service]
Type=simple
WorkingDirectory=/home/galene
User=galene
Group=galene
ExecStart=/home/galene/galene
LimitNOFILE=65536
[Install]
WantedBy=multi-user.targetWykorzystywane porty to TCP 8443 dla interfejsu webowego, TCP i UDP 1194 dla wbudowanego serwera TURN oraz zakres wysokich portów UDP dla mediów. Należy ograniczyć ten zakres, aby umożliwić utworzenie pojedynczej reguły firewalla:
./galene -udp-range 40000-40100Opcja -turn jest kluczowa w przypadku VPS. -turn ':1194' nasłuchuje na wszystkich publicznych adresach IPv4. -turn '203.0.113.1:1194' informuje Galène o adresie, który faktycznie zobaczą klienci, co jest niezbędne, gdy adres maszyny jest prywatny. -turn '' wyłącza wbudowany serwer, co pozwala wskazać zewnętrzny serwer za pomocą data/ice-servers.json. Wartością domyślną jest auto, która zachowuje się jak :1194, jeśli nie istnieje ice-servers.json.
Można umieścić nginx przed interfejsem webowym, ustawiając proxyURL w data/config.json i proxyjąc lokalizację /ws z nagłówkami aktualizacji WebSocket. Należy pamiętać o zakresie działania: klienci nadal otwierają bezpośrednie strumienie UDP i połączenia TCP do portu TURN, więc reverse proxy obsługuje jedynie stronę i sygnalizację. Dane multimedialne nigdy nie przechodzą przez proxy.
Dokumentacja Galène wskazuje na bardzo niskie zapotrzebowanie na zasoby serwera i nie podaje konkretnych wartości, więc nie należy oczekiwać sztywnych wytycznych. Powyższe obliczenia dotyczące przepustowości pozostają w pełni aktualne. Oszczędność polega na mniejszym zużyciu pamięci oraz braku konieczności utrzymywania komponentów niezwiązanych bezpośrednio z SFU.
Owncast: jeden do wielu, gdzie przepustowość pozostaje liniowa
Wiele wymagań dotyczących „wideokonferencji” w rzeczywistości sprowadza się do prezentacji jednej osoby dla odbiorców, którzy komunikują się za pomocą czatu. Jeśli tak jest w Twoim przypadku, SFU jest niewłaściwym narzędziem, a ekonomia rozwiązania zmienia się całkowicie. Owncast przyjmuje strumień RTMP z OBS lub podobnego enkodera i udostępnia go przez HLS za pośrednictwem standardowego HTTPS. Przepustowość na widza jest liniowa, a nie kwadratowa. Ponieważ wyjście składa się ze zwykłych segmentów HTTP, można je przenieść za pamięć obiektową lub CDN, eliminując koszty po stronie źródła.
curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.shDokumentacja projektu zaleca, aby nie uruchamiać go jako root oraz sprawdzać każdy zdalny skrypt przed wykonaniem, dlatego pobieranie jest oddzielnym krokiem opisanym powyżej. Instalator pobiera bieżące wydanie oraz binarny plik ffmpeg, jeśli nie jest on już dostępny w systemie. Uruchom ./owncast z katalogu instalacyjnego i otwórz panel administracyjny pod adresem /admin na porcie 8080. Domyślny login to użytkownik admin, a domyślne hasło to abc123. Zmień je przed skierowaniem domeny na serwer.
Z architektury HLS wynikają dwie konsekwencje. Widzowie mają opóźnienie wynoszące kilka sekund lub minut względem transmisji na żywo, ponieważ HLS przesyła całe segmenty, co wyklucza konwersację w czasie rzeczywistym. W ścieżce nie występuje UDP ani TURN, dzięki czemu rozwiązanie działa w sieciach, w których połączenie WebRTC w ogóle nie może zostać nawiązane.
Owncast jest również jedynym narzędziem w tym zestawieniu, które celowo wykonuje transkodowanie. Każda włączona jakość wyjściowa to kolejne kodowanie strumienia wejściowego przez ffmpeg, działające przez cały czas trwania transmisji. Na małym VPS oferuj jedną lub dwie jakości. Pięć jakości spowoduje wysycenie procesora, podczas gdy sieć pozostanie niewykorzystana.
Uruchomienie Element Call na własnym serwerze Matrix
Jeśli posiadasz już serwer Matrix, obsługa wideo stanowi rozszerzenie, a nie odrębny produkt do utrzymania. Nadal jednak wymagane jest więcej niż jedno oprogramowanie. Element Call wymaga dwóch komponentów działających za homeserverem. Pierwszym jest LiveKit SFU, który odpowiada za przekazywanie mediów. Drugim jest usługa autoryzacji MatrixRTC, element-hq/lk-jwt-service, która dostarcza klientowi adres URL WebSocket usługi LiveKit oraz podpisany token JWT (JSON web token) niezbędny do nawiązania połączenia. Usługa ta korzysta z API federacji Matrix, dlatego wymaga umieszczenia przed nią reverse proxy z terminacją TLS oraz nazwy hosta dostępnej dla federacji.
Porty udokumentowane dla LiveKit:
- TCP 7880 dla API oraz klienta WebSocket, za proxy z terminacją TLS
- TCP 7881 dla ICE over TCP, używane, gdy klient nie może nawiązać połączenia przez UDP
- UDP 50000 do 60000 dla mediów, gdzie każdy uczestnik rozmowy wykorzystuje dwa porty
- UDP 3478 oraz TCP 5349 w przypadku włączenia wbudowanego serwera TURN; port 5349 musi zostać przekierowany na 443, chyba że przed serwerem znajduje się load balancer
Dwa porty na uczestnika brzmią groźnie, ale w praktyce tak nie jest. Zakres 10 000 portów wystarcza dla tysięcy uczestników, a przepustowość łącza wyczerpie się znacznie wcześniej niż dostępny zakres portów. Należy otworzyć cały zakres, ponieważ częściowo otwarty zakres powoduje, że połączenie działa u niektórych użytkowników, a u innych nie, co jest najtrudniejszym do zdiagnozowania rodzajem awarii. Konfiguracja po stronie homeserwera to osobne zadanie, opisane w uruchamianiu homeserwera Synapse na VPS.
Dlaczego jedna osoba nigdy nie może się połączyć? TURN i sieci blokujące UDP
Najpierw słowniczek pojęć, użytych tutaj jednokrotnie. ICE (interactive connectivity establishment) to proces, w którym dwa punkty końcowe WebRTC znajdują działającą ścieżkę połączenia. STUN (session traversal utilities for NAT) to niewielka usługa informująca klienta, jak jego publiczny adres wygląda z zewnątrz. TURN (traversal using relays around NAT) to przekaźnik: gdy bezpośrednia ścieżka nie istnieje, obie strony wysyłają media do serwera TURN, który je przekazuje dalej.
TURN jest niezbędny dla uczestników, których sieci są niedostępne. Jedna z takich osób znajduje się w sieci korporacyjnej lub uczelnianej, gdzie ruch wychodzący UDP jest całkowicie blokowany. Inna osoba może znajdować się za NAT-em klasy operatorskiej (carrier-grade NAT), który przypisuje inny port źródłowy dla każdego miejsca docelowego; jest to tzw. symetryczny NAT, który sprawia, że adres zgłoszony przez STUN staje się bezużyteczny.
Objawy są specyficzne. Większość osób dołącza i wszystko działa. Jedna osoba widzi listę uczestników, widzi czat, ale zamiast obrazu widzi czarne pole i ikonę ładowania. Przeglądarka tej osoby zebrała kandydatów, żadna z par nie zadziałała, a proces ICE zakończył się niepowodzeniem. W przeglądarce Chrome, chrome://webrtc-internals otwarte podczas próby połączenia pokazuje pary kandydatów oraz ten błąd. Należy poprosić tę osobę o ponowną próbę połączenia z telefonu korzystającego z danych mobilnych. Jeśli tam działa, przyczyną jest sieć użytkownika, a rozwiązaniem jest TURN.
TURN przez TCP na porcie 443 lub 5349 to mechanizm awaryjny, który działa niemal wszędzie, ponieważ sieć blokująca TLS na porcie 443 blokowałaby również dostęp do stron WWW. Pakiet Jitsi instaluje i konfiguruje coturn automatycznie, dlatego udokumentowane reguły zapory sieciowej obejmują UDP 3478 oraz TCP 5349. Galène ma wbudowany TURN na porcie 1194. LiveKit posiada wbudowany serwer TURN, który włącza się w konfiguracji. W przypadku samodzielnego uruchomienia coturn:
sudo apt install -y coturn
sudo systemctl enable --now coturnlistening-port=3478
tls-listening-port=5349
fingerprint
use-auth-secret
static-auth-secret=REPLACE_WITH_A_LONG_RANDOM_STRING
realm=turn.example.com
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
min-port=49152
max-port=65535
no-multicast-peersPowyższe ustawienia umieszcza się w /etc/turnserver.conf. W systemach Debian i Ubuntu pakiet uruchamia coturn natychmiast po instalacji, korzystając z domyślnej wersji tego pliku, więc enable --now powyżej wykryje, że usługa już działa i nie wprowadzi zmian. Ustawienia zaczną obowiązywać po wykonaniu sudo systemctl restart coturn; każda późniejsza edycja pliku wymaga ponownego restartu. Starsze poradniki zalecają również ustawienie TURNSERVER_ENABLED=1 w /etc/default/coturn. Tylko stary skrypt init odczytuje ten przełącznik. Jednostka systemd, z której korzystają obecne pakiety, tego nie robi, więc ta linia nie zmienia niczego, a coturn, który nie został zrestartowany, nadal korzysta z domyślnej konfiguracji.
Teraz kwestia kosztów, o których nikt nie pisze. Przekaźnik przenosi pełny strumień mediów każdego przekazywanego uczestnika w obu kierunkach. Gdy coturn współdzieli maszynę z SFU, większość tego ruchu przechodzi przez interfejs loopback i obciąża procesor zamiast łącza zewnętrznego, a słuchacz TLS szyfruje każdy pakiet po raz drugi, dodatkowo do szyfrowania DTLS, które media już posiadają. Po przeniesieniu TURN na osobną maszynę, wymaga ona własnego planu przepustowości, zaplanowanego tak samo jak dla SFU. Ponadto TURN przez TCP zmienia media czasu rzeczywistego w strumień niezawodny, więc utracony pakiet jest retransmitowany zamiast pomijany, a uczestnik korzystający z przekaźnika na łączu o słabej jakości odczuje narastające opóźnienie zamiast krótkiego zakłócenia. Przekaźnik to rozwiązanie awaryjne, które zapewnia połączenie, ale o jakości niższej niż w przypadku ścieżki bezpośredniej.
Kiedy SFU wykonuje transkodowanie i jaki jest tego koszt?
SFU przesyła pakiety i nigdy nie dekoduje wideo, dlatego cztery rdzenie procesora mogą obsłużyć pokój, który teoretycznie wydaje się niemożliwy do obsłużenia. Dwie funkcje naruszają tę zasadę i obie zaskakują użytkowników, którzy włączyli je za pomocą pola wyboru.
Pierwszą z nich jest nagrywanie. Jitsi nagrywa przy użyciu Jibri, a dokumentacja Jibri dokładnie opisuje sposób działania: uruchamia instancję Chrome renderowaną w wirtualnym buforze ramki (framebuffer), a następnie przechwytuje i koduje wyjście za pomocą ffmpeg. Jest to pełna przeglądarka renderująca całe spotkanie oraz enkoder wideo, działające w sposób ciągły przez cały czas trwania połączenia. Ta sama dokumentacja stwierdza, że na pojedynczym Jibri obsługiwane jest tylko jedno nagrywanie jednocześnie oraz że Jibri powinno działać na oddzielnej maszynie lub maszynie wirtualnej, na której żadne inne aplikacje nie korzystają z urządzeń wyświetlających ani audio. Nagrywanie to osobny serwer, a nie tylko pole wyboru.
Drugą funkcją jest telefoniczne połączenie przychodzące (dial-in). Mostkowanie linii telefonicznej z konferencją oznacza konwersję dźwięku Opus 48 kHz na format akceptowany przez sieć telefoniczną, zazwyczaj G.711 8 kHz, w obu kierunkach i w sposób ciągły przez cały czas trwania połączenia. Transkodowanie audio jest znacznie tańsze niż transkodowanie wideo, ale odbywa się dla każdej sesji połączenia i nigdy nie jest wstrzymywane, więc koszt rośnie wraz z liczbą dzwoniących. Jeśli wymagany jest numer do połączeń przychodzących, samodzielnie hostowany serwer VoIP jest komponentem, który wykonuje tę pracę i z tego samego powodu co Jibri, powinien znajdować się na oddzielnej maszynie.
Jak dużego serwera faktycznie potrzeba?
Dla dwóch osób wystarczy niemal dowolna maszyna. Jitsi domyślnie włącza tryb peer-to-peer, gdy w konferencji uczestniczą dokładnie dwie osoby. W tym trybie konferencja przestaje przesyłać dane przez videobridge i wykorzystuje bezpośrednie połączenie. Dołączenie trzeciej osoby powoduje powrót do pracy przez most. Dlatego VPS z 1 GB RAM dobrze sprawdzi się jako serwer do rozmów jeden na jeden, ale słabo poradzi sobie z czterema osobami. To wyjaśnia, dlaczego tak często słyszy się opinię: „działało, gdy testowałem”.
Przy maksymalnie dziesięciu osobach z włączonymi kamerami, 67.2 Mbps przy ośmiu uczestnikach mieści się w przepustowości łącza typowego VPS-a. Dwa wirtualne procesory i 4 GB RAM wystarczą do uruchomienia Jitsi lub Galène przy tej skali, pod warunkiem, że nie prowadzi się nagrywania. Należy monitorować licznik transferu, a nie wykres obciążenia CPU.
Dla trzydziestu osób najgorszy scenariusz to 1,044 Mbps ciągłego transferu, co przy dwudziestu godzinach daje 9.4 TB. Przy tej skali najpierw należy wycenić koszt transferu, a dopiero potem serwera. Warto włączyć funkcję last-N, aby most przekazywał tylko obraz od ostatnich mówców, ustawić domyślne wyłączenie kamer dla uczestników i umieścić SFU w lokalizacji z limitem transferu, który wytrzyma takie obliczenia.
Powyżej tej liczby jeden VPS to niewłaściwe rozwiązanie. Jeśli wydarzenie ma charakter transmisji, lepiej użyć Owncast wraz z CDN, co kosztuje ułamek tej kwoty. W przeciwnym razie konieczne jest użycie więcej niż jednego videobridge za pojedynczą warstwą sygnalizacyjną, co stanowi projekt o znacznie większym stopniu złożoności.
Ostatnia uwaga dotycząca routingu. Większość zespołów potrzebuje czatu przez znacznie więcej godzin dziennie niż wideo, a czat jest tani w utrzymaniu i łatwy w obsłudze. Uruchomienie własnej alternatywy dla Slack do codziennej komunikacji i utrzymywanie serwera konferencyjnego wyłącznie do zaplanowanych rozmów to układ, który pozwala zmieścić się w budżecie małego VPS-a.
FAQ
Dlaczego uczestnicy mogą dołączyć do spotkania Jitsi, ale nie widzą ani nie słyszą się nawzajem?
Czat i lista uczestników przesyłane są kanałem sygnalizacyjnym, który wykorzystuje TCP na porcie 443, natomiast audio i wideo korzystają z UDP 10000 do videobridge. Jeśli lista uczestników się zapełnia, a wszystkie okna wideo pozostają czarne, oznacza to, że ścieżka mediów jest przerwana, mimo poprawnego działania sygnalizacji. Sprawdź port UDP 10000 w obu zaporach sieciowych: tej działającej na serwerze oraz zewnętrznej zaporze w panelu sterowania dostawcy. Następnie zweryfikuj, czy bridge rozpoznaje swój publiczny adres IP: na maszynie wirtualnej z prywatnym adresem i przypisanym adresem publicznym, dodaj statyczne mapowanie w ice4j.harvest.mapping w pliku /etc/jitsi/videobridge/jvb.conf i zrestartuj jitsi-videobridge2. Uruchomienie sudo tcpdump -ni any udp port 10000 podczas dołączania uczestnika pozwoli ustalić przyczynę, ponieważ brak jakichkolwiek pakietów oznacza, że blokada występuje przed systemem operacyjnym.
Jaką przepustowość zużywa wideokonferencja dla 30 osób?
W najgorszym scenariuszu, gdy każdy ma włączoną kamerę, a SFU przesyła strumień pełnej jakości do każdego uczestnika, serwer opuszcza około 1,044 Mbps, co daje 469.8 GB na godzinę. Jest to wyliczenie matematyczne oparte na N razy (N minus 1) strumieni po 1.2 Mbps każdy, a nie pomiar rzeczywistego obciążenia. Mechanizmy simulcast oraz ustawienie last-N znacząco redukują to zużycie w typowych warunkach, ponieważ większość uczestników nie jest wyświetlana na ekranie w tym samym czasie. Mimo to należy planować zasoby pod kątem najgorszego scenariusza, ponieważ podczas spotkań ogólnych wszyscy użytkownicy mogą jednocześnie włączyć kamery.
Czy mogę uruchomić Jitsi Meet na VPS z 1 GB pamięci RAM?
Instalacja zakończy się powodzeniem, a połączenie dwuosobowe będzie działać, częściowo dlatego, że Jitsi używa trybu peer-to-peer dla dokładnie dwóch uczestników, całkowicie pomijając videobridge. Nie jest to jednak użyteczny serwer do połączeń grupowych. Prosody, videobridge oraz środowisko uruchomieniowe Java wymagają znacznych zasobów pamięci; oficjalna dokumentacja zaleca 8 GB dla poważnych wdrożeń, a ograniczenia przepustowości staną się problemem szybciej niż brak pamięci RAM. Jeśli dysponujesz jedynie maszyną z 1 GB pamięci, Galène będzie lepszym wyborem niż Jitsi.
Czy nadal potrzebuję serwera TURN, jeśli mój VPS ma publiczny adres IP?
Tak. Problem, który rozwiązuje TURN, występuje po drugiej stronie połączenia. Uczestnik znajdujący się w sieci korporacyjnej blokującej ruch wychodzący UDP lub za NAT-em klasy operatorskiej, który przypisuje inny port źródłowy dla każdego miejsca docelowego, nie będzie w stanie nawiązać bezpośredniej ścieżki mediów, niezależnie od tego, jak publiczny jest adres Twojego serwera. TURN przez TCP na porcie 443 lub 5349 zapewnia przekaźnik, który dla zapory sieciowej wygląda jak zwykły ruch internetowy. Pakiet instalacyjny Jitsi domyślnie konfiguruje coturn, dlatego udokumentowane reguły zapory sieciowej otwierają porty UDP 3478 oraz TCP 5349.
Dlaczego BigBlueButton wymaga znacznie mocniejszego sprzętu niż Jitsi Meet?
Ponieważ wykonuje znacznie więcej zadań niż tylko przekazywanie wideo. Publikowane wymagania produkcyjne to 16 GB pamięci RAM oraz 8 rdzeni procesora, w porównaniu do 8 GB i 4 rdzeni w dokumentacji Jitsi. BigBlueButton uruchamia pełny stos konferencji audio, współdzieloną tablicę, warstwę prezentacji, potok nagrywania i przetwarzania końcowego oraz interfejs webowy z kontami użytkowników, wszystko na tej samej maszynie. Projekt ma również określone wymagania co do platformy: według stanu na sierpień 2026 wspieraną wersją instalacyjną jest 3.0 na Ubuntu 22.04. Obie wartości pochodzą z dokumentacji poszczególnych projektów i stanowią punkty wyjścia, a nie pomiary Twojego rzeczywistego obciążenia.