Extract chapters from video page
This commit is contained in:
parent
61e736ce97
commit
12f9f919cf
@ -82,7 +82,33 @@ interface VideoOptions {
|
|||||||
* Gives info about music content in that video.
|
* Gives info about music content in that video.
|
||||||
*/
|
*/
|
||||||
music?: VideoMusic[];
|
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
|
* Class for YouTube Video url
|
||||||
*/
|
*/
|
||||||
@ -163,6 +189,12 @@ export class YouTubeVideo {
|
|||||||
* Gives info about music content in that video.
|
* Gives info about music content in that video.
|
||||||
*/
|
*/
|
||||||
music?: VideoMusic[];
|
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
|
* Constructor for YouTube Video Class
|
||||||
* @param data JSON parsed data.
|
* @param data JSON parsed data.
|
||||||
@ -193,6 +225,7 @@ export class YouTubeVideo {
|
|||||||
this.tags = data.tags || [];
|
this.tags = data.tags || [];
|
||||||
this.discretionAdvised = data.discretionAdvised ?? undefined;
|
this.discretionAdvised = data.discretionAdvised ?? undefined;
|
||||||
this.music = data.music || [];
|
this.music = data.music || [];
|
||||||
|
this.chapters = data.chapters || [];
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Converts class to title name of video.
|
* Converts class to title name of video.
|
||||||
@ -222,7 +255,8 @@ export class YouTubeVideo {
|
|||||||
live: this.live,
|
live: this.live,
|
||||||
private: this.private,
|
private: this.private,
|
||||||
discretionAdvised: this.discretionAdvised,
|
discretionAdvised: this.discretionAdvised,
|
||||||
music: this.music
|
music: this.music,
|
||||||
|
chapters: this.chapters
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { request } from './../../Request/index';
|
import { request } from './../../Request/index';
|
||||||
import { format_decipher } from './cipher';
|
import { format_decipher } from './cipher';
|
||||||
import { YouTubeVideo } from '../classes/Video';
|
import { VideoChapter, YouTubeVideo } from '../classes/Video';
|
||||||
import { YouTubePlayList } from '../classes/Playlist';
|
import { YouTubePlayList } from '../classes/Playlist';
|
||||||
import { InfoData, StreamInfoData } from './constants';
|
import { InfoData, StreamInfoData } from './constants';
|
||||||
import { URL, URLSearchParams } from 'node:url';
|
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;
|
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;
|
let upcomingDate;
|
||||||
if (upcoming) {
|
if (upcoming) {
|
||||||
if (microformat.liveBroadcastDetails.startTimestamp)
|
if (microformat.liveBroadcastDetails.startTimestamp)
|
||||||
@ -271,7 +286,8 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
|
|||||||
live: vid.isLiveContent,
|
live: vid.isLiveContent,
|
||||||
private: vid.isPrivate,
|
private: vid.isPrivate,
|
||||||
discretionAdvised,
|
discretionAdvised,
|
||||||
music
|
music,
|
||||||
|
chapters
|
||||||
});
|
});
|
||||||
let format = [];
|
let format = [];
|
||||||
if (!upcoming) {
|
if (!upcoming) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user