mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-12 05:51:44 +08:00
feat(youtube-transcript): add end times to chapter data
Add 'end' field to Chapter interface and parseChapters output.
Each chapter's end is derived from the next chapter's start time,
with the last chapter ending at the video's total duration.
This makes chapter data complete and ready for downstream consumers
(e.g. video clipping with ffmpeg) without requiring them to compute
end times from adjacent chapters.
Before: { title: 'Overview', start: 0 }
After: { title: 'Overview', start: 0, end: 21 }
This commit is contained in:
@@ -44,6 +44,7 @@ interface TranscriptInfo {
|
||||
interface Chapter {
|
||||
title: string;
|
||||
start: number;
|
||||
end: number;
|
||||
}
|
||||
|
||||
interface VideoMeta {
|
||||
@@ -249,16 +250,21 @@ async function fetchTranscriptSnippets(info: TranscriptInfo, translateTo?: strin
|
||||
|
||||
// --- Metadata & chapters ---
|
||||
|
||||
function parseChapters(description: string): Chapter[] {
|
||||
const chapters: Chapter[] = [];
|
||||
function parseChapters(description: string, duration: number = 0): Chapter[] {
|
||||
const raw: { title: string; start: number }[] = [];
|
||||
for (const line of description.split("\n")) {
|
||||
const m = line.trim().match(/^(?:(\d{1,2}):)?(\d{1,2}):(\d{2})\s+(.+)$/);
|
||||
if (m) {
|
||||
const h = m[1] ? parseInt(m[1]) : 0;
|
||||
chapters.push({ title: m[4].trim(), start: h * 3600 + parseInt(m[2]) * 60 + parseInt(m[3]) });
|
||||
raw.push({ title: m[4].trim(), start: h * 3600 + parseInt(m[2]) * 60 + parseInt(m[3]) });
|
||||
}
|
||||
}
|
||||
return chapters.length >= 2 ? chapters : [];
|
||||
if (raw.length < 2) return [];
|
||||
return raw.map((ch, i) => ({
|
||||
title: ch.title,
|
||||
start: ch.start,
|
||||
end: i < raw.length - 1 ? raw[i + 1].start : duration,
|
||||
}));
|
||||
}
|
||||
|
||||
function getThumbnailUrls(videoId: string, data: any): string[] {
|
||||
@@ -644,7 +650,8 @@ async function fetchAndCache(videoId: string, baseDir: string, opts: Options): P
|
||||
const info = findTranscript(transcripts, opts.languages, opts.excludeGenerated, opts.excludeManual);
|
||||
const result = await fetchTranscriptSnippets(info, opts.translate || undefined);
|
||||
const description = data?.videoDetails?.shortDescription || "";
|
||||
const chapters = parseChapters(description);
|
||||
const duration = parseInt(data?.videoDetails?.lengthSeconds || "0");
|
||||
const chapters = parseChapters(description, duration);
|
||||
const langInfo = { code: result.languageCode, name: result.language, isGenerated: info.isGenerated };
|
||||
const meta = buildVideoMeta(data, videoId, langInfo, chapters);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user