Preserve HLS subtitle and closed-caption cues across recovery
This commit is contained in:
@ -57,15 +57,27 @@ class CaptionTracks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepareMediaRecovery() {
|
prepareMediaRecovery() {
|
||||||
if (!this.remoteTracks.length) return;
|
const tracks = Array.from(this.hlsTracks, ([key, entry]) => ({ key, entry,
|
||||||
|
cues: Array.from(entry.element.track.cues || []), mode: entry.element.track.mode }));
|
||||||
|
const hasRemoteTracks = this.remoteTracks.length > 0;
|
||||||
|
if (!hasRemoteTracks && !tracks.length) return;
|
||||||
const selected = this.remoteTracks.findIndex(element => element.track.mode === 'showing');
|
const selected = this.remoteTracks.findIndex(element => element.track.mode === 'showing');
|
||||||
const generation = this.generation, revision = this.selectionRevision;
|
const generation = this.generation, revision = this.selectionRevision;
|
||||||
return () => {
|
return () => {
|
||||||
if (this.generation !== generation || this.selectionRevision !== revision) return;
|
if (this.generation !== generation) return;
|
||||||
// HLS detachment clears native cues, including extracted remote subtitles.
|
// HLS detachment clears all native cues, including our owned caption tracks.
|
||||||
this.removeRemoteTracks();
|
for (const { key, entry, cues, mode } of tracks) {
|
||||||
this.addRemoteTracks();
|
if (this.hlsTracks.get(key) !== entry) continue;
|
||||||
if (selected >= 0 && this.remoteTracks[selected]) this.remoteTracks[selected].track.mode = 'showing';
|
this.appendHlsCues(entry, cues);
|
||||||
|
if (this.selectionRevision === revision) entry.element.track.mode = mode;
|
||||||
|
}
|
||||||
|
if (hasRemoteTracks) {
|
||||||
|
const remoteSelection = this.selectionRevision === revision ? selected :
|
||||||
|
this.remoteTracks.findIndex(element => element.track.mode === 'showing');
|
||||||
|
this.removeRemoteTracks();
|
||||||
|
this.addRemoteTracks();
|
||||||
|
if (remoteSelection >= 0 && this.remoteTracks[remoteSelection]) this.remoteTracks[remoteSelection].track.mode = 'showing';
|
||||||
|
}
|
||||||
this.onChange();
|
this.onChange();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,6 +104,11 @@ test('both subtitle menus select real HLS cues, discard stale tracks and preserv
|
|||||||
});
|
});
|
||||||
assert.equal(await page.locator('#list button.active').count(), 1);
|
assert.equal(await page.locator('#list button.active').count(), 1);
|
||||||
}
|
}
|
||||||
|
await page.evaluate(() => window.player.audioRecovery.requestRecovery('caption recovery fixture'));
|
||||||
|
await page.waitForFunction(() => window.player.audioRecovery.lastRecovery > 0 && !window.player.audioRecovery.onAttached);
|
||||||
|
await page.waitForFunction(() => Array.from(window.player.video.textTracks).some(track =>
|
||||||
|
track.mode === 'showing' && Array.from(track.activeCues || []).some(cue => cue.text === 'Cue from /sub2.vtt')));
|
||||||
|
assert.equal(await page.evaluate(() => window.player.video.paused), true);
|
||||||
await page.locator('#list button').first().click();
|
await page.locator('#list button').first().click();
|
||||||
assert.equal(await page.evaluate(() => window.player.hls.subtitleTrack), -1);
|
assert.equal(await page.evaluate(() => window.player.hls.subtitleTrack), -1);
|
||||||
assert.equal(await page.evaluate(() => Array.from(window.player.video.textTracks).every(track => track.mode === 'disabled')), true);
|
assert.equal(await page.evaluate(() => Array.from(window.player.video.textTracks).every(track => track.mode === 'disabled')), true);
|
||||||
@ -162,6 +167,11 @@ test('both subtitle menus select real HLS cues, discard stale tracks and preserv
|
|||||||
return track.mode === 'showing' && track.cues?.length === 1 && track.cues[0].text === 'CEA caption';
|
return track.mode === 'showing' && track.cues?.length === 1 && track.cues[0].text === 'CEA caption';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await page.evaluate(() => window.player.audioRecovery.requestRecovery('CEA recovery fixture'));
|
||||||
|
await page.waitForFunction(() => window.player.audioRecovery.lastRecovery > 0 && !window.player.audioRecovery.onAttached);
|
||||||
|
await page.waitForFunction(() => Array.from(window.player.video.textTracks).some(track =>
|
||||||
|
track.label === 'English CC' && track.mode === 'showing' && track.cues?.length === 1 && track.cues[0].text === 'CEA caption'));
|
||||||
|
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
const player = window.player;
|
const player = window.player;
|
||||||
player.stop();
|
player.stop();
|
||||||
|
|||||||
Reference in New Issue
Block a user