Dzisiejszy wpis jest kontynuacją wpisu sprzed dwóch lat o tytule Dockeryzacja aplikacji z graficznym interfejsem użytkownika. Wtedy poświęciłem kilka chwil na opisaniu, w jaki sposób wyświetlić obraz z kontenera, dzisiaj dodatkowo pokażę, jak usłyszeć dźwięk audio.
Na potrzeby dzisiejszego wpisu przygotujemy sobie prosty kontener oparty o obraz Ubuntu, z zainstalowaną grą Battle for Wesnoth. Polecam tę grę gorąco, jeżeli ktoś do tej pory nie miał z nią do czynienia, a jest fanem strategii turowych... na dodatek darmowych 😎.
Tworzymy sobie pusty projekt, a w nim plik o nazwie Dockerfile:
FROM docker.io/ubuntu:22.04
RUN apt-get update
RUN apt-get install -y wesnoth
Powyższy obraz to po prostu Ubuntu z zainstalowaną grą. Dodatkowo tworzymy plik konfiguracyjny docker-compose.yaml:
services:
app:
command: /usr/games/wesnoth -w
build:
context: .
dockerfile: Dockerfile
environment:
DISPLAY: host.docker.internal:0.0
Dzięki temu uruchamiając serwis, uruchomimy także bezpośrednio grę. Pewnie od razu rzuciła ci się różnica w stosunku do poprzedniego wpisu - zamiast ręcznie dodawać IP łączymy się poprzez host.docker.internal - człowiek cały czas się uczy 😊. Uruchamiam projekt na Windowsie, dlatego muszę uruchomić zainstalowaną tak jak poprzednio aplikację VcXsrv, będącą serwerem X.
⚠ Na Linuksie konfiguracja ta będzie wyglądać trochę inaczej. Przekazujemy zmienną DISPLAY z naszego hosta do kontenera i montujemy odpowiedni socket:
services:
app:
command: /usr/games/wesnoth -w
build:
context: .
dockerfile: Dockerfile
environment:
DISPLAY: $DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
Dodatkowo wykonujemy komendę, która pozwoli połączyć się do naszego wyświetlacza:
xhost +local:docker
Teraz mogę zbudować i uruchomić serwis poleceniem: docker compose up, a chwilę po tym ukaże mi się na okienko z menu gry (ale w chwili obecnej jeszcze bez dźwięku).
Przechwytywanie strumienia audio
Serwer X pozwala na przekazywanie obrazu wideo, jednak nie pozwala na przekazywanie dźwięku audio. Do tego należy wykorzystać podobne rozwiązanie o nazwie Pulse Audio. Podobnie jak z obrazem wideo, na maszynie hosta musi zostać uruchomiona aplikacja serwera, można ją pobrać z tej strony dla systemu Windows. Pobieram tak więc wersję dla Windows, rozpakowuję ją i modyfikuję pliki konfiguracyjne.
W pliku etc/pulse/daemon.conf w rozpakowanym folderze dodaję na końcu linię:
exit-idle-time = -1
Spowoduje to zachowanie się serwera w taki sposób, że po braku połączenia pozostanie dalej uruchomiony.
W pliku etc/pulse/default.pa dodaję na końcu linię:
load-module module-native-protocol-tcp listen=0.0.0.0 auth-anonymous=1
Zmiana na pozwala na łączenie się do serwera z dowolnego IP. Następnie uruchamiam serwer z pliku wykonywalnego: bin/pulseaudio.exe.
W systemie Linux konfiguracja Pulse Audio jest praktycznie identyczna, łącznie ze ścieżkami.
Teraz pozostało skonfigurować kontener, aby przekazywał dźwięk do serwera na naszej maszynie-hoście. W pliku docker compose.yaml dodaję zmienną środowiskową PULSE_SERVER:
services:
app:
command: /usr/games/wesnoth -w
build:
context: .
dockerfile: Dockerfile
environment:
DISPLAY: host.docker.internal:0.0
PULSE_SERVER: host.docker.internal
dla systemu Linux zmienną host.docker.internal zastępujemy odpowiadającym adresem IP:
services:
app:
command: /usr/games/wesnoth -w
build:
context: .
dockerfile: Dockerfile
environment:
DISPLAY: $DISPLAY
PULSE_SERVER: 172.17.0.1
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
i uruchamiam ponownie serwis: docker-compose up. Po chwili ukazuje się okienko z grą oraz dźwiękiem audio.
To na tym etapie tyle. Ogólnie wydajność tego rozwiązania może pozostawiać wiele do życzenia - np. w moim przypadku, na starszym sprzęcie z Docker Desktop (Windows 10) wideo rozjeżdżało się z audio dość znacznie, ale na drugim, z zainstalowanym Podmanem zamiast Dockera działało dużo lepiej. Natomiast na Dockerze na Linuksie praktycznie nie zauważyłem żadnych opóźnień.
Komentarze
Ten wpis nie posiada komentarzy.
Dodaj komentarz
Pola oznaczone gwiazdką (*) są wymagane. Komentarze są wstępnie moderowane i mogą nie pojawić się na stronie.