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
|
// Sidebar audio visualizer
|
||||||
if (playing) {
|
if (playing) {
|
||||||
npInitVisualizer();
|
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();
|
startSidebarVisualizer();
|
||||||
} else {
|
} else {
|
||||||
stopSidebarVisualizer();
|
stopSidebarVisualizer();
|
||||||
|
|
@ -2661,6 +2665,20 @@ function getNpAlbumArtUrl() {
|
||||||
// WEB AUDIO VISUALIZER
|
// 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() {
|
function npInitVisualizer() {
|
||||||
if (npVizInitialized || !audioPlayer) return;
|
if (npVizInitialized || !audioPlayer) return;
|
||||||
try {
|
try {
|
||||||
|
|
@ -2676,6 +2694,9 @@ function npInitVisualizer() {
|
||||||
npAnalyser.connect(npAudioContext.destination);
|
npAnalyser.connect(npAudioContext.destination);
|
||||||
}
|
}
|
||||||
npVizInitialized = true;
|
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) {
|
} catch (e) {
|
||||||
console.warn('Web Audio visualizer init failed, using CSS fallback:', e.message);
|
console.warn('Web Audio visualizer init failed, using CSS fallback:', e.message);
|
||||||
// Mark as CSS fallback
|
// Mark as CSS fallback
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue