* Add basic skeletons for Invidious captions api * Add logic to fetch and convert transcripts to vtt * Use transcripts logic in captions route * Format * Fix lint
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { Innertube } from "youtubei.js";
|
||
|
||
function createTemporalDuration(milliseconds) {
|
||
return new Temporal.Duration(
|
||
undefined,
|
||
undefined,
|
||
undefined,
|
||
undefined,
|
||
undefined,
|
||
undefined,
|
||
undefined,
|
||
milliseconds,
|
||
);
|
||
}
|
||
|
||
const ESCAPE_SUBSTITUTIONS = {
|
||
"&": "&",
|
||
"<": "<",
|
||
">": ">",
|
||
"\u200E": "‎",
|
||
"\u200F": "‏",
|
||
"\u00A0": " ",
|
||
};
|
||
|
||
export async function handleTranscripts(
|
||
innertubeClient: Innertube,
|
||
videoId: string,
|
||
selectedCaption,
|
||
) {
|
||
const lines: string[] = ["WEBVTT"];
|
||
|
||
const info = await innertubeClient.getInfo(videoId);
|
||
const transcriptInfo = await (await info.getTranscript()).selectLanguage(
|
||
selectedCaption.name.simpleText,
|
||
);
|
||
const rawTranscriptLines =
|
||
transcriptInfo.transcript.content.body.initial_segments;
|
||
|
||
rawTranscriptLines.forEach((line) => {
|
||
const timestampFormatOptions = {
|
||
style: "digital",
|
||
minutesDisplay: "always",
|
||
fractionalDigits: 3,
|
||
};
|
||
|
||
const start_ms = createTemporalDuration(line.start_ms).round({
|
||
largestUnit: "year",
|
||
}).toLocaleString(undefined, timestampFormatOptions);
|
||
const end_ms = createTemporalDuration(line.end_ms).round({
|
||
largestUnit: "year",
|
||
}).toLocaleString(undefined, timestampFormatOptions);
|
||
const timestamp = `${start_ms} --> ${end_ms}`;
|
||
|
||
const text = line.snippet.text.replace(
|
||
/[&<>\u200E\u200F\u00A0]/g,
|
||
(match) => ESCAPE_SUBSTITUTIONS[match],
|
||
);
|
||
|
||
lines.push(`${timestamp}\n${text}`);
|
||
});
|
||
|
||
return lines.join("\n\n");
|
||
}
|