fix(transcript): tlang en dernier recours + garde anti-blob
CI / build-and-test (push) Successful in 14m5s

Le fallback &tlang= peut renvoyer la piste source en un seul bloc
de plusieurs Ko (throttle YouTube) : il passait devant les pistes
directes et son blob anglais etait mis en cache comme 'fr'.
tlang desormais etape 3 (apres directes signees), isBlobTranscript()
refuse les cues uniques > 2000 chars (fetch, yt-dlp et post-dedupe).
Tests 27/27.
This commit is contained in:
2026-09-27 20:56:08 -04:00
parent a79831f406
commit a57bc0f7ae
3 changed files with 67 additions and 18 deletions
+11 -2
View File
@@ -20,6 +20,7 @@ import {
looksLikeHtmlError,
ensureFmtParam,
isEmptyTimedTextBody,
isBlobTranscript,
mergeTranscriptCandidates,
capLines,
normalizeTranscriptProvider,
@@ -252,14 +253,22 @@ describe('timedtext fetch guards (anti-429 datacenter)', () => {
assert.equal(isEmptyTimedTextBody(JSON.stringify({ events: [{ tStartMs: 0, dDurationMs: 1, segs: [{ utf8: 'Hi' }] }] })), false);
assert.equal(isEmptyTimedTextBody('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\nHello\n'), false);
});
it('mergeTranscriptCandidates prefers signed urls, dedupes, bounds', () => {
const s = { track: { url: 'https://x/signed?sig=1' }, lang: 'fr' };
it('mergeTranscriptCandidates prefers signed urls, dedupes, bounds', () => { const s = { track: { url: 'https://x/signed?sig=1' }, lang: 'fr' };
const dup = { track: { url: 'https://x/signed?sig=1' }, lang: 'fr' };
const it = { track: { url: 'https://x/innertube?fmt=json3' }, lang: 'fr' };
const out = mergeTranscriptCandidates({ signed: [s, dup], innertube: [it], max: 5 });
assert.deepEqual(out.map((c) => c.track.url), ['https://x/signed?sig=1', 'https://x/innertube?fmt=json3']);
assert.equal(mergeTranscriptCandidates({ signed: [s], innertube: [it], max: 1 }).length, 1);
});
it('isBlobTranscript rejects single giant cues, accepts real lines', () => {
assert.equal(isBlobTranscript([{ t: 0, dur: 1, text: 'x'.repeat(8581) }]), true);
assert.equal(isBlobTranscript([{ t: 0, dur: 1, text: 'Bonjour' }]), false);
assert.equal(isBlobTranscript([
{ t: 0, dur: 1, text: 'a' },
{ t: 1, dur: 1, text: 'b' },
]), false);
assert.equal(isBlobTranscript([]), false);
});
});
describe('capLines + normalizeTranscriptProvider', () => { it('truncates very long transcripts', () => {