Compare commits
11 Commits
5583d99ab4
...
45fefec624
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45fefec624 | ||
|
|
60d5ea6700 | ||
|
|
2bfbfe6dec | ||
|
|
6a8569feb8 | ||
|
|
76c237346e | ||
|
|
58f79fcacc | ||
|
|
1ae7ba8fce | ||
|
|
3147d98760 | ||
|
|
9661d8f17a | ||
|
|
fc6007b472 | ||
|
|
5dc1eff4eb |
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@ -2,7 +2,6 @@ name: Publish NPM package + Docs
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
jobs:
|
||||||
publish_npm:
|
publish_npm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
28
package-lock.json
generated
28
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "play-dl",
|
"name": "play-dl",
|
||||||
"version": "1.9.5",
|
"version": "1.9.7",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "play-dl",
|
"name": "play-dl",
|
||||||
"version": "1.9.5",
|
"version": "1.9.7",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"play-audio": "^0.5.2"
|
"play-audio": "^0.5.2"
|
||||||
@ -971,9 +971,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@ -1518,9 +1518,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.8.4",
|
"version": "4.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||||
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
|
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@ -2204,9 +2204,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@ -2572,9 +2572,9 @@
|
|||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.8.4",
|
"version": "4.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||||
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
|
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"vscode-oniguruma": {
|
"vscode-oniguruma": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "play-dl",
|
"name": "play-dl",
|
||||||
"version": "1.9.5",
|
"version": "1.9.7",
|
||||||
"description": "YouTube, SoundCloud, Spotify, Deezer searching and streaming for discord-js bots",
|
"description": "YouTube, SoundCloud, Spotify, Deezer searching and streaming for discord-js bots",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
@ -39,7 +39,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/play-dl/play-dl#readme",
|
"homepage": "https://github.com/play-dl/play-dl#readme",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/*"
|
"dist/*",
|
||||||
|
"play-dl/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.7.23",
|
"@types/node": "^18.7.23",
|
||||||
|
|||||||
@ -111,10 +111,14 @@ export async function stream(url: string, quality?: number): Promise<SoundCloudS
|
|||||||
* @returns client ID
|
* @returns client ID
|
||||||
*/
|
*/
|
||||||
export async function getFreeClientID(): Promise<string> {
|
export async function getFreeClientID(): Promise<string> {
|
||||||
const data = await request('https://soundcloud.com/');
|
const data: any = await request('https://soundcloud.com/', {headers: {}}).catch(err => err);
|
||||||
|
|
||||||
|
if (data instanceof Error)
|
||||||
|
throw new Error("Failed to get response from soundcloud.com: " + data.message);
|
||||||
|
|
||||||
const splitted = data.split('<script crossorigin src="');
|
const splitted = data.split('<script crossorigin src="');
|
||||||
const urls: string[] = [];
|
const urls: string[] = [];
|
||||||
splitted.forEach((r) => {
|
splitted.forEach((r: string) => {
|
||||||
if (r.startsWith('https')) {
|
if (r.startsWith('https')) {
|
||||||
urls.push(r.split('"')[0]);
|
urls.push(r.split('"')[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,10 @@ export class SpotifyTrack {
|
|||||||
* Spotify Track ID
|
* Spotify Track ID
|
||||||
*/
|
*/
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* Spotify Track ISRC
|
||||||
|
*/
|
||||||
|
isrc: string;
|
||||||
/**
|
/**
|
||||||
* Spotify Track url
|
* Spotify Track url
|
||||||
*/
|
*/
|
||||||
@ -124,6 +128,7 @@ export class SpotifyTrack {
|
|||||||
constructor(data: any) {
|
constructor(data: any) {
|
||||||
this.name = data.name;
|
this.name = data.name;
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
|
this.isrc = data.external_ids?.isrc || '';
|
||||||
this.type = 'track';
|
this.type = 'track';
|
||||||
this.url = data.external_urls.spotify;
|
this.url = data.external_urls.spotify;
|
||||||
this.explicit = data.explicit;
|
this.explicit = data.explicit;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export interface SpotifyDataOptions {
|
|||||||
file?: boolean;
|
file?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pattern = /^((https:)?\/\/)?open.spotify.com\/(track|album|playlist)\//;
|
const pattern = /^((https:)?\/\/)?open\.spotify\.com\/(?:intl\-.{2}\/)?(track|album|playlist)\//;
|
||||||
/**
|
/**
|
||||||
* Gets Spotify url details.
|
* Gets Spotify url details.
|
||||||
*
|
*
|
||||||
@ -55,7 +55,9 @@ export async function spotify(url: string): Promise<Spotify> {
|
|||||||
return err;
|
return err;
|
||||||
});
|
});
|
||||||
if (response instanceof Error) throw response;
|
if (response instanceof Error) throw response;
|
||||||
return new SpotifyTrack(JSON.parse(response));
|
const resObj = JSON.parse(response);
|
||||||
|
if (resObj.error) throw new Error(`Got ${resObj.error.status} from the spotify request: ${resObj.error.message}`);
|
||||||
|
return new SpotifyTrack(resObj);
|
||||||
} else if (url_.indexOf('album/') !== -1) {
|
} else if (url_.indexOf('album/') !== -1) {
|
||||||
const albumID = url.split('album/')[1].split('&')[0].split('?')[0];
|
const albumID = url.split('album/')[1].split('&')[0].split('?')[0];
|
||||||
const response = await request(`https://api.spotify.com/v1/albums/${albumID}?market=${spotifyData.market}`, {
|
const response = await request(`https://api.spotify.com/v1/albums/${albumID}?market=${spotifyData.market}`, {
|
||||||
@ -66,7 +68,9 @@ export async function spotify(url: string): Promise<Spotify> {
|
|||||||
return err;
|
return err;
|
||||||
});
|
});
|
||||||
if (response instanceof Error) throw response;
|
if (response instanceof Error) throw response;
|
||||||
return new SpotifyAlbum(JSON.parse(response), spotifyData, false);
|
const resObj = JSON.parse(response);
|
||||||
|
if (resObj.error) throw new Error(`Got ${resObj.error.status} from the spotify request: ${resObj.error.message}`);
|
||||||
|
return new SpotifyAlbum(resObj, spotifyData, false);
|
||||||
} else if (url_.indexOf('playlist/') !== -1) {
|
} else if (url_.indexOf('playlist/') !== -1) {
|
||||||
const playlistID = url.split('playlist/')[1].split('&')[0].split('?')[0];
|
const playlistID = url.split('playlist/')[1].split('&')[0].split('?')[0];
|
||||||
const response = await request(
|
const response = await request(
|
||||||
@ -80,7 +84,9 @@ export async function spotify(url: string): Promise<Spotify> {
|
|||||||
return err;
|
return err;
|
||||||
});
|
});
|
||||||
if (response instanceof Error) throw response;
|
if (response instanceof Error) throw response;
|
||||||
return new SpotifyPlaylist(JSON.parse(response), spotifyData, false);
|
const resObj = JSON.parse(response);
|
||||||
|
if (resObj.error) throw new Error(`Got ${resObj.error.status} from the spotify request: ${resObj.error.message}`);
|
||||||
|
return new SpotifyPlaylist(resObj, spotifyData, false);
|
||||||
} else throw new Error('URL is out of scope for play-dl.');
|
} else throw new Error('URL is out of scope for play-dl.');
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,16 +7,12 @@ import { YouTubeThumbnail } from './Thumbnail';
|
|||||||
* The property names change depending on your region's language.
|
* The property names change depending on your region's language.
|
||||||
*/
|
*/
|
||||||
interface VideoMusic {
|
interface VideoMusic {
|
||||||
song?: string | MusicEntry;
|
song?: string;
|
||||||
artist?: string | MusicEntry;
|
url?: string | null;
|
||||||
|
artist?: string;
|
||||||
album?: string;
|
album?: string;
|
||||||
writers?: string;
|
writers?: string;
|
||||||
license?: string;
|
licenses?: string;
|
||||||
}
|
|
||||||
|
|
||||||
interface MusicEntry {
|
|
||||||
text?: string;
|
|
||||||
url?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VideoOptions {
|
interface VideoOptions {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ const video_id_pattern = /^[a-zA-Z\d_-]{11,12}$/;
|
|||||||
const playlist_id_pattern = /^(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}$/;
|
const playlist_id_pattern = /^(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}$/;
|
||||||
const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8';
|
const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8';
|
||||||
const video_pattern =
|
const video_pattern =
|
||||||
/^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|shorts\/|embed\/|v\/)?)([\w\-]+)(\S+)?$/;
|
/^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|shorts\/|embed\/|live\/|v\/)?)([\w\-]+)(\S+)?$/;
|
||||||
const playlist_pattern =
|
const playlist_pattern =
|
||||||
/^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))\/(?:(playlist|watch))?(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}(&.*)?$/;
|
/^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))\/(?:(playlist|watch))?(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}(&.*)?$/;
|
||||||
/**
|
/**
|
||||||
@ -81,6 +81,8 @@ function extractVideoId(urlOrId: string): string | false {
|
|||||||
id = urlOrId.split('youtube.com/embed/')[1].split(/(\?|\/|&)/)[0];
|
id = urlOrId.split('youtube.com/embed/')[1].split(/(\?|\/|&)/)[0];
|
||||||
} else if (urlOrId.includes('youtube.com/shorts/')) {
|
} else if (urlOrId.includes('youtube.com/shorts/')) {
|
||||||
id = urlOrId.split('youtube.com/shorts/')[1].split(/(\?|\/|&)/)[0];
|
id = urlOrId.split('youtube.com/shorts/')[1].split(/(\?|\/|&)/)[0];
|
||||||
|
} else if (urlOrId.includes('youtube.com/live/')) {
|
||||||
|
id = urlOrId.split('youtube.com/live/')[1].split(/(\?|\/|&)/)[0];
|
||||||
} else {
|
} else {
|
||||||
id = (urlOrId.split('watch?v=')[1] ?? urlOrId.split('&v=')[1]).split(/(\?|\/|&)/)[0];
|
id = (urlOrId.split('watch?v=')[1] ?? urlOrId.split('&v=')[1]).split(/(\?|\/|&)/)[0];
|
||||||
}
|
}
|
||||||
@ -212,28 +214,26 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const microformat = player_response.microformat.playerMicroformatRenderer;
|
const microformat = player_response.microformat.playerMicroformatRenderer;
|
||||||
const musicInfo =
|
const musicInfo = initial_response.engagementPanels.find((item: any) => item?.engagementPanelSectionListRenderer?.panelIdentifier == 'engagement-panel-structured-description')?.engagementPanelSectionListRenderer.content.structuredDescriptionContentRenderer.items
|
||||||
initial_response.contents.twoColumnWatchNextResults.results.results.contents?.[1]?.videoSecondaryInfoRenderer
|
.find((el: any) => el.videoDescriptionMusicSectionRenderer)?.videoDescriptionMusicSectionRenderer.carouselLockups;
|
||||||
?.metadataRowContainer?.metadataRowContainerRenderer?.rows;
|
|
||||||
const music: any[] = [];
|
const music: any[] = [];
|
||||||
if (musicInfo) {
|
if (musicInfo) {
|
||||||
musicInfo.forEach((x: any) => {
|
musicInfo.forEach((x: any) => {
|
||||||
if (!x.metadataRowRenderer) return;
|
if (!x.carouselLockupRenderer) return;
|
||||||
const row = x.metadataRowRenderer;
|
const row = x.carouselLockupRenderer;
|
||||||
|
|
||||||
const title = row.title.simpleText ?? row.title.runs[0].text;
|
const song = row.videoLockup?.compactVideoRenderer.title.simpleText ?? row.videoLockup?.compactVideoRenderer.title.runs?.find((x:any) => x.text)?.text;
|
||||||
const contents = row.contents[0].simpleText ?? row.contents[0]?.runs?.[0]?.text;
|
const metadata = row.infoRows?.map((info: any) => [info.infoRowRenderer.title.simpleText.toLowerCase(), ((info.infoRowRenderer.expandedMetadata ?? info.infoRowRenderer.defaultMetadata)?.runs?.map((i:any) => i.text).join("")) ?? info.infoRowRenderer.defaultMetadata?.simpleText ?? info.infoRowRenderer.expandedMetadata?.simpleText ?? ""]);
|
||||||
const url = row.contents[0]?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata.url;
|
const contents = Object.fromEntries(metadata ?? {});
|
||||||
|
const id = row.videoLockup?.compactVideoRenderer.navigationEndpoint?.watchEndpoint.videoId
|
||||||
|
?? row.infoRows?.find((x: any) => x.infoRowRenderer.title.simpleText.toLowerCase() == "song")?.infoRowRenderer.defaultMetadata.runs?.find((x: any) => x.navigationEndpoint)?.navigationEndpoint.watchEndpoint?.videoId;
|
||||||
|
|
||||||
if (music.length === 0) music.push({});
|
music.push({song, url: id ? `https://www.youtube.com/watch?v=${id}` : null, ...contents})
|
||||||
|
|
||||||
music[music.length - 1][title.toLowerCase()] = url ? {text: contents, url: `https://www.youtube.com${url}`} : contents;
|
|
||||||
|
|
||||||
if (row.hasDividerLine) music.push({});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const rawChapters =
|
const rawChapters =
|
||||||
initial_response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer?.decoratedPlayerBarRenderer.playerBar?.multiMarkersPlayerBarRenderer.markersMap.find(
|
initial_response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer?.decoratedPlayerBarRenderer.playerBar?.multiMarkersPlayerBarRenderer.markersMap?.find(
|
||||||
(m: any) => m.key === 'DESCRIPTION_CHAPTERS'
|
(m: any) => m.key === 'DESCRIPTION_CHAPTERS'
|
||||||
)?.value?.chapters;
|
)?.value?.chapters;
|
||||||
const chapters: VideoChapter[] = [];
|
const chapters: VideoChapter[] = [];
|
||||||
@ -258,6 +258,13 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
|
|||||||
upcomingDate = new Date(parseInt(timestamp) * 1000);
|
upcomingDate = new Date(parseInt(timestamp) * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const likeRenderer = initial_response.contents.twoColumnWatchNextResults.results.results.contents
|
||||||
|
.find((content: any) => content.videoPrimaryInfoRenderer)
|
||||||
|
?.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons?.find(
|
||||||
|
(button: any) => button.toggleButtonRenderer?.defaultIcon.iconType === 'LIKE' || button.segmentedLikeDislikeButtonRenderer?.likeButton.toggleButtonRenderer?.defaultIcon.iconType === 'LIKE'
|
||||||
|
)
|
||||||
|
|
||||||
const video_details = new YouTubeVideo({
|
const video_details = new YouTubeVideo({
|
||||||
id: vid.videoId,
|
id: vid.videoId,
|
||||||
title: vid.title,
|
title: vid.title,
|
||||||
@ -279,12 +286,8 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
|
|||||||
views: vid.viewCount,
|
views: vid.viewCount,
|
||||||
tags: vid.keywords,
|
tags: vid.keywords,
|
||||||
likes: parseInt(
|
likes: parseInt(
|
||||||
initial_response.contents.twoColumnWatchNextResults.results.results.contents
|
likeRenderer?.toggleButtonRenderer?.defaultText.accessibility?.accessibilityData.label.replace(/\D+/g, '') ??
|
||||||
.find((content: any) => content.videoPrimaryInfoRenderer)
|
likeRenderer?.segmentedLikeDislikeButtonRenderer?.likeButton.toggleButtonRenderer?.defaultText.accessibility?.accessibilityData.label.replace(/\D+/g, '') ?? 0
|
||||||
?.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons?.find(
|
|
||||||
(button: any) => button.toggleButtonRenderer.defaultIcon.iconType === 'LIKE'
|
|
||||||
)
|
|
||||||
?.toggleButtonRenderer.defaultText.accessibility?.accessibilityData.label.replace(/\D+/g, '') ?? 0
|
|
||||||
),
|
),
|
||||||
live: vid.isLiveContent,
|
live: vid.isLiveContent,
|
||||||
private: vid.isPrivate,
|
private: vid.isPrivate,
|
||||||
@ -294,15 +297,17 @@ export async function video_basic_info(url: string, options: InfoOptions = {}):
|
|||||||
});
|
});
|
||||||
let format = [];
|
let format = [];
|
||||||
if (!upcoming) {
|
if (!upcoming) {
|
||||||
format.push(...(player_response.streamingData.formats ?? []));
|
// TODO: Properly handle the formats, for now ignore and use iOS formats
|
||||||
format.push(...(player_response.streamingData.adaptiveFormats ?? []));
|
//format.push(...(player_response.streamingData.formats ?? []));
|
||||||
|
//format.push(...(player_response.streamingData.adaptiveFormats ?? []));
|
||||||
|
|
||||||
// get the formats for the android player for legacy videos
|
// get the formats for the android player for legacy videos
|
||||||
// fixes the stream being closed because not enough data
|
// fixes the stream being closed because not enough data
|
||||||
// arrived in time for ffmpeg to be able to extract audio data
|
// arrived in time for ffmpeg to be able to extract audio data
|
||||||
if (parseAudioFormats(format).length === 0 && !options.htmldata) {
|
//if (parseAudioFormats(format).length === 0 && !options.htmldata) {
|
||||||
format = await getAndroidFormats(vid.videoId, cookieJar, body);
|
// format = await getAndroidFormats(vid.videoId, cookieJar, body);
|
||||||
}
|
//}
|
||||||
|
format = await getIosFormats(vid.videoId, cookieJar, body);
|
||||||
}
|
}
|
||||||
const LiveStreamData = {
|
const LiveStreamData = {
|
||||||
isLive: video_details.live,
|
isLive: video_details.live,
|
||||||
@ -401,15 +406,17 @@ export async function video_stream_info(url: string, options: InfoOptions = {}):
|
|||||||
};
|
};
|
||||||
let format = [];
|
let format = [];
|
||||||
if (!upcoming) {
|
if (!upcoming) {
|
||||||
format.push(...(player_response.streamingData.formats ?? []));
|
// TODO: Properly handle the formats, for now ignore and use iOS formats
|
||||||
format.push(...(player_response.streamingData.adaptiveFormats ?? []));
|
//format.push(...(player_response.streamingData.formats ?? []));
|
||||||
|
//format.push(...(player_response.streamingData.adaptiveFormats ?? []));
|
||||||
|
|
||||||
// get the formats for the android player for legacy videos
|
// get the formats for the android player for legacy videos
|
||||||
// fixes the stream being closed because not enough data
|
// fixes the stream being closed because not enough data
|
||||||
// arrived in time for ffmpeg to be able to extract audio data
|
// arrived in time for ffmpeg to be able to extract audio data
|
||||||
if (parseAudioFormats(format).length === 0 && !options.htmldata) {
|
//if (parseAudioFormats(format).length === 0 && !options.htmldata) {
|
||||||
format = await getAndroidFormats(player_response.videoDetails.videoId, cookieJar, body);
|
// format = await getAndroidFormats(player_response.videoDetails.videoId, cookieJar, body);
|
||||||
}
|
//}
|
||||||
|
format = await getIosFormats(player_response.videoDetails.videoId, cookieJar, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LiveStreamData = {
|
const LiveStreamData = {
|
||||||
@ -541,7 +548,7 @@ export async function playlist_info(url: string, options: PlaylistOptions = {}):
|
|||||||
throw new Error(`While parsing playlist url\n${response.alerts[0].alertRenderer.text.runs[0].text}`);
|
throw new Error(`While parsing playlist url\n${response.alerts[0].alertRenderer.text.runs[0].text}`);
|
||||||
else throw new Error('While parsing playlist url\nUnknown Playlist Error');
|
else throw new Error('While parsing playlist url\nUnknown Playlist Error');
|
||||||
}
|
}
|
||||||
if (url_.indexOf('watch?v=') !== -1) {
|
if (response.currentVideoEndpoint) {
|
||||||
return getWatchPlaylist(response, body, url_);
|
return getWatchPlaylist(response, body, url_);
|
||||||
} else return getNormalPlaylist(response, body);
|
} else return getNormalPlaylist(response, body);
|
||||||
}
|
}
|
||||||
@ -628,7 +635,7 @@ async function acceptViewerDiscretion(
|
|||||||
},
|
},
|
||||||
nextEndpoint: {
|
nextEndpoint: {
|
||||||
urlEndpoint: {
|
urlEndpoint: {
|
||||||
url: `watch?v=${videoId}`
|
url: `/watch?v=${videoId}&has_verified=1`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setControvercy: true
|
setControvercy: true
|
||||||
@ -677,7 +684,7 @@ async function acceptViewerDiscretion(
|
|||||||
return { streamingData };
|
return { streamingData };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAndroidFormats(videoId: string, cookieJar: { [key: string]: string }, body: string): Promise<any[]> {
|
async function getIosFormats(videoId: string, cookieJar: { [key: string]: string }, body: string): Promise<any[]> {
|
||||||
const apiKey =
|
const apiKey =
|
||||||
body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ??
|
body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ??
|
||||||
body.split('innertubeApiKey":"')[1]?.split('"')[0] ??
|
body.split('innertubeApiKey":"')[1]?.split('"')[0] ??
|
||||||
@ -688,8 +695,10 @@ async function getAndroidFormats(videoId: string, cookieJar: { [key: string]: st
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
context: {
|
context: {
|
||||||
client: {
|
client: {
|
||||||
clientName: 'ANDROID',
|
clientName: 'IOS',
|
||||||
clientVersion: '16.49',
|
clientVersion: '19.09.3',
|
||||||
|
deviceModel: 'iPhone16,1',
|
||||||
|
userAgent: 'com.google.ios.youtube/19.09.3 (iPhone; CPU iPhone OS 17_5 like Mac OS X)',
|
||||||
hl: 'en',
|
hl: 'en',
|
||||||
timeZone: 'UTC',
|
timeZone: 'UTC',
|
||||||
utcOffsetMinutes: 0
|
utcOffsetMinutes: 0
|
||||||
@ -704,7 +713,8 @@ async function getAndroidFormats(videoId: string, cookieJar: { [key: string]: st
|
|||||||
cookieJar
|
cookieJar
|
||||||
});
|
});
|
||||||
|
|
||||||
return JSON.parse(response).streamingData.formats;
|
return JSON.parse(response).streamingData.adaptiveFormats;
|
||||||
|
//return JSON.parse(response).streamingData.formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWatchPlaylist(response: any, body: any, url: string): YouTubePlayList {
|
function getWatchPlaylist(response: any, body: any, url: string): YouTubePlayList {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user