1
KATEDRA SYSTEMÓW MULTIMEDIALNYCH
LABORATORIUM
SYSTEMY I TERMINALE MULTIMEDIALNE
Transmisja dźwięku i obrazu z wykorzystaniem
technologii WebRTC
Opracowanie:
Łukasz Kosikowski
Paweł Spaleniak
1. Wprowadzenie
1.1 WebRTC
WebRTC [1] to otwarty standard komunikacji w czasie rzeczywistym rozwijany przede wszystkim przez Google i Mozilla. Umożliwia komunikację bez użycia dodatkowych wtyczek (ang. plugins) w przeglądarkach, które go implementują. Wykorzystanie WebRTC API JavaScript pozwala na realizację komunikacji między przeglądarkami w sieci Internet, w szczególności transmisję audio i video oraz przesyłanie danych (w tym plików). Od czasu wydania przez Google wszystkich patentów w ramach wolnej od opłat i publicznej licencji, która umożliwiła implementację kodeka w innych niż Google Chrome przeglądarkach internetowych, obowiązującym kodekiem wizyjnym w standardzie WebRTC jest kodek VP8.
1.2 WebSocket
WebSocket, to protokół komunikacyjny opracowany na potrzeby komunikacji głównie serwera z przeglądarkami internetowymi. Podstawową cechą protokołu jest komunikacja dwukierunkowa, pomiędzy serwerem, a klientem (przeglądarka internetową). Połączenie pomiędzy przeglądarka, a serwerem WebSocket jest podtrzymywane, dlatego w dowolnej chwili istnieje możliwość wysłania komunikatu z przeglądarki do serwera jak i od serwera do przeglądarki. Zadaniem klienta wykorzystującego ten sposób komunikacji jest nawiązanie i podtrzymywanie połączenie z serwerem (w razie konieczności, również, jego ponowne nawiązanie).
2
1.3 Serwer konferencyjny
Do wstępnej komunikacji (sygnalizacyjnej) pomiędzy dwoma użytkownikami końcowymi WebRTC wymagany jest serwer konferencyjny (ang. Web Conferencing Serwer), przy pomocy którego następuje wymiana komunikatów, służących do nawiązania bezpośredniej lub pośredniej sesji, pomiędzy użytkownikami.
1.4 Serwer STUN
Serwer STUN [2] (ang. Simple Traversal of User Datagram Protocol [UDP] through Network Address Translators [NATs]) umożliwia klientom, zlokalizowanym w podsieciach z dynamiczną translacją prywatnych adresów sieciowych na adresy zewnętrzne, ustanowienie połączeń z operatorem VOIP zlokalizowanym poza siecią prywatną. Według dokumentacji RFC, port oraz adres IP serwera STUN są dowolne, natomiast zalecanym portem jest port 3478.
W trakcie ćwiczenia będzie wykorzystywany bezpośredni model transmisji danych multimedialnych pomiędzy użytkownikami (ang. peers) wykorzystujący topologię peer-topeer (p2p). Ten model transmisji jest realizowany przy pomocy serwera pośredniczącego (serwera konferencyjnego). Topologię połączenia przedstawiono na rysunku Rys. 1.
Rys. 1. Schemat prostej topologii WebRTC
1.5 SDP
SDP [3] (ang. Session Description Protocol), to format opisujący parametry inicjalizacyjne sesji transmisji medialnych. SDP zawiera informacje o rodzajach mediów, kodekach i ich parametrach, adresach IP, kierunku strumieni, dostępnym pasmie i in.. Został zdefiniowany w normie RFC 2327.
Serwer pośredniczący Przeglądarka Przeglądarka Użytkownik 2 Użytkownik 1 JS API JS API Sygnalizacja Sygnalizacja Media
3
1.5.1 Wybrane parametry SDP
Deskryptor sesji:
• v = [protocol version]
• o = [originator and session identifier] – źródło i identyfikator sesji
• (dowolna nazwa) (id sesji) (wersja sesji) IN (IP4|IP6) (adres IP źródła sesji)
• c = [connection information] – opis połączenia, nie wymagany IN (IP4|IP6) (adres IP) • b = [zero or more bandwidth information lines] – sugerowane pasmo
• zero lub więcej deskryptorów czasu
• a = [zero or more session attribute lines] – atrybuty:
o sendonly – jeśli dana strona chce tylko wysyłać media, o recvonly – jeśli dana strona chce tylko odbierać media, o inactive – brak mediów,
o sendrecv – jeśli dana strona chce wysyłać i odbierać media • zero lub więcej deskryptorów mediów
Deskryptor mediów:
• m = [media name and transport address] – opis mediów (audio|video|text) RTP/AVP (opis danych medialnych)
• c = [connection information] – opis połączenia, nie wymagany, jeśli jest obecny w opisie sesji • b = [zero or more bandwidth information lines] – sugerowane pasmo
• a = [zero or more media attribute lines] – atrybuty strumienia, nadpisują atrybuty zdefiniowane w opisie sesji:
o sendonly – jeśli dana strona tylko chce wysyłać media, o recvonly – jeśli dana strona chce tylko odbierać media, o inactive – brak mediów,
o sendrecv – jeśli strona chce wysyłać i odbierać media, o rtcp – port dla rtcp,
o ptime – długość mediów w sekundach, w przesyłanym pakiecie, o rtpmap – mapuje numer typu zawartości do konkretnego kodeka i jego
częstotliwości,
o fmtp – umożliwia mapowanie parametrów tak aby warstwa SDP nie musiało tego interpretować
Nawiązanie bezpośredniego połączenia pomiędzy użytkownikami (ang. peers)
Użytkownik A (Peer A) ustala przy pomocy serwera STUN swój zewnętrzny adres IP i port poprzez który może odbywać się transmisja bezpośrednia. Po otrzymaniu tych danych, tworzy tzw. ofertę (ang. offer) i przy pomocy serwera pośredniczącego (poprzez Signaling Channel) przesyła ją do użytkownika B (Peer B). Użytkownik B, poprzez serwer pośredniczący, odsyła odpowiedz (ang. answer) na ofertę. Następnie, również poprzez serwer pośredniczący następuje negocjacja dotycząca sposobu i parametrów ustanowienia połączenia pomiędzy użytkownikami tzw. negocjacja ICE (ang. Internet Connectivity Establishment). Podczas tej negocjacji wymieniane są informacje o możliwością połączenia bezpośredniego pomiędzy użytkownikami lub pośredniego z wykorzystaniem serwera TURN (połączenie pośrednie nie jest tematem niniejszego ćwiczenia). Ogólny schemat przebiegu negocjacji z wykorzystaniem protokołu SDP przedstawiono na rysunku Rys. 2.
4
Rys. 2. Ogólny schemat negocjacji połącznia przy użyciu m.in. protokołu SDP
1.6
WebRTC JavaScript API
WebRTC JavaScript API znajduje się w fazie ciągłego rozwoju, dlatego każda przeglądarka stosuje swoje przedrostki do standardowych nazw interfejsów opisujących wykorzystywanych w standardzie WebRTC. To podejście jest również nieustannie modyfikowane.
Podstawowym zestawem interfejsów w standardzie WebRTC jest zbiór:
• RTCPeerConnection [4] – Interfejs reprezentujący połączenie pomiędzy lokalnym i zdalnym komputerem
• RTCIceCandidate [5] – Interfejs reprezentujący parametry kandydata ICE służący nawiązaniu RTCPeerConnection.
• RTCSessionDescription [6] – Interfejs opisujący parametry sesji. Wybrane nazwy interfejsów w różnych przeglądarkach:
• Chrome:
o RTCPeerConnection -> webkitRTCPeerConnection • Firefox:
o RTCPeerConnection -> mozRTCPeerConnection
Istotną metodą, która umożliwia dostęp do urządzeń źródłowych (kamery i mikrofonu) jest metoda getUserMedia [7].
Metoda getUserMedia jest eksportowana w przeglądarkach w następujący sposób: • Chrome:
o navigator.webkitGetUserMedia • Firefox:
5
Ze względu na różnice w interfejsie WebRTC pomiędzy przeglądarkami, dobrym zwyczajem jest implementacja adaptera, który ujednolica korzystanie z interfejsu dla różnych przeglądarek. Przykładowa implementacja adaptera:
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
1.7
Node.js
Node.js jest platformą umożliwiającą uruchomienie kodu JavaScript. Platforma udostępnia API, którego najszerszym (lecz nie jedynym) zastosowaniem jest tworzenie stron internetowych opartych na programowaniu sterowanym zdarzeniami. Poza samą możliwością uruchomienia skryptów JavaScript w środowisku innym niż przeglądarka, platforma oferuje wiele modułów stanowiących potężny zestaw narzędzi programistycznych.
1.7.1 Charakterystyka Node.js
• Asynchroniczność. W architekturzeprogramowania sterowanego zdarzeniami czas występowania zdarzeń oraz ich kolejność nie są określone. Pojawiające się zdarzenia są obsługiwane kiedy tylko dostępne są wolne zasoby. Takie podejście skutkuje lepszym wykorzystaniem zasobów oraz większą separacją kodu i luźnym powiązaniem komponentów (loose coupling).
• Unifikacja kodu po stronie klienta i serwera. Używanie tego samego języka programowania po obu stronach połączenia pozwala uniknąć koniecznego w innych wypadkach
duplikowania logiki fragmentów aplikacji.
• V8 czyli otwarty silnik JavaScript stworzony na potrzeby Google Chrome. Silnik nie interpretuje kodu JavaScript w czasie rzeczywistym, a kompiluje kod do kodu maszynowego, co zwiększa wydajność. Następnie ma miejsce proces optymalizacji wykonania między innymi przez usuwanie “martwego” kodu, czy przewidywanie rozgałęzień wykonania pętli. Zarządzaniem pamięcią zajmuje się wydajny odśmiecacz. • npm - menadżer pakietów dla node.js
używany do instalacji rozszerzeń. Node.js rozwija się bardzo dynamicznie - obecnie npm zawiera ponad 250 tys. pakietów, a ich liczba wciąż rośnie.
2. Informacje dodatkowe
2.1
Domyślne ustawienia portów
Dla serwera HTTP domyślnym portem jest port: 8080 Dla serwera WebSocket domyślnym portem jest port: 8081
2.2
Zmiana urządzenia źródłowego i nadawanie praw dostępu do urządzeń
Wybór/zmiana urządzenia (mikrofonu i kamery) odbywa się poprzez menu opcji dostępnym po kliknięciu na symbol kamery (lub przekreślonej kamery jeśli zabroniono wcześniej dostępu do
6
urządzeń dla danego adresu internetowego) znajdujący się po prawej stronie paska adresu przeglądarki Chrome (patrz Rys. 3).
Rys. 3. Zmiana urządzenia źródłowego w przeglądarce Chrome
2.3
Modyfikacja kodu
Modyfikacje kodu aplikacji wykonaj w dowolnym edytorze tekstowym zainstalowanym na komputerze (np. Notepad++, Visual Studio Code)
2.4
Skróty klawiaturowe
7
3. Zadania do wykonania
Wymagania do realizacji zadań
PC lub Mac z zainstalowanym node.js, przeglądarka Chrome lub Firefox, kamera, mikrofon
Do wykonania poniższych zadań niezbędne jest pobranie paczki z plikami oraz zainstalowanie środowiska node.js na komputerze (do pobrania pod tym linkiem).
W paczce znajdują się następujące pliki:
• Odpowiedzialne za działanie lokalnego serwera: server.js, package.json oraz folder
node_modules
• Odpowiedzialne za widok aplikacji klienta w katalogu public: index.html oraz foldery js, img, css
3.1
Uruchomienie lokalnego serwera (node.js) – 2 pkt
Celem tego zadania jest uruchomienie własnego serwera lokalnego obsługującego protokoły http oraz wss (WebSocket).
W konsoli (terminalu) przejdź do folderu, w którym znajduje się plik server.js 3.1.1 Uruchom aplikację serwerową wywołując polecenie
node server.js
Uwaga: Aby zakończyć dziłanie serwera należy w terminalu użyć kombinacji klawiszy CTRL+C
3.1.2 Uruchom przeglądarkę internetową i wpisz adres: localhost:8080/index.html
Co wyświetliło się na stronie?
3.1.3 Uruchom przeglądarkę internetową i wpisz adres: localhost:8080/index
Co wyświetliło się na stronie i jaka jest tego przyczyna? Jaki błąd został zwrócony i co oznacza?
3.1.4 Otwórz plik server.js w dowolnym edytorze kodu (polecane Visual Studio Code lub
Notepad++). Zapoznaj się z kodem i komentarzami. Czy możliwe jest uruchomienie serwera http i WebSocket na tym samym porcie. Co otrzymujemy w wyniku takiej próby i co to oznacza?
UWAGA: Zmiany w pliku server.js wymagają zatrzymania i ponownego uruchomienia serwera
– patrz 3.1.1
3.2
Komunikacja Peer to Peer (html + javascript) – 8 pkt
W tej części zadanie polega na utworzeniu połączenia między dwoma użytkownikami (wirtualnymi) oraz przesłanie za jego pomocą strumienia audio i wideo przechwyconego z kamery. Do dyspozycji w paczce z plikami oddano szkielet aplikacji klienckiej. Edytowane pliki: index.html oraz
8
3.2.1 Otwórz pliki index.html oraz main.js w dowolnym edytorze kodu. Przeanalizuj zarówno sam kod, jak i komentarze. Upewnij się, że serwer lokalny jest uruchomiony. Są one częścią widoku klienta, który powinien prezentować się jak na obrazku poniżej.
Rys. 4. Widok aplikacji klienta do testowania połączenia z serwerem WebSocket oraz komunikacji peer-to-peer
Sprawdzanie stanu połączenia z serwerem WebSocket
Nawiązanie połączenia z serwerem WebSocket następuje wraz z kliknięciem przycisku Start w widoku klienta (uruchamiana jest funkcja async function start() w pliku main.js). Ta sama
funkcja wywołuje żądanie przechwycenia strumienia mediów (należy pozwolić przeglądarce na dostęp do odpowiednich urządzeń kiedy o to poprosi)
Zaprezentuj w widoku klienta aktualny stan połączenia z serwerem WebSocket.
Wykorzystaj do tego obiekt:
<span id="wss-status-txt"> </span> Przydatne funkcje:
onOpenConnection // zdefiniowane w kodzie w main.js onCloseConnection // zdefiniowane w kodzie w main.js WebSocket.readyState
9
3.2.2 Rozbuduj funkcję start() o możliwość wyświetlenia przechwytywanego strumienia w obiekcie:
<video id="localVideo" playsinline autoplay muted></video> Przydatne funkcje:
MediaDevices.getUserMedia() HTMLMediaElement.srcObject
3.2.3 Analizując kod funkcji async function call() opisz, najlepiej w formie schematu, proces
zestawiania połączenia peer-to-peer. Wykorzystaj do tego nazwy funkcji użyte w pliku oraz wiedzę z części teoretycznej niniejszej instrukcji.
3.2.4 Rozbuduj funkcję gotRemoteStream(e) o możliwość wyświetlenia przechwytywanego
strumienia w obiekcie:
<video id="remoteVideo" playsinline autoplay></video> Przydatne funkcje:
HTMLMediaElement.srcObject
Podpowiedź: Event zwraca tablicę strumieni
3.2.5 Zanotuj kilka wybranych parametrów protokołu SDP wymienianych przez klientów poprzez połączenie p2p (wykorzystaj do tego logi z konsoli przeglądarki). W szczególności zwróć uwagę na deskryptor mediów. Jakie kodeki pojawiają się podczas negocjacji połączenia?
3.2.6 Wymuś transmisję samego obrazu oraz samego dźwięku. Który element kodu za to odpowiada?
3.2.7 Wnioski i proponowane usprawnienia aplikacji.
PO ZAKOŃCZONEJ PRACY:
Wynikowy kod źródłowy oraz plik PDF ze sprawozdaniem należy spakować do ZIP i umieścić w
10
4. Literatura
[1] WebRTC RFC: https://tools.ietf.org/html/rfc7478 [2] STUN RFC: http://www.ietf.org/rfc/rfc3489.txt [3] SDP RFC: https://www.ietf.org/rfc/rfc2327.txt
[4] RTCPeerConnection API Reference: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection
[5] RTCIceCandidate API Reference: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate
[6] RTCSessionDescription API Reference: https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription
[7] getUserMedia Method Reference:
https://developer.mozilla.org/pl/docs/Web/API/Navigator/getUserMedia [8] Unix system errors,
http://wwwnumi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors .html
[9] Node.js API Reference: https://nodejs.org/dist/latest-v4.x/docs/api/
[10] WebRTC Integrator's Guide, https://books.google.pl/books?id=rdskBQAAQBAJ, Packt Publishing Ltd, Oct 31, 2014