Video Info bug fixes and stream improvements

This commit is contained in:
Atari Tom 2022-05-27 15:35:02 -04:00
parent 126c5f98d1
commit a0e3ae88c2
6 changed files with 16 additions and 12 deletions

14
package-lock.json generated
View File

@ -18,7 +18,7 @@
"typedoc": "^0.22.11", "typedoc": "^0.22.11",
"typedoc-plugin-extras": "^2.2.1", "typedoc-plugin-extras": "^2.2.1",
"typedoc-plugin-missing-exports": "^0.22.4", "typedoc-plugin-missing-exports": "^0.22.4",
"typescript": "^4.5.5" "typescript": "^4.7.2"
}, },
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"
@ -1460,9 +1460,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.6.4", "version": "4.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz",
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@ -2454,9 +2454,9 @@
"requires": {} "requires": {}
}, },
"typescript": { "typescript": {
"version": "4.6.4", "version": "4.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz",
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==",
"dev": true "dev": true
}, },
"vscode-oniguruma": { "vscode-oniguruma": {

View File

@ -48,7 +48,7 @@
"typedoc": "^0.22.11", "typedoc": "^0.22.11",
"typedoc-plugin-extras": "^2.2.1", "typedoc-plugin-extras": "^2.2.1",
"typedoc-plugin-missing-exports": "^0.22.4", "typedoc-plugin-missing-exports": "^0.22.4",
"typescript": "^4.5.5" "typescript": "^4.7.2"
}, },
"dependencies": { "dependencies": {
"play-audio": "^0.5.2" "play-audio": "^0.5.2"

View File

@ -71,6 +71,7 @@ export class SeekStream {
duration: number, duration: number,
headerLength: number, headerLength: number,
contentLength: number, contentLength: number,
bitrate: number,
video_url: string, video_url: string,
options: StreamOptions options: StreamOptions
) { ) {
@ -83,7 +84,7 @@ export class SeekStream {
this.type = StreamType.Opus; this.type = StreamType.Opus;
this.bytes_count = 0; this.bytes_count = 0;
this.video_url = video_url; this.video_url = video_url;
this.per_sec_bytes = Math.ceil(contentLength / duration); this.per_sec_bytes = bitrate ? Math.ceil(bitrate / 8) : Math.ceil(contentLength / duration);
this.header_length = headerLength; this.header_length = headerLength;
this.content_length = contentLength; this.content_length = contentLength;
this.request = null; this.request = null;

View File

@ -65,6 +65,8 @@ export async function stream_from_info(
): Promise<YouTubeStream> { ): Promise<YouTubeStream> {
if (info.format.length === 0) if (info.format.length === 0)
throw new Error('Upcoming and premiere videos that are not currently live cannot be streamed.'); throw new Error('Upcoming and premiere videos that are not currently live cannot be streamed.');
if (options.quality && !Number.isInteger(options.quality))
throw new Error("Quality must be set to an integer.")
const final: any[] = []; const final: any[] = [];
if ( if (
@ -99,6 +101,7 @@ export async function stream_from_info(
info.video_details.durationInSec, info.video_details.durationInSec,
final[0].indexRange.end, final[0].indexRange.end,
Number(final[0].contentLength), Number(final[0].contentLength),
Number(final[0].bitrate),
info.video_details.url, info.video_details.url,
options options
); );

View File

@ -151,7 +151,7 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
const player_data = body const player_data = body
.split('var ytInitialPlayerResponse = ')?.[1] .split('var ytInitialPlayerResponse = ')?.[1]
?.split(';</script>')[0] ?.split(';</script>')[0]
.split(/;\s*(var|const|let)\s/)[0]; .split(/(?<=}}});\s*(var|const|let)\s/)[0];
if (!player_data) throw new Error('Initial Player Response Data is undefined.'); if (!player_data) throw new Error('Initial Player Response Data is undefined.');
const initial_data = body const initial_data = body
.split('var ytInitialData = ')?.[1] .split('var ytInitialData = ')?.[1]
@ -349,7 +349,7 @@ export async function video_stream_info(url: string, options: InfoOptions = {}):
const player_data = body const player_data = body
.split('var ytInitialPlayerResponse = ')?.[1] .split('var ytInitialPlayerResponse = ')?.[1]
?.split(';</script>')[0] ?.split(';</script>')[0]
.split(/;\s*(var|const|let)\s/)[0]; .split(/(?<=}}});\s*(var|const|let)\s/)[0];
if (!player_data) throw new Error('Initial Player Response Data is undefined.'); if (!player_data) throw new Error('Initial Player Response Data is undefined.');
const player_response = JSON.parse(player_data); const player_response = JSON.parse(player_data);
let upcoming = false; let upcoming = false;

View File

@ -146,7 +146,7 @@ export function parseVideo(data?: any): YouTubeVideo {
id: data.videoRenderer.videoId, id: data.videoRenderer.videoId,
url: `https://www.youtube.com/watch?v=${data.videoRenderer.videoId}`, url: `https://www.youtube.com/watch?v=${data.videoRenderer.videoId}`,
title: data.videoRenderer.title.runs[0].text, title: data.videoRenderer.title.runs[0].text,
description: data.videoRenderer.detailedMetadataSnippets?.[0].snippetText.runs.length description: data.videoRenderer.detailedMetadataSnippets?.[0].snippetText.runs?.length
? data.videoRenderer.detailedMetadataSnippets[0].snippetText.runs.map((run: any) => run.text).join('') ? data.videoRenderer.detailedMetadataSnippets[0].snippetText.runs.map((run: any) => run.text).join('')
: '', : '',
duration: durationText ? parseDuration(durationText.simpleText) : 0, duration: durationText ? parseDuration(durationText.simpleText) : 0,