VNC/noVNC only ever streams video, so game sound needed a completely separate path. Adds pulseaudio/pulseaudio-utils/libasound2-plugins and routes ALSA's default device through Pulse (/etc/asound.conf), so dosbox/scummvm need zero special config. server.sh starts one PulseAudio daemon and one pcm_ws_bridge.py (from docker-common) for the container's whole lifetime, capturing Pulse's single default sink via parec. Audio is a single shared mix, not per-game - considered and dropped a per-slot-isolated design (mirroring the video architecture) as unnecessary complexity per direction. Every running game's audio just mixes into the one default sink; every /screen/<name> page connects to the same AUDIO_PORT. setup_server.py gains GET /screen/<name> (an iframe onto the game's noVNC screen plus an Enable Sound button - browsers require a user gesture before audio can start) and GET /pcm-worklet.js. The "Open Screen" link simplifies from a client-side-JS-built cross-port link to a plain same-origin relative link, since /screen/<name> now reads the real host server-side from the request's own Host header. Found and fixed a real bug along the way: parec --device=@DEFAULT_SINK@.monitor looks correct but fails with "Stream error: Invalid argument" - the actual PulseAudio macro is the single token @DEFAULT_MONITOR@. Verified end-to-end with real audio, not just plumbing: confirmed via `pactl list sink-inputs` that dosbox connects to Pulse correctly (unmuted, uncorked), then used xdotool to advance stuntcar past its silent title screen and captured real audible game audio (RMS ~9292) through the WebSocket bridge with a raw Python client. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NiNnj78HGx1KWyCCo39HSz
42 lines
1.6 KiB
Docker
42 lines
1.6 KiB
Docker
# syntax=docker/dockerfile:1
|
|
FROM ich777/novnc-baseimage
|
|
|
|
ENV DISPLAY_NUM=99
|
|
ENV GAMES_HOME=/opt/games
|
|
ENV SCRIPTS_HOME=/opt/scripts
|
|
ENV PATH=${PATH}:${SCRIPTS_HOME}
|
|
|
|
# unzip/smbclient/python3 are needed at runtime: the games are no longer baked into the
|
|
# image, setup_server.py serves an HTML install UI (backed by smbget+unzip) that the user
|
|
# drives on ${SETUP_PORT} instead of anything being auto-downloaded at container start.
|
|
# pulseaudio/pulseaudio-utils/libasound2-plugins carry game audio out to the browser (see
|
|
# scripts/pcm_ws_bridge.py) - VNC/noVNC only ever streams video, never audio.
|
|
RUN apt-get update && \
|
|
apt-get -y install --no-install-recommends dosbox scummvm alsa-utils unzip smbclient python3 \
|
|
pulseaudio pulseaudio-utils libasound2-plugins && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Route ALSA's default device through PulseAudio, so dosbox/scummvm need no special config -
|
|
# every game's audio ends up mixed into Pulse's one default sink, captured by pcm_ws_bridge.py.
|
|
RUN printf 'pcm.!default pulse\nctl.!default pulse\n' > /etc/asound.conf
|
|
|
|
RUN openssl req -x509 -nodes -newkey rsa:2048 -keyout /tmp/novnc.key -out /tmp/novnc.pem -days 3650 -subj "/C=US/ST=NY/L=NY/O=NY/OU=NY/CN=NY emailAddress=email@example.com"
|
|
RUN touch /root/.Xauthority
|
|
|
|
RUN mkdir -p ${GAMES_HOME}
|
|
VOLUME ${GAMES_HOME}
|
|
|
|
ADD scripts ${SCRIPTS_HOME}
|
|
WORKDIR /
|
|
|
|
EXPOSE 60${DISPLAY_NUM}
|
|
EXPOSE 70${DISPLAY_NUM}
|
|
EXPOSE 71${DISPLAY_NUM}
|
|
EXPOSE 8090-8099
|
|
EXPOSE 5900
|
|
|
|
ENTRYPOINT ["/opt/scripts/server_start.sh", "/opt/scripts/server.sh"]
|
|
|
|
# see also
|
|
# https://github.com/ich777/docker-krusader
|