mirror of
https://github.com/games-on-whales/wolf.git
synced 2026-10-15 13:02:03 +00:00
[GH-ISSUE #413] Streamed apps have no audio on NVIDIA — audio producer pipeline never constructed (no pulsesrc, no record client in WolfPulseAudio) #268
Labels
No labels
🧠 1 - 🤖 999
AMD
bug
bug
cannot reproduce
documentation
duplicate
easy
enhancement
enhancement
enhancement
fixed?
fixed?
good first issue
hard
help wanted
Intel
invalid
LXC
medium
moonlight-protocol
Multi GPU
nixos
not a bug
nvidia
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/wolf#268
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @xavdematos on GitHub (May 20, 2026).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/413
Streamed apps have no audio on NVIDIA — audio producer pipeline never constructed (no
pulsesrc, no record client in WolfPulseAudio)Summary
Streamed apps on NVIDIA play silently. The per-session PulseAudio sink can be present and the streamed app can be bound to it cleanly, yet Wolf never seems to build the audio producer pipeline (
pulsesrc device=virtual_sink_<id> ! ... ! interpipesink name=<id>_audio) — only the encoder/consumer pipeline (interpipesrc … ! opusenc ! rtpmoonlightpay_audio ! appsink) is ever logged, andWolfPulseAudionever gains a record client. As a result the Opus encoder has no audio source feeding it and the WebRTC audio track is silent.The video side works correctly on the same setup (corresponding
interpipesink … name=<id>_videoIS present in logs).Reproduced on three Wolf image tags (
:stable,:fix-pulseaudio-nvidia-device-nodes,:alpha), identical symptom on each.Environment
nvidia-driver-vol(NVIDIA_DRIVER_VOLUME_NAME), NOTruntime: nvidia(avoidsMESA ZINK: failed to choose pdev). Volume populated fromgow/nvidia-driverDockerfile pinned to the host driver version.nvidia-drm modeset=Yverified.ghcr.io/games-on-whales/pulseaudio:master(no other tag tried).ghcr.io/games-on-whales/wolf:stableghcr.io/games-on-whales/wolf:fix-pulseaudio-nvidia-device-nodesghcr.io/games-on-whales/wolf:alpha(GStreamer 1.26.7-0)interpipesrc/interpipesinkID throughout.What works (so this is squarely an audio-producer issue, not config / pulse-permissions / app-side)
WolfPulseAudio(default.pa loadsmodule-native-protocol-unix auth-anonymous=1+module-always-sink) is up; the streamed container shares its socket via the per-session volume.pactl load-module module-null-sink sink_name=$PULSE_SINK(since Wolf's own session-side[STREAM_SESSION] Create virtual audio sinkdoesn't actually result in a sink in our reproductions —auto_nullonly, but that's likely a downstream of the same issue and not the focus here).[PULSE_ROUTER]observes the sink and logsSink appeared name='virtual_sink_<id>' idx=1 -> session='<id>'.virtual_sink_<id>explicitly) opens PulseAudio cleanly — buffer allocated, audio driver started, no fallback errors.What does NOT happen
Across many sessions on each of the three Wolf images:
pulsesrcever appears in Wolf's logs atWOLF_LOG_LEVEL=DEBUG.docker logs wolf | grep pulsesrcis empty for the entire container lifetime.interpipesinkis ever logged. Wolf'sStarting audio pipeline:debug shows only the encoder/consumer pipeline: The matching producer pipeline (pulsesrc device=virtual_sink_<id> … ! interpipesink name=<id>_audio) is never logged. Compare the video side, whereinterpipesink … name=<id>_videoIS present.WolfPulseAudionever gains a record client. From inside the pulse container as uid 1000: There is no Wolf-side recording client (no client recording fromvirtual_sink_<id>.monitor) at any point during an active stream.pactl list short sink-inputsis empty even during active gameplay, although the streamed app's[Audio]driver log indicates it has an open PulseAudio stream.Minimal reproduction
nvidia-driver-volmethod (or any working video setup).$PULSE_SINK = virtual_sink_<sessionid>(any PulseAudio client targeting that sink will do).Sink appeared, but client hears nothing.docker logs wolf | grep pulsesrc→ empty.pactl list short clientsinside WolfPulseAudio → onlywolf(router) and your own diagnostic.pactl list short sink-inputs→ empty.Source pointers / model
src/moonlight-server/audio/pulse_router.cpp— router model (move sink-inputs ontovirtual_sink_<id>); does NOT construct the audio capture pipeline itself.src/moonlight-server/streaming/streaming.cpp::start_streaming_audio()— usespulsesrc device="{sink_name}" server="{server_name}"againstaudio_session->gst_pipeline; expected to be where the producer pipeline goes live. In our reproductions this code path either isn't entered or itsrun_pipeline()is silently no-op on NVIDIA.What we'd like to know
WOLF_LOG_LEVEL=DEBUG? If yes, its absence indicates the construction is skipped; pointers to the precondition that's being missed (any requiredgstreamer.audiotemplate, audio bitrate, session config flag) would be enough to unblock us.I can attach the raw Wolf log file,
pactl listsnapshots, and the streamed-app's PulseAudio init log if helpful — happy to share whatever helps.Thanks for Wolf — the rest of the stack (video, controller, save sync) works beautifully.
@ABeltramo commented on GitHub (May 20, 2026):
I've skimmed thru the massive text wall, unfortunately it's missing any useful info that I can use to help you out. 😅
Please post the full Wolf logs with the added env variable
WOLF_LOG_LEVEL=DEBUGand which Moonlight client are you using for streaming.@xavdematos commented on GitHub (May 21, 2026):
wolf-413-fulllog-scrubbed.txt
Moonlight client: the browser-based moonlight-web-stream (mrcreativ3001's web client / WebRTC bridge), not a native Moonlight app. Signaling is over a WebSocket; media is WebRTC. (Full Wolf DEBUG log attached as
wolf-413-fulllog-scrubbed.txt.)Environment: Wolf
:stable,pulseaudio:master, NVIDIA (RTX 3080, driver 595.71.05), Ubuntu 25.04 host.nvh264enchardware path, audio server enabled.The bug, pinned at the PulseAudio layer
Captured live from inside the PulseAudio container during an active stream (an emulator is running and producing sound):
So:
virtual_sink_<id>exists and is RUNNING.xemuhere, same with RetroArch) has live sink-inputs — game audio is flowing into the sink..monitorand no recording client — i.e. Wolf never opens apulsesrcto capture the monitor, so nothing feeds the Opus encoder. Result: encoded audio stream is silent.Matching evidence in the Wolf DEBUG log
The audio encoder pipeline starts fine (consumer side):
…but the producer/capture pipeline that should feed
<id>_audiois never built. In the full attached log:Create virtual audio sink— logged 7× (once per session attempt)pulsesrc— 0 occurrencesinterpipesink(i.e.interpipesink name=<id>_audio) — 0 occurrencesCompare the video side, which logs both halves (
interpipesink name=<id>_videoproducer + theinterpipesrc … nvh264encconsumer) and works perfectly. Only the audio producer is missing.Note on the sink (so the logs make sense)
You'll see the sink gets created by a
pactl load-module module-null-sink sink_name=virtual_sink_<id>from inside our app container — that's a workaround we added because in our earlier runs Wolf's ownCreate virtual audio sinkstep produced only the fallbackauto_null(the named per-session sink never appeared). With the sink force-created,[PULSE_ROUTER]does logSink appeared name='virtual_sink_<id>'and moves the app's sink-input onto it — but it still never opens a capturepulsesrcon the monitor. So whether or not the sink exists, the capture side isn't instantiated on this NVIDIA setup.Happy to run any specific
pactl/gst probes or test a patched build.@JBailes commented on GitHub (May 21, 2026):
What nvidia GPU are you using? What is your CPU?
@xavdematos commented on GitHub (May 21, 2026):
GPU: NVIDIA GeForce RTX 3080 (GA102, 12 GB VRAM), driver 595.71.05
CPU: AMD Ryzen AI 9 HX PRO 370 (24 threads)
RAM: 96 GB
OS: Unraid 7.2, kernel 6.12.54
Worth flagging: it's a dual-GPU box; the RTX 3080 (c6:00.0, /dev/dri/renderD128, what Wolf uses) plus the CPU's AMD Radeon 890M iGPU (c7:00.0). Wolf correctly picks the NVIDIA node and the amdgpu/VAAPI probes just warn and fall back, so video/NVENC work fine , noting it only in case the second GPU is relevant to audio-device selection.
@JBailes commented on GitHub (May 22, 2026):
I have a few ideas. I'll do some fiddling today, I think I may be able to help with this. I need a bit of time to parse through the logs.
@xavdematos commented on GitHub (Jun 27, 2026):
Any thoughts here?