Fix: streamed tracks play with no sound (suspended Web Audio context)
The visualizer calls createMediaElementSource(audioPlayer), which permanently reroutes the shared <audio> element's output through npAudioContext. That context is created from an async play().then() callback (outside the user gesture), so browsers start it 'suspended' under the autoplay policy — and the only resume() lived in the visualizer loop, which runs when the Now Playing modal opens, NOT on play. Result: the element advances (looks like it's playing) but its audio drains into a suspended context = no sound, everywhere. Add npEnsureAudioContextRunning() and call it on every play start (setPlayingState(true)) plus right after the context is created in npInitVisualizer. Resuming an already-running/absent context is a safe no-op.
This commit is contained in:
parent
ceb9ee15fc
commit
5cb65ab00e
1 changed files with 21 additions and 0 deletions
|
|
@ -304,6 +304,10 @@ function setPlayingState(playing) {
|
|||
// Sidebar audio visualizer
|
||||
if (playing) {
|
||||
npInitVisualizer();
|
||||
// npInitVisualizer only runs its setup once; the element stays routed
|
||||
// through npAudioContext, so resume it on EVERY play start or playback
|
||||
// is silent when the context has been suspended (autoplay / tab blur).
|
||||
npEnsureAudioContextRunning();
|
||||
startSidebarVisualizer();
|
||||
} else {
|
||||
stopSidebarVisualizer();
|
||||
|
|
@ -2661,6 +2665,20 @@ function getNpAlbumArtUrl() {
|
|||
// WEB AUDIO VISUALIZER
|
||||
// ===============================
|
||||
|
||||
// Once createMediaElementSource() captures the <audio> element, ALL of its
|
||||
// output is routed through this AudioContext — so if the context is suspended
|
||||
// (browsers create it suspended under the autoplay policy, and we init it from
|
||||
// an async play().then callback that's outside the gesture), the track plays
|
||||
// but no sound reaches the speakers. Resuming must happen on every play start,
|
||||
// not only when the visualizer loop runs. Safe to call anytime.
|
||||
function npEnsureAudioContextRunning() {
|
||||
try {
|
||||
if (npAudioContext && npAudioContext.state === 'suspended') {
|
||||
npAudioContext.resume().catch(() => {});
|
||||
}
|
||||
} catch (_) { /* no-op */ }
|
||||
}
|
||||
|
||||
function npInitVisualizer() {
|
||||
if (npVizInitialized || !audioPlayer) return;
|
||||
try {
|
||||
|
|
@ -2676,6 +2694,9 @@ function npInitVisualizer() {
|
|||
npAnalyser.connect(npAudioContext.destination);
|
||||
}
|
||||
npVizInitialized = true;
|
||||
// Freshly created contexts start suspended — resume so the rerouted
|
||||
// element is actually audible (this is the no-sound-on-play bug).
|
||||
npEnsureAudioContextRunning();
|
||||
} catch (e) {
|
||||
console.warn('Web Audio visualizer init failed, using CSS fallback:', e.message);
|
||||
// Mark as CSS fallback
|
||||
|
|
|
|||
Loading…
Reference in a new issue