Extract chapters from video page

This commit is contained in:
absidue 2022-03-10 20:31:49 +01:00
parent 61e736ce97
commit 12f9f919cf
2 changed files with 53 additions and 3 deletions

View File

@ -82,7 +82,33 @@ interface VideoOptions {
* Gives info about music content in that video.
*/
music?: VideoMusic[];
/**
* The chapters for this video
*
* If the video doesn't have any chapters or if the video object wasn't created by {@link video_basic_info} or {@link video_info} this will be an empty array.
*/
chapters: VideoChapter[];
}
export interface VideoChapter {
/**
* The title of the chapter
*/
title: string;
/**
* The timestamp of the start of the chapter
*/
timestamp: string;
/**
* The start of the chapter in seconds
*/
seconds: number;
/**
* Thumbnails of the frame at the start of this chapter
*/
thumbnails: YouTubeThumbnail[];
}
/**
* Class for YouTube Video url
*/
@ -163,6 +189,12 @@ export class YouTubeVideo {
* Gives info about music content in that video.
*/
music?: VideoMusic[];
/**
* The chapters for this video
*
* If the video doesn't have any chapters or if the video object wasn't created by {@link video_basic_info} or {@link video_info} this will be an empty array.
*/
chapters: VideoChapter[];
/**
* Constructor for YouTube Video Class
* @param data JSON parsed data.
@ -193,6 +225,7 @@ export class YouTubeVideo {
this.tags = data.tags || [];
this.discretionAdvised = data.discretionAdvised ?? undefined;
this.music = data.music || [];
this.chapters = data.chapters || [];
}
/**
* Converts class to title name of video.
@ -222,7 +255,8 @@ export class YouTubeVideo {
live: this.live,
private: this.private,
discretionAdvised: this.discretionAdvised,
music: this.music
music: this.music,
chapters: this.chapters
};
}
}

View File

@ -1,6 +1,6 @@
import { request } from './../../Request/index';
import { format_decipher } from './cipher';
import { YouTubeVideo } from '../classes/Video';
import { VideoChapter, YouTubeVideo } from '../classes/Video';
import { YouTubePlayList } from '../classes/Playlist';
import { InfoData, StreamInfoData } from './constants';
import { URL, URLSearchParams } from 'node:url';
@ -229,6 +229,21 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
x.metadataRowRenderer.contents[0].simpleText ?? x.metadataRowRenderer.contents[0]?.runs?.[0]?.text;
});
}
const rawChapters =
initial_response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer.decoratedPlayerBarRenderer.playerBar?.multiMarkersPlayerBarRenderer.markersMap.find(
(m: any) => m.key === 'DESCRIPTION_CHAPTERS'
).value.chapters;
const chapters: VideoChapter[] = [];
if (rawChapters) {
for (const { chapterRenderer } of rawChapters) {
chapters.push({
title: chapterRenderer.title.simpleText,
timestamp: parseSeconds(chapterRenderer.timeRangeStartMillis / 1000),
seconds: chapterRenderer.timeRangeStartMillis / 1000,
thumbnails: chapterRenderer.thumbnail.thumbnails
});
}
}
let upcomingDate;
if (upcoming) {
if (microformat.liveBroadcastDetails.startTimestamp)
@ -271,7 +286,8 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
live: vid.isLiveContent,
private: vid.isPrivate,
discretionAdvised,
music
music,
chapters
});
let format = [];
if (!upcoming) {