From c53ad95104509824a410b109401a72e769bff727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Zatorski?= Date: Mon, 28 Sep 2026 09:16:01 +0200 Subject: [PATCH] LiveKit: jeden port UDP dla wszystkich (mux) zamiast zakresu Zakres port_range 50000-50100 rezerwowal osobny port na kazde polaczenie. Test z 200 botami wszedl dokladnie w 49, a log serwera pokazal kandydata UDP tylko przy 52 polaczeniach i TCP przy wszystkich 204: kolejni uczestnicy dostawali juz tylko TCP. Zmienna UDP_PORT z zakresem nie wlaczala muxa, bo przegrywala z zakresem z pliku. Teraz udp_port: 7882 (sprawdzone lokalnie: rtc.portUDP Start 7882, End 0), nowa zmienna LIVEKIT_UDP_PORT, zeby stara LIVEKIT_UDP_RANGE w .env nie mogla przywrocic zakresu. Automatyczne wdrozenie nie dotyka profilu livekit: kontener trzeba przeladowac recznie. Co-Authored-By: Claude Opus 5.5 --- .env.production.example | 6 ++++-- CLAUDE.md | 11 ++++++++++- DEPLOYMENT_CHECKLIST.md | 2 +- README.md | 18 ++++++++++-------- docker-compose.prod.yml | 10 +++++----- docker-compose.yml | 19 +++++++++---------- livekit/livekit.yaml | 28 ++++++++++++++++++---------- 7 files changed, 57 insertions(+), 37 deletions(-) diff --git a/.env.production.example b/.env.production.example index 7898c23..563bebd 100644 --- a/.env.production.example +++ b/.env.production.example @@ -148,10 +148,12 @@ LIVEKIT_API_KEY= LIVEKIT_API_SECRET= # Porty serwera. UDP jest **glowna droga ruchu audio i wideo**: bez otwarcia -# tego zakresu uczestnicy dolacza do pokoju, ale nie beda sie slyszec. +# tego portu uczestnicy dolacza do pokoju, ale nie beda sie slyszec. +# Jeden port UDP dla wszystkich uczestnikow (tryb mux). Dawny zakres +# LIVEKIT_UDP_RANGE konczyl sie po okolo 50 osobach i nie jest juz czytany. LIVEKIT_PORT=7880 LIVEKIT_TCP_PORT=7881 -LIVEKIT_UDP_RANGE=50000-50100 +LIVEKIT_UDP_PORT=7882 # TURN: przekazuje ruch uczestnikom za restrykcyjnym NAT-em, czyli w praktyce # wiekszosci osob w sieciach firmowych. Bez niego czesc uczestnikow nie diff --git a/CLAUDE.md b/CLAUDE.md index 9475ff2..1d94701 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2040,10 +2040,19 @@ Wlaczenie: `docker compose --profile livekit up -d`. - **Wersja serwera musi nadazac za `livekit-client`.** Klient 2.22 laczy sie sciezka `/rtc/v1`, ktorej serwer 1.8 nie zna: sala wyglada na dzialajaca, ale nie plynie ani obraz, ani dzwiek. Obraz przypiety do `v1.13`. -- **Zakres UDP 50000-50100 musi byc otwarty.** To glowna droga audio i wideo. +- **Port UDP 7882 musi byc otwarty.** To glowna droga audio i wideo. Bez niego uczestnicy dolacza do pokoju i zobacza liste obecnych, ale nie beda sie slyszec: to najczestsza przyczyna zgloszenia "wideo nie dziala" przy poprawnie skonfigurowanym serwerze. +- **Jeden port UDP dla wszystkich (`udp_port`, tryb mux), NIGDY zakres.** + Przy `port_range_start/end` serwer rezerwuje osobny port na kazde polaczenie. + Zakres 50000-50100 konczyl sie po okolo 50 uczestnikach: test z 200 botami + wszedl dokladnie w 49, a log serwera pokazal kandydata UDP tylko przy 52 + polaczeniach i TCP przy wszystkich 204. Przegladarka wchodzi wtedy po TCP + (zacinajacy sie obraz przy utracie pakietow), klient bez ICE-TCP nie wchodzi. + **Zmienna `UDP_PORT` z zakresem nie wlaczala muxa**: przegrywala z zakresem + z pliku, a wczesniejsza analiza wziela ja za dzialajacy mux. Rozstrzyga log: + `connectionType` i kandydaci `[local]` przy wejsciu uczestnika. - **coturn dziala w `network_mode: host`**, bo TURN musi widziec prawdziwe adresy IP. Za NAT-em Dockera rozdawalby uczestnikom adresy wewnetrzne kontenera, pod ktore nikt z zewnatrz sie nie polaczy. diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md index 6b24201..9f0bb9c 100644 --- a/DEPLOYMENT_CHECKLIST.md +++ b/DEPLOYMENT_CHECKLIST.md @@ -22,7 +22,7 @@ z testow nie trafi do prawdziwych ludzi. | A3 | Sprawdzic DNS domeny: `dig +short webinary.klient.pl` | adres IP serwera | | A4 | Sprawdzic certyfikat SSL na reverse proxy klienta | waznosc powyzej 14 dni | | A5 | Porty otwarte na firewallu: 80, 443 | dostepne z internetu | -| A6 | Przy `VIDEO_PROVIDER=LIVEKIT`: dodatkowo 7880, 7881 TCP oraz **zakres UDP** (domyslnie 50000-50100) | dostepne z internetu | +| A6 | Przy `VIDEO_PROVIDER=LIVEKIT`: dodatkowo 7880, 7881 TCP oraz **port UDP 7882** (tryb mux, jeden port dla wszystkich) | dostepne z internetu | **A6 jest najczestszym przeoczeniem.** Bez otwartego zakresu UDP uczestnicy wchodza do pokoju i widza liste obecnych, ale **sie nie slysza**. Objaw wyglada jak awaria diff --git a/README.md b/README.md index 0d81852..e4e1fdc 100644 --- a/README.md +++ b/README.md @@ -690,10 +690,10 @@ serwer, w panelu sluza do podpisywania tokenow wejscia. | --- | --- | --- | | 7880 | TCP | sygnalizacja WebSocket i API serwera | | 7881 | TCP | media po TCP, droga zapasowa gdy UDP jest zablokowane | -| 50000-50100 | **UDP** | **glowna droga audio i wideo** | +| 7882 | **UDP** | **glowna droga audio i wideo**, jeden port dla wszystkich (mux) | | 49160-49200 | UDP | TURN, dla uczestnikow za restrykcyjnym NAT-em | -**Zakres UDP jest obowiazkowy.** Bez niego uczestnicy dolacza do pokoju i zobacza +**Port UDP jest obowiazkowy.** Bez niego uczestnicy dolacza do pokoju i zobacza liste obecnych, ale nie beda sie slyszec ani widziec. To najczestsza przyczyna zgloszenia "wideo nie dziala" przy poprawnie skonfigurowanym serwerze. @@ -705,13 +705,15 @@ IP: za NAT-em Dockera rozdawalby uczestnikom adresy wewnetrzne kontenera. Zebrane przy uruchomieniu profilu na zywo. **Kazda z nich blokuje pierwsze wdrozenie**, a zadna nie daje czytelnego komunikatu. -**1. Zakres portow UDP musi byc wolny w systemie.** +**1. Port UDP musi byc wolny w systemie, a serwer ma pracowac w trybie mux.** Windows rezerwuje zakresy dla Hyper-V i WSL (sprawdzenie: -`netsh interface ipv4 show excludedportrange protocol=udp`). Domyslne -50000-50100 wpada w rezerwacje 50000-50059 i kontener nie wstaje z bledem -"ports are not available". Zmiana `LIVEKIT_UDP_RANGE` w `.env` wystarcza: -zakres idzie do serwera zmienna `UDP_PORT` i **musi byc taki sam po obu -stronach mapowania portow**, inaczej Docker odrzuca konfiguracje. +`netsh interface ipv4 show excludedportrange protocol=udp`); gdy 7882 jest +zajety, kontener nie wstaje z bledem "ports are not available". Zmiana +`LIVEKIT_UDP_PORT` w `.env` wystarcza: port idzie do serwera zmienna `UDP_PORT` +i **musi byc taki sam po obu stronach mapowania portow**. +**Nie wracac do zakresu portow** (`port_range_start/end`): serwer rezerwuje +wtedy osobny port na kazde polaczenie i przy zakresie 50000-50100 konczyl pule +po okolo 50 uczestnikach. Kolejni dostawali juz tylko TCP. **2. `use_external_ip: true` nadpisuje `NODE_IP`.** Przy uruchomieniu lokalnym serwer wykrywa publiczny adres lacza i rozglasza go diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 697f9eb..ac60b25 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -187,7 +187,7 @@ services: - ./livekit/livekit.yaml:/etc/livekit.yaml:ro environment: LIVEKIT_KEYS: "${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}" - UDP_PORT: ${LIVEKIT_UDP_RANGE:-50000-50100} + UDP_PORT: ${LIVEKIT_UDP_PORT:-7882} # NA PRODUKCJI: publiczny adres IP serwera. Bez niego uczestnicy wchodza # do pokoju i sie nie slysza, bo serwer rozglasza adres nieosiagalny # z internetu. Ustawienie `use_external_ip: true` w livekit.yaml @@ -198,10 +198,10 @@ services: - "${LIVEKIT_PORT:-7880}:7880" # RTC po TCP: droga zapasowa, gdy UDP jest zablokowane w sieci klienta - "${LIVEKIT_TCP_PORT:-7881}:7881" - # MEDIA PO UDP: to jest glowna droga audio i wideo. Bez otwarcia tego - # zakresu na firewallu serwera uczestnicy widza liste obecnych, ale - # sie nie slysza. Najczestsza przyczyna zgloszenia "wideo nie dziala". - - "${LIVEKIT_UDP_RANGE:-50000-50100}:${LIVEKIT_UDP_RANGE:-50000-50100}/udp" + # MEDIA PO UDP: to jest glowna droga audio i wideo. Jeden port dla + # wszystkich (tryb mux, opis w livekit.yaml). Bez otwarcia go na + # firewallu serwera uczestnicy widza liste obecnych, ale sie nie slysza. + - "${LIVEKIT_UDP_PORT:-7882}:${LIVEKIT_UDP_PORT:-7882}/udp" logging: driver: json-file options: diff --git a/docker-compose.yml b/docker-compose.yml index bc1c768..164ec39 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -114,11 +114,11 @@ services: - ./livekit/livekit.yaml:/etc/livekit.yaml:ro environment: LIVEKIT_KEYS: "${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}" - # Zakres portow UDP. Ma pierwszenstwo przed wartoscia w livekit.yaml, - # bo serwer nie rozwija zmiennych w pliku konfiguracyjnym. Instancja, - # ktora musi ominac porty zajete w systemie (na Windows sa rezerwacje - # Hyper-V), zmienia wylacznie LIVEKIT_UDP_RANGE w .env. - UDP_PORT: ${LIVEKIT_UDP_RANGE:-50000-50100} + # Jeden port UDP dla wszystkich uczestnikow (tryb mux), opis + # w livekit.yaml. Ma pierwszenstwo przed wartoscia z pliku, bo serwer nie + # rozwija zmiennych w pliku konfiguracyjnym. Instancja z zajetym portem + # zmienia wylacznie LIVEKIT_UDP_PORT w .env. + UDP_PORT: ${LIVEKIT_UDP_PORT:-7882} # Adres rozglaszany uczestnikom. Przy uruchomieniu lokalnym ustaw # NODE_IP=127.0.0.1 w .env: bez tego serwer rozglasza publiczny adres # lacza, a przegladarka na tej samej maszynie nie zestawi polaczenia. @@ -129,11 +129,10 @@ services: # RTC po TCP: droga zapasowa, gdy UDP jest zablokowane w sieci klienta - "${LIVEKIT_TCP_PORT:-7881}:7881" # media po UDP. To jest **glowna** droga ruchu audio i wideo: - # bez tego zakresu uczestnicy widza sie, ale sie nie slysza - # Ten sam zakres po obu stronach: UDP_PORT ustawia go wewnatrz - # kontenera, wiec mapowanie musi go odwzorowac jeden do jednego. - # Rozjechanie stron konczy sie bledem "invalid ranges specified". - - "${LIVEKIT_UDP_RANGE:-50000-50100}:${LIVEKIT_UDP_RANGE:-50000-50100}/udp" + # bez tego portu uczestnicy widza sie, ale sie nie slysza. + # Ten sam numer po obu stronach: UDP_PORT ustawia go wewnatrz kontenera, + # a serwer rozglasza uczestnikom wlasnie ten numer. + - "${LIVEKIT_UDP_PORT:-7882}:${LIVEKIT_UDP_PORT:-7882}/udp" # TURN: przekazuje ruch, gdy polaczenie bezposrednie jest niemozliwe. # diff --git a/livekit/livekit.yaml b/livekit/livekit.yaml index ea365cb..7507090 100644 --- a/livekit/livekit.yaml +++ b/livekit/livekit.yaml @@ -6,18 +6,26 @@ port: 7880 rtc: - # Zakres portow UDP. + # JEDEN PORT UDP DLA WSZYSTKICH (tryb mux). # - # **Serwer NIE rozwija zmiennych srodowiskowych w tym pliku**, wiec wartosci - # sa tu wpisane wprost. Zakres przekazywany jest dodatkowo zmienna UDP_PORT - # w docker-compose i to ona ma pierwszenstwo: dzieki temu instancja, ktora - # musi ominac porty zajete w systemie, zmienia jedna wartosc w .env, - # zamiast edytowac ten plik. + # Wczesniej byl tu zakres `port_range_start/end` 50000-50100. W tym trybie + # serwer REZERWUJE OSOBNY PORT NA KAZDE POLACZENIE, a uczestnik ma ich do + # dwoch. Test z botami pokazal skutek: po okolo 50 osobach pula sie konczyla + # i kolejni dostawali juz tylko kandydata TCP na 7881. Przegladarka wchodzi + # wtedy po TCP (zacinajacy sie obraz i dzwiek przy kazdej utracie pakietu), + # klient bez obslugi ICE-TCP nie wchodzi wcale. Zmienna UDP_PORT z zakresem + # NIE wlaczala muxa: przegrywala z zakresem z tego pliku. # - # Musi zgadzac sie z mapowaniem portow w docker-compose i byc otwarty - # na firewallu. To jest glowna droga ruchu audio i wideo. - port_range_start: 50000 - port_range_end: 50100 + # W trybie mux wszyscy uczestnicy dziela jeden port, rozrozniani po + # identyfikatorze sesji ICE. Liczba osob nie zalezy juz od liczby portow. + # + # **Serwer NIE rozwija zmiennych srodowiskowych w tym pliku.** Port idzie + # takze zmienna UDP_PORT z docker-compose i ona ma pierwszenstwo, wiec + # instancja z zajetym 7882 zmienia jedna wartosc w .env (LIVEKIT_UDP_PORT). + # **Nie dopisywac tu z powrotem port_range_start/end**: zakres wylacza mux. + # + # Port musi byc otwarty na firewallu. To glowna droga ruchu audio i wideo. + udp_port: 7882 tcp_port: 7881 # Adres, ktory serwer rozglasza uczestnikom jako swoj. #