From d25484be46bb031ab89d49d3c65e011ae3a9a166 Mon Sep 17 00:00:00 2001 From: Omri Hefez Date: Mon, 18 May 2026 23:28:39 +0300 Subject: [PATCH] Player: retry audio-track restore until player acknowledges selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #2564 — audio language not applied on stream re-open (LG webOS). On stream re-open the auto-selection effect calls video.setAudioTrack(id) exactly once when the audioTracks list first becomes available, then sets defaultAudioTrackSelected.current = true and never retries. On platforms where the underlying player hasn't fully initialized at that moment (e.g. LG webOS Smart TV), the call is silently ignored — the UI state (selectedAudioTrackId in core) reflects the desired track, but actual playback uses the player's default track. The user observes that the correct language is highlighted in the menu, yet re-clicking it is what actually switches the audio. Patch: - Don't mark the selection as 'done' on the first setAudioTrack call. Wait until video.state.selectedAudioTrackId === desired id. Once it matches, we know the player has actually applied the selection. - Include video.state.selectedAudioTrackId in the effect deps so the effect re-runs when the player updates its state, giving us a chance to retry if the first call didn't take. setAudioTrack is idempotent on the core side, so re-issuing the same id on subsequent renders is safe. --- src/routes/Player/Player.js | 41 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 67baeceb2..ab42f8ccc 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -463,18 +463,39 @@ const Player = ({ urlParams, queryParams }) => { }, [player.nextVideo, video.state.time, video.state.duration]); // Auto audio track selection + // Bug: on stream re-open, calling video.setAudioTrack() once during audioTracks + // initialization is not always honored by the underlying player — the UI state + // reflects the desired track (selectedAudioTrackId in core) but the actual + // playback uses the player's default track (the first / index 0). This is + // observable on LG webOS Smart TV (see issue #2564). Symptom: user re-selects + // the already-highlighted option and only then does the audio actually switch. + // + // Fix: don't mark the selection as "done" until the player's + // selectedAudioTrackId actually matches the desired id. Until they match, + // keep retrying on each render of audioTracks / selectedAudioTrackId / streamState. React.useEffect(() => { - if (!defaultAudioTrackSelected.current) { - const savedTrackId = player.streamState?.audioTrack?.id; - const savedTrack = savedTrackId ? findTrackById(video.state.audioTracks, savedTrackId) : null; - const audioTrack = savedTrack ?? findTrackByLang(video.state.audioTracks, settings.audioLanguage); - - if (audioTrack && audioTrack.id) { - video.setAudioTrack(audioTrack.id); - defaultAudioTrackSelected.current = true; - } + if (defaultAudioTrackSelected.current) { + return; } - }, [video.state.audioTracks, player.streamState]); + const savedTrackId = player.streamState?.audioTrack?.id; + const savedTrack = savedTrackId ? findTrackById(video.state.audioTracks, savedTrackId) : null; + const audioTrack = savedTrack ?? findTrackByLang(video.state.audioTracks, settings.audioLanguage); + + if (!audioTrack || !audioTrack.id) { + return; + } + + if (video.state.selectedAudioTrackId === audioTrack.id) { + // Player has acknowledged the selection — we're done. + defaultAudioTrackSelected.current = true; + return; + } + + // Either we haven't requested the change yet, or the player hasn't picked + // it up. Request again. This is safe to call repeatedly with the same id + // because setAudioTrack is idempotent on the core side. + video.setAudioTrack(audioTrack.id); + }, [video.state.audioTracks, video.state.selectedAudioTrackId, player.streamState]); React.useEffect(() => { defaultAudioTrackSelected.current = false;