fix(transcript): pipeline URLs signees yt-dlp + fetch durci anti-429
CI / build-and-test (push) Successful in 14m1s
CI / build-and-test (push) Successful in 14m1s
Les URLs timedtext InnerTube repondent 200-vide (throttle YouTube) : sonde rapide max 2 sans retry, puis dump yt-dlp -> URLs signees en direct (max 4), puis --write-sub. 200-vide traite comme 429 (retryAfterSec), fmt= plus jamais duplique (signature), cookies YT_COOKIES_FILE reutilises par le fetch direct. Tests 26/26.
This commit is contained in:
@@ -18,6 +18,9 @@ import {
|
||||
translatedFallbacks,
|
||||
firstPerLanguage,
|
||||
looksLikeHtmlError,
|
||||
ensureFmtParam,
|
||||
isEmptyTimedTextBody,
|
||||
mergeTranscriptCandidates,
|
||||
capLines,
|
||||
normalizeTranscriptProvider,
|
||||
} from '../transcript.mjs';
|
||||
@@ -234,6 +237,31 @@ describe('dedupeTranscriptLines (rolling-window auto-captions)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('timedtext fetch guards (anti-429 datacenter)', () => {
|
||||
it('ensureFmtParam never duplicates fmt on signed urls', () => {
|
||||
const signed = 'https://www.youtube.com/api/timedtext?v=abc&fmt=json3&signature=XYZ';
|
||||
assert.equal(ensureFmtParam(signed), signed);
|
||||
const bare = 'https://www.youtube.com/api/timedtext?v=abc&caps=asr';
|
||||
assert.match(ensureFmtParam(bare), /fmt=json3/);
|
||||
assert.equal(ensureFmtParam('', 'json3'), '');
|
||||
});
|
||||
it('isEmptyTimedTextBody treats 200-empty as transient', () => {
|
||||
assert.equal(isEmptyTimedTextBody(''), true);
|
||||
assert.equal(isEmptyTimedTextBody(' '), true);
|
||||
assert.equal(isEmptyTimedTextBody('<!DOCTYPE html> sorry'), true);
|
||||
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' };
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
describe('capLines + normalizeTranscriptProvider', () => { it('truncates very long transcripts', () => {
|
||||
const lines = Array.from({ length: 10 }, (_, i) => ({ t: i, dur: 1, text: `l${i}` }));
|
||||
assert.equal(capLines(lines, 3).length, 3);
|
||||
|
||||
Reference in New Issue
Block a user