fix(player): stabilize progressive captions

This commit is contained in:
XZH 2026-08-28 16:22:56 -07:00
parent 8d6922c043
commit 57f1310bd4
2 changed files with 15 additions and 16 deletions

View File

@ -658,7 +658,7 @@ function processCueElement(cueEl, currentTime) {
} }
function applyProgressiveCaptions(currentTime) { function applyProgressiveCaptions(currentTime) {
const cueElements = document.querySelectorAll('.vjs-text-track-cue'); const cueElements = player.el().querySelectorAll('.vjs-text-track-cue');
if (!cueElements || cueElements.length === 0) return; if (!cueElements || cueElements.length === 0) return;
for (let i = 0; i < cueElements.length; i++) { for (let i = 0; i < cueElements.length; i++) {
@ -669,6 +669,7 @@ function applyProgressiveCaptions(currentTime) {
(function initProgressiveCaptionsLoop() { (function initProgressiveCaptionsLoop() {
let rafId = null; let rafId = null;
let rvfcId = null; let rvfcId = null;
let rvfcVideoEl = null;
let isLoopRunning = false; let isLoopRunning = false;
function updateCaptionFrame() { function updateCaptionFrame() {
@ -693,6 +694,7 @@ function applyProgressiveCaptions(currentTime) {
function scheduleNextFrame(videoEl) { function scheduleNextFrame(videoEl) {
isLoopRunning = true; isLoopRunning = true;
if (videoEl && typeof videoEl.requestVideoFrameCallback === 'function') { if (videoEl && typeof videoEl.requestVideoFrameCallback === 'function') {
rvfcVideoEl = videoEl;
rvfcId = videoEl.requestVideoFrameCallback(function () { rvfcId = videoEl.requestVideoFrameCallback(function () {
updateCaptionFrame(); updateCaptionFrame();
}); });
@ -712,15 +714,14 @@ function applyProgressiveCaptions(currentTime) {
function stopCaptionLoop() { function stopCaptionLoop() {
isLoopRunning = false; isLoopRunning = false;
const tech = player.tech(true); if (rvfcVideoEl && typeof rvfcVideoEl.cancelVideoFrameCallback === 'function' && rvfcId !== null) {
const videoEl = tech && tech.el(); rvfcVideoEl.cancelVideoFrameCallback(rvfcId);
if (videoEl && typeof videoEl.cancelVideoFrameCallback === 'function' && rvfcId !== null) {
videoEl.cancelVideoFrameCallback(rvfcId);
} }
if (rafId !== null) { if (rafId !== null) {
window.cancelAnimationFrame(rafId); window.cancelAnimationFrame(rafId);
} }
rvfcId = null; rvfcId = null;
rvfcVideoEl = null;
rafId = null; rafId = null;
} }
@ -762,6 +763,11 @@ function applyProgressiveCaptions(currentTime) {
// For real-time updates to captions (if currently showing) // For real-time updates to captions (if currently showing)
function update_captions() { function update_captions() {
applyProgressiveCaptions(player.currentTime()); applyProgressiveCaptions(player.currentTime());
const textTrackDisplay = player.getChild('textTrackDisplay');
if (textTrackDisplay && typeof textTrackDisplay.updateDisplay === 'function') {
textTrackDisplay.updateDisplay();
applyProgressiveCaptions(player.currentTime());
}
} }
function toggle_fullscreen() { function toggle_fullscreen() {
@ -952,6 +958,7 @@ if (player.share) player.share(shareOptions);
(function initCaptionLoading() { (function initCaptionLoading() {
const tracks = player.textTracks(); const tracks = player.textTracks();
let preferredTrackSelected = false; let preferredTrackSelected = false;
let captionTrackShowing = false;
let prefetchStarted = false; let prefetchStarted = false;
function prefetchCaptionSource() { function prefetchCaptionSource() {
@ -973,6 +980,7 @@ if (player.share) player.share(shareOptions);
if (!firstCaptionTrack) firstCaptionTrack = track; if (!firstCaptionTrack) firstCaptionTrack = track;
if (track.mode === 'showing') { if (track.mode === 'showing') {
captionTrackShowing = true;
preferredTrackSelected = preferredTrackSelected || preferredTrackSelected = preferredTrackSelected ||
player_data.preferred_caption_found; player_data.preferred_caption_found;
} }
@ -981,8 +989,7 @@ if (player.share) player.share(shareOptions);
if (player_data.preferred_caption_found && !preferredTrackSelected && firstCaptionTrack) { if (player_data.preferred_caption_found && !preferredTrackSelected && firstCaptionTrack) {
preferredTrackSelected = true; preferredTrackSelected = true;
firstCaptionTrack.mode = 'showing'; firstCaptionTrack.mode = 'showing';
} else if (!player_data.preferred_caption_found && !prefetchStarted && } else if (!captionTrackShowing && !prefetchStarted && caption_track_sources.length > 0) {
caption_track_sources.length > 0) {
prefetchStarted = true; prefetchStarted = true;
prefetchCaptionSource(); prefetchCaptionSource();
} }

View File

@ -68,15 +68,7 @@
<% end %> <% end %>
<% end %> <% end %>
<% preferred_captions.each do |caption| <% (preferred_captions + captions).each do |caption|
api_captions_url = "/api/v1/captions/"
api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion)
api_captions_check_id = "&check=#{invidious_companion_check_id}"
%>
<track kind="captions" src="<%= api_captions_url %><%= video.id %>?label=<%= URI.encode_www_form(caption.name) %><%= api_captions_check_id %>" label="<%= caption.name %>">
<% end %>
<% captions.each do |caption|
api_captions_url = "/api/v1/captions/" api_captions_url = "/api/v1/captions/"
api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion) api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion)
api_captions_check_id = "&check=#{invidious_companion_check_id}" api_captions_check_id = "&check=#{invidious_companion_check_id}"