VirtualKimi commited on
Commit
a9fae17
·
verified ·
1 Parent(s): cc1ed17

Upload kimi-videos.js

Browse files
Files changed (1) hide show
  1. kimi-js/kimi-videos.js +42 -7
kimi-js/kimi-videos.js CHANGED
@@ -58,6 +58,8 @@ class KimiVideoManager {
58
  this._recentFailures = new Map();
59
  this._failureCooldown = 5000;
60
  this._consecutiveErrorCount = 0;
 
 
61
  }
62
 
63
  //Centralized crossfade transition between two videos.
@@ -1105,6 +1107,17 @@ class KimiVideoManager {
1105
 
1106
  loadAndSwitchVideo(videoSrc, priority = "normal") {
1107
  const startTs = performance.now();
 
 
 
 
 
 
 
 
 
 
 
1108
  // Guard: ignore if recently failed and still in cooldown
1109
  const lastFail = this._recentFailures.get(videoSrc);
1110
  if (lastFail && performance.now() - lastFail < this._failureCooldown) {
@@ -1170,6 +1183,7 @@ class KimiVideoManager {
1170
 
1171
  // Stocker les références aux handlers pour pouvoir les nettoyer
1172
  let fired = false;
 
1173
  const onReady = () => {
1174
  if (fired) return;
1175
  fired = true;
@@ -1210,16 +1224,27 @@ class KimiVideoManager {
1210
  const networkState = mediaEl ? mediaEl.networkState : -1;
1211
  let mediaErrorCode = null;
1212
  if (mediaEl && mediaEl.error) mediaErrorCode = mediaEl.error.code;
 
 
 
 
 
 
 
 
1213
  console.warn(
1214
- `Error loading video: ${videoSrc} (readyState=${readyState} networkState=${networkState} mediaError=${mediaErrorCode}) falling back to: ${fallbackVideo}`
1215
  );
1216
  this._loadingInProgress = false;
1217
  if (this._loadTimeout) {
1218
  clearTimeout(this._loadTimeout);
1219
  this._loadTimeout = null;
1220
  }
1221
- this._recentFailures.set(videoSrc, performance.now());
1222
- this._consecutiveErrorCount++;
 
 
 
1223
  // Stop runaway fallback loop: pause if too many sequential errors relative to pool size
1224
  if (this._fallbackPool && this._consecutiveErrorCount >= this._fallbackPool.length * 2) {
1225
  console.error("Temporarily pausing fallback loop after repeated failures. Retrying in 2s.");
@@ -1276,12 +1301,17 @@ class KimiVideoManager {
1276
  // Cap by clip length ratio if we know (assume 10000ms default when metadata absent)
1277
  const currentClipMs = 10000; // All clips are 10s
1278
  adaptiveTimeout = Math.min(adaptiveTimeout, Math.floor(currentClipMs * this._timeoutCapRatio));
 
 
 
 
1279
  this._loadTimeout = setTimeout(() => {
1280
  if (!fired) {
1281
  // If metadata is there but not canplay yet, extend once
1282
  if (this.inactiveVideo.readyState >= 1 && this.inactiveVideo.readyState < 2) {
 
1283
  console.debug(
1284
- `Extending timeout for ${videoSrc} (readyState=${this.inactiveVideo.readyState}) by ${this._timeoutExtension}ms`
1285
  );
1286
  this._loadTimeout = setTimeout(() => {
1287
  if (!fired) {
@@ -1292,15 +1322,19 @@ class KimiVideoManager {
1292
  return;
1293
  }
1294
  // Grace retry: still fetching over network (networkState=2) with no data (readyState=0)
 
1295
  if (
1296
  this.inactiveVideo.networkState === 2 &&
1297
  this.inactiveVideo.readyState === 0 &&
1298
- (this._graceRetryCounts?.[videoSrc] || 0) < 1
1299
  ) {
1300
  if (!this._graceRetryCounts) this._graceRetryCounts = {};
1301
  this._graceRetryCounts[videoSrc] = (this._graceRetryCounts[videoSrc] || 0) + 1;
1302
- const extra = this._timeoutExtension + 600;
1303
- console.debug(`Grace retry for ${videoSrc} (network loading). Extending by ${extra}ms`);
 
 
 
1304
  this._loadTimeout = setTimeout(() => {
1305
  if (!fired) {
1306
  if (this.inactiveVideo.readyState >= 2) onReady();
@@ -1312,6 +1346,7 @@ class KimiVideoManager {
1312
  if (this.inactiveVideo.readyState >= 2) {
1313
  onReady();
1314
  } else {
 
1315
  this._currentErrorHandler();
1316
  }
1317
  }
 
58
  this._recentFailures = new Map();
59
  this._failureCooldown = 5000;
60
  this._consecutiveErrorCount = 0;
61
+ // Track per-video load attempts to adapt timeouts & avoid faux échecs
62
+ this._videoAttempts = new Map();
63
  }
64
 
65
  //Centralized crossfade transition between two videos.
 
1107
 
1108
  loadAndSwitchVideo(videoSrc, priority = "normal") {
1109
  const startTs = performance.now();
1110
+ // Register attempt count (used for adaptive backoff)
1111
+ const prevAttempts = this._videoAttempts.get(videoSrc) || 0;
1112
+ const attempts = prevAttempts + 1;
1113
+ this._videoAttempts.set(videoSrc, attempts);
1114
+ // Light trimming to avoid unbounded growth
1115
+ if (this._videoAttempts.size > 300) {
1116
+ for (const key of this._videoAttempts.keys()) {
1117
+ if (this._videoAttempts.size <= 200) break;
1118
+ this._videoAttempts.delete(key);
1119
+ }
1120
+ }
1121
  // Guard: ignore if recently failed and still in cooldown
1122
  const lastFail = this._recentFailures.get(videoSrc);
1123
  if (lastFail && performance.now() - lastFail < this._failureCooldown) {
 
1183
 
1184
  // Stocker les références aux handlers pour pouvoir les nettoyer
1185
  let fired = false;
1186
+ let errorCause = "error-event"; // will be overwritten if timeout based
1187
  const onReady = () => {
1188
  if (fired) return;
1189
  fired = true;
 
1224
  const networkState = mediaEl ? mediaEl.networkState : -1;
1225
  let mediaErrorCode = null;
1226
  if (mediaEl && mediaEl.error) mediaErrorCode = mediaEl.error.code;
1227
+ const stillLoading = !mediaEl?.error && networkState === 2;
1228
+ const realMediaError = !!mediaEl?.error;
1229
+ // Differentiate timeout vs real media error for clarity
1230
+ const tag = realMediaError
1231
+ ? "VideoLoadFail:media-error"
1232
+ : errorCause.startsWith("timeout")
1233
+ ? `VideoLoadFail:${errorCause}`
1234
+ : "VideoLoadFail:unknown";
1235
  console.warn(
1236
+ `[${tag}] src=${videoSrc} readyState=${readyState} networkState=${networkState} mediaError=${mediaErrorCode} attempts=${attempts} fallback=${fallbackVideo}`
1237
  );
1238
  this._loadingInProgress = false;
1239
  if (this._loadTimeout) {
1240
  clearTimeout(this._loadTimeout);
1241
  this._loadTimeout = null;
1242
  }
1243
+ // Only mark as failure if c'est une vraie erreur décodage OU plusieurs timeouts persistants
1244
+ if (realMediaError || (!stillLoading && errorCause.startsWith("timeout")) || attempts >= 3) {
1245
+ this._recentFailures.set(videoSrc, performance.now());
1246
+ this._consecutiveErrorCount++;
1247
+ }
1248
  // Stop runaway fallback loop: pause if too many sequential errors relative to pool size
1249
  if (this._fallbackPool && this._consecutiveErrorCount >= this._fallbackPool.length * 2) {
1250
  console.error("Temporarily pausing fallback loop after repeated failures. Retrying in 2s.");
 
1301
  // Cap by clip length ratio if we know (assume 10000ms default when metadata absent)
1302
  const currentClipMs = 10000; // All clips are 10s
1303
  adaptiveTimeout = Math.min(adaptiveTimeout, Math.floor(currentClipMs * this._timeoutCapRatio));
1304
+ // First ever attempt for a video: be more lenient if no historical avg yet
1305
+ if (attempts === 1 && !this._avgLoadTime) {
1306
+ adaptiveTimeout = Math.floor(adaptiveTimeout * 1.8); // ~5400ms au lieu de 3000ms typique
1307
+ }
1308
  this._loadTimeout = setTimeout(() => {
1309
  if (!fired) {
1310
  // If metadata is there but not canplay yet, extend once
1311
  if (this.inactiveVideo.readyState >= 1 && this.inactiveVideo.readyState < 2) {
1312
+ errorCause = "timeout-metadata";
1313
  console.debug(
1314
+ `Extending timeout (metadata) for ${videoSrc} readyState=${this.inactiveVideo.readyState} +${this._timeoutExtension}ms`
1315
  );
1316
  this._loadTimeout = setTimeout(() => {
1317
  if (!fired) {
 
1322
  return;
1323
  }
1324
  // Grace retry: still fetching over network (networkState=2) with no data (readyState=0)
1325
+ const maxGrace = 2; // allow up to two grace extensions
1326
  if (
1327
  this.inactiveVideo.networkState === 2 &&
1328
  this.inactiveVideo.readyState === 0 &&
1329
+ (this._graceRetryCounts?.[videoSrc] || 0) < maxGrace
1330
  ) {
1331
  if (!this._graceRetryCounts) this._graceRetryCounts = {};
1332
  this._graceRetryCounts[videoSrc] = (this._graceRetryCounts[videoSrc] || 0) + 1;
1333
+ const extra = this._timeoutExtension + 900;
1334
+ errorCause = "timeout-grace";
1335
+ console.debug(
1336
+ `Grace retry #${this._graceRetryCounts[videoSrc]} for ${videoSrc} (still NETWORK_LOADING). Ext +${extra}ms`
1337
+ );
1338
  this._loadTimeout = setTimeout(() => {
1339
  if (!fired) {
1340
  if (this.inactiveVideo.readyState >= 2) onReady();
 
1346
  if (this.inactiveVideo.readyState >= 2) {
1347
  onReady();
1348
  } else {
1349
+ errorCause = errorCause === "error-event" ? "timeout-final" : errorCause;
1350
  this._currentErrorHandler();
1351
  }
1352
  }