mirror of
https://github.com/YuzuZensai/play-dl-test.git
synced 2026-01-06 04:32:40 +00:00
Some huge changes
This commit is contained in:
@@ -104,7 +104,7 @@ export class LiveStream {
|
||||
info.LiveStreamData.hlsManifestUrl !== null &&
|
||||
info.video_details.durationInSec === 0
|
||||
) {
|
||||
this.url = info.LiveStreamData.dashManifestUrl;
|
||||
this.url = info.LiveStreamData.dashManifestUrl as string;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getPlaylistVideos, getContinuationToken } from '../utils/extractor';
|
||||
import { request } from '../../Request';
|
||||
import { YouTubeChannel } from './Channel';
|
||||
import { YouTubeVideo } from './Video';
|
||||
import { YouTubeThumbnail } from './Thumbnail';
|
||||
const BASE_API = 'https://www.youtube.com/youtubei/v1/browse?key=';
|
||||
/**
|
||||
* YouTube Playlist Class containing vital informations about playlist.
|
||||
@@ -46,12 +47,7 @@ export class YouTubePlayList {
|
||||
/**
|
||||
* YouTube Playlist thumbnail Data
|
||||
*/
|
||||
thumbnail?: {
|
||||
id: string | undefined;
|
||||
width: number | undefined;
|
||||
height: number | undefined;
|
||||
url: string | undefined;
|
||||
};
|
||||
thumbnail?: YouTubeThumbnail
|
||||
/**
|
||||
* Videos array containing data of first 100 videos
|
||||
*/
|
||||
@@ -238,7 +234,7 @@ export class YouTubePlayList {
|
||||
return {
|
||||
id: this.id,
|
||||
title: this.title,
|
||||
thumbnail: this.thumbnail,
|
||||
thumbnail: this.thumbnail?.toJSON() || this.thumbnail,
|
||||
channel: this.channel,
|
||||
url: this.url,
|
||||
videos: this.videos
|
||||
|
||||
22
play-dl/YouTube/classes/Thumbnail.ts
Normal file
22
play-dl/YouTube/classes/Thumbnail.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export class YouTubeThumbnail {
|
||||
id : string;
|
||||
url : string;
|
||||
width : number;
|
||||
height : number;
|
||||
|
||||
constructor(data : any){
|
||||
this.id = data.id
|
||||
this.url = data.url
|
||||
this.width = data.width
|
||||
this.height = data.height
|
||||
}
|
||||
|
||||
toJSON(){
|
||||
return {
|
||||
id : this.id,
|
||||
url : this.url,
|
||||
width : this.width,
|
||||
height : this.height
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,145 @@
|
||||
import { YouTubeChannel } from './Channel';
|
||||
import { YouTubeThumbnail } from './Thumbnail';
|
||||
|
||||
interface VideoOptions {
|
||||
id?: string;
|
||||
url?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
durationRaw: string;
|
||||
durationInSec: number;
|
||||
uploadedAt?: string;
|
||||
views: number;
|
||||
thumbnail?: {
|
||||
/**
|
||||
* YouTube Video ID
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* YouTube video url
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* YouTube Video title
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* YouTube Video description.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* YouTube Video Duration Formatted
|
||||
*/
|
||||
durationRaw: string;
|
||||
/**
|
||||
* YouTube Video Duration in seconds
|
||||
*/
|
||||
durationInSec: number;
|
||||
/**
|
||||
* YouTube Video Uploaded Date
|
||||
*/
|
||||
uploadedAt?: string;
|
||||
/**
|
||||
* YouTube Views
|
||||
*/
|
||||
views: number;
|
||||
/**
|
||||
* YouTube Thumbnail Data
|
||||
*/
|
||||
thumbnail?: {
|
||||
id: string | undefined;
|
||||
width: number | undefined;
|
||||
height: number | undefined;
|
||||
url: string | undefined;
|
||||
};
|
||||
channel?: any;
|
||||
type: string;
|
||||
ratings: {
|
||||
likes: number;
|
||||
dislikes: number;
|
||||
};
|
||||
live: boolean;
|
||||
private: boolean;
|
||||
tags: string[];
|
||||
/**
|
||||
* YouTube Video's uploader Channel Data
|
||||
*/
|
||||
channel?: YouTubeChannel;
|
||||
/**
|
||||
* YouTube Video's likes
|
||||
*/
|
||||
likes: number;
|
||||
/**
|
||||
* YouTube Video's dislikes
|
||||
*/
|
||||
dislikes: number;
|
||||
/**
|
||||
* YouTube Video live status
|
||||
*/
|
||||
live: boolean;
|
||||
/**
|
||||
* YouTube Video private status
|
||||
*/
|
||||
private: boolean;
|
||||
/**
|
||||
* YouTube Video tags
|
||||
*/
|
||||
tags: string[];
|
||||
}
|
||||
/**
|
||||
* Class for YouTube Video url
|
||||
*/
|
||||
export class YouTubeVideo {
|
||||
/**
|
||||
* YouTube Video ID
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* YouTube video url
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* YouTube Class type. == "video"
|
||||
*/
|
||||
type: 'video' | 'playlist' | 'channel';
|
||||
/**
|
||||
* YouTube Video title
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* YouTube Video description.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* YouTube Video Duration Formatted
|
||||
*/
|
||||
durationRaw: string;
|
||||
/**
|
||||
* YouTube Video Duration in seconds
|
||||
*/
|
||||
durationInSec: number;
|
||||
/**
|
||||
* YouTube Video Uploaded Date
|
||||
*/
|
||||
uploadedAt?: string;
|
||||
/**
|
||||
* YouTube Views
|
||||
*/
|
||||
views: number;
|
||||
thumbnail?: {
|
||||
id: string | undefined;
|
||||
width: number | undefined;
|
||||
height: number | undefined;
|
||||
url: string | undefined;
|
||||
};
|
||||
/**
|
||||
* YouTube Thumbnail Data
|
||||
*/
|
||||
thumbnail?: YouTubeThumbnail;
|
||||
/**
|
||||
* YouTube Video's uploader Channel Data
|
||||
*/
|
||||
channel?: YouTubeChannel;
|
||||
/**
|
||||
* YouTube Video's likes
|
||||
*/
|
||||
likes: number;
|
||||
/**
|
||||
* YouTube Video's dislikes
|
||||
*/
|
||||
dislikes: number;
|
||||
/**
|
||||
* YouTube Video live status
|
||||
*/
|
||||
live: boolean;
|
||||
/**
|
||||
* YouTube Video private status
|
||||
*/
|
||||
private: boolean;
|
||||
/**
|
||||
* YouTube Video tags
|
||||
*/
|
||||
tags: string[];
|
||||
|
||||
/**
|
||||
* Constructor Class for YouTube Video
|
||||
* @param data JSON parsed data.
|
||||
*/
|
||||
constructor(data: any) {
|
||||
if (!data) throw new Error(`Can not initiate ${this.constructor.name} without data`);
|
||||
|
||||
@@ -71,12 +160,18 @@ export class YouTubeVideo {
|
||||
this.private = !!data.private;
|
||||
this.tags = data.tags || [];
|
||||
}
|
||||
|
||||
get toString(): string {
|
||||
/**
|
||||
* Converts class to title name of video.
|
||||
* @returns Title name
|
||||
*/
|
||||
toString(): string {
|
||||
return this.url || '';
|
||||
}
|
||||
|
||||
get toJSON(): VideoOptions {
|
||||
/**
|
||||
* Converts class to JSON data
|
||||
* @returns JSON data.
|
||||
*/
|
||||
toJSON(): VideoOptions {
|
||||
return {
|
||||
id: this.id,
|
||||
url: this.url,
|
||||
@@ -85,15 +180,12 @@ export class YouTubeVideo {
|
||||
durationInSec: this.durationInSec,
|
||||
durationRaw: this.durationRaw,
|
||||
uploadedAt: this.uploadedAt,
|
||||
thumbnail: this.thumbnail,
|
||||
thumbnail: this.thumbnail?.toJSON() || this.thumbnail,
|
||||
channel: this.channel,
|
||||
views: this.views,
|
||||
type: this.type,
|
||||
tags: this.tags,
|
||||
ratings: {
|
||||
likes: this.likes,
|
||||
dislikes: this.dislikes
|
||||
},
|
||||
likes: this.likes,
|
||||
dislikes: this.dislikes,
|
||||
live: this.live,
|
||||
private: this.private
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { video_info } from '.';
|
||||
import { LiveStream, Stream } from './classes/LiveStream';
|
||||
import { ProxyOptions as Proxy } from './../Request';
|
||||
import { InfoData } from './utils/constants';
|
||||
|
||||
export enum StreamType {
|
||||
Arbitrary = 'arbitrary',
|
||||
@@ -16,16 +17,6 @@ export interface StreamOptions {
|
||||
htmldata?: boolean;
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
LiveStreamData: {
|
||||
isLive: boolean;
|
||||
dashManifestUrl: string;
|
||||
hlsManifestUrl: string;
|
||||
};
|
||||
html5player: string;
|
||||
format: any[];
|
||||
video_details: any;
|
||||
}
|
||||
/**
|
||||
* Command to find audio formats from given format array
|
||||
* @param formats Formats to search from
|
||||
@@ -58,12 +49,12 @@ export async function stream(url: string, options: StreamOptions = {}): Promise<
|
||||
const final: any[] = [];
|
||||
if (
|
||||
info.LiveStreamData.isLive === true &&
|
||||
info.LiveStreamData.hlsManifestUrl !== null &&
|
||||
info.LiveStreamData.dashManifestUrl !== null &&
|
||||
info.video_details.durationInSec === 0
|
||||
) {
|
||||
return new LiveStream(
|
||||
info.LiveStreamData.dashManifestUrl,
|
||||
info.format[info.format.length - 1].targetDurationSec,
|
||||
info.format[info.format.length - 1].targetDurationSec as number,
|
||||
info.video_details.url
|
||||
);
|
||||
}
|
||||
@@ -95,12 +86,12 @@ export async function stream_from_info(info: InfoData, options: StreamOptions =
|
||||
const final: any[] = [];
|
||||
if (
|
||||
info.LiveStreamData.isLive === true &&
|
||||
info.LiveStreamData.hlsManifestUrl !== null &&
|
||||
info.LiveStreamData.dashManifestUrl !== null &&
|
||||
info.video_details.durationInSec === 0
|
||||
) {
|
||||
return new LiveStream(
|
||||
info.LiveStreamData.dashManifestUrl,
|
||||
info.format[info.format.length - 1].targetDurationSec,
|
||||
info.format[info.format.length - 1].targetDurationSec as number,
|
||||
info.video_details.url
|
||||
);
|
||||
}
|
||||
|
||||
39
play-dl/YouTube/utils/constants.ts
Normal file
39
play-dl/YouTube/utils/constants.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { YouTubeVideo } from "../classes/Video";
|
||||
|
||||
export interface LiveStreamData {
|
||||
isLive: boolean;
|
||||
dashManifestUrl: string | null
|
||||
hlsManifestUrl: string | null
|
||||
}
|
||||
|
||||
export interface formatData {
|
||||
itag: number;
|
||||
mimeType: string
|
||||
bitrate: number
|
||||
width: number
|
||||
height: number
|
||||
lastModified: string
|
||||
contentLength: string
|
||||
quality: string
|
||||
fps: number
|
||||
qualityLabel: string
|
||||
projectionType: string
|
||||
averageBitrate: number
|
||||
audioQuality: string
|
||||
approxDurationMs: string
|
||||
audioSampleRate: string
|
||||
audioChannels: number
|
||||
url : string
|
||||
signatureCipher : string;
|
||||
cipher : string;
|
||||
loudnessDb : number;
|
||||
targetDurationSec : number;
|
||||
}
|
||||
|
||||
export interface InfoData{
|
||||
LiveStreamData : LiveStreamData
|
||||
html5player : string
|
||||
format : Partial<formatData>[]
|
||||
video_details : YouTubeVideo
|
||||
related_videos: string[]
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { ProxyOptions as Proxy, request } from './../../Request/index';
|
||||
import { format_decipher } from './cipher';
|
||||
import { YouTubeVideo } from '../classes/Video';
|
||||
import { YouTubePlayList } from '../classes/Playlist';
|
||||
import { InfoData } from '../stream';
|
||||
import { InfoData } from './constants';
|
||||
|
||||
interface InfoOptions {
|
||||
proxy?: Proxy[];
|
||||
@@ -79,7 +79,7 @@ export function extractID(url: string): string {
|
||||
* @param options cookie and proxy parameters to add
|
||||
* @returns Data containing video_details, LiveStreamData and formats of video url.
|
||||
*/
|
||||
export async function video_basic_info(url: string, options: InfoOptions = {}) {
|
||||
export async function video_basic_info(url: string, options: InfoOptions = {}) : Promise<InfoData> {
|
||||
let body: string;
|
||||
if (options.htmldata) {
|
||||
body = url;
|
||||
@@ -187,7 +187,7 @@ function parseSeconds(seconds: number): string {
|
||||
* @param options cookie and proxy parameters to add
|
||||
* @returns Data containing video_details, LiveStreamData and formats of video url.
|
||||
*/
|
||||
export async function video_info(url: string, options: InfoOptions = {}) {
|
||||
export async function video_info(url: string, options: InfoOptions = {}): Promise<InfoData> {
|
||||
const data = await video_basic_info(url, options);
|
||||
if (data.LiveStreamData.isLive === true && data.LiveStreamData.hlsManifestUrl !== null) {
|
||||
return data;
|
||||
|
||||
@@ -11,7 +11,7 @@ export {
|
||||
} from './YouTube';
|
||||
export { spotify, sp_validate, refreshToken, is_expired, Spotify } from './Spotify';
|
||||
export { soundcloud, so_validate, SoundCloud, SoundCloudStream, getFreeClientID } from './SoundCloud';
|
||||
export { deezer, dz_validate, dz_search, dz_advanced_track_search, Deezer } from './Deezer';
|
||||
export { deezer, dz_validate, dz_advanced_track_search, Deezer } from './Deezer';
|
||||
export { setToken } from './token';
|
||||
|
||||
enum AudioPlayerStatus {
|
||||
@@ -30,6 +30,7 @@ interface SearchOptions {
|
||||
soundcloud?: 'tracks' | 'playlists' | 'albums';
|
||||
deezer?: 'track' | 'playlist' | 'album';
|
||||
};
|
||||
fuzzy?: boolean;
|
||||
}
|
||||
|
||||
import readline from 'node:readline';
|
||||
@@ -46,11 +47,17 @@ import {
|
||||
} from '.';
|
||||
import { SpotifyAuthorize, sp_search } from './Spotify';
|
||||
import { check_id, so_search, stream as so_stream, stream_from_info as so_stream_info } from './SoundCloud';
|
||||
import { InfoData, stream as yt_stream, StreamOptions, stream_from_info as yt_stream_info } from './YouTube/stream';
|
||||
import { SoundCloudTrack } from './SoundCloud/classes';
|
||||
import { stream as yt_stream, StreamOptions, stream_from_info as yt_stream_info } from './YouTube/stream';
|
||||
import { SoundCloudPlaylist, SoundCloudTrack } from './SoundCloud/classes';
|
||||
import { yt_search } from './YouTube/search';
|
||||
import { EventEmitter } from 'stream';
|
||||
import { Deezer, dz_search, dz_validate } from './Deezer';
|
||||
import { InfoData } from './YouTube/utils/constants';
|
||||
import { YouTubeVideo } from './YouTube/classes/Video';
|
||||
import { YouTubePlayList } from './YouTube/classes/Playlist';
|
||||
import { YouTubeChannel } from './YouTube/classes/Channel';
|
||||
import { SpotifyAlbum, SpotifyPlaylist, SpotifyTrack } from './Spotify/classes';
|
||||
import { DeezerAlbum, DeezerPlaylist, DeezerTrack } from './Deezer/classes';
|
||||
/**
|
||||
* Main stream Command for streaming through various sources
|
||||
* @param url The video / track url to make stream of
|
||||
@@ -79,7 +86,21 @@ export async function stream(url: string, options: StreamOptions = {}): Promise<
|
||||
* @param query string to search.
|
||||
* @param options contains limit and source to choose.
|
||||
* @returns Array of YouTube or Spotify or SoundCloud or Deezer
|
||||
deezer?: 'track' | 'playlist' | 'album';
|
||||
*/
|
||||
|
||||
export async function search( query: string, options: { source : { deezer : "album" } } & SearchOptions) : Promise<DeezerAlbum[]>;
|
||||
export async function search( query: string, options: { source : { deezer : "playlist" } } & SearchOptions) : Promise<DeezerPlaylist[]>;
|
||||
export async function search( query: string, options: { source : { deezer : "track" } } & SearchOptions) : Promise<DeezerTrack[]>;
|
||||
export async function search( query: string, options: { source : { soundcloud : "albums" } } & SearchOptions) : Promise<SoundCloudPlaylist[]>;
|
||||
export async function search( query: string, options: { source : { soundcloud : "playlists" } } & SearchOptions) : Promise<SoundCloudPlaylist[]>;
|
||||
export async function search( query: string, options: { source : { soundcloud : "tracks" } } & SearchOptions) : Promise<SoundCloudTrack[]>;
|
||||
export async function search( query: string, options: { source : { spotify : "album" } } & SearchOptions) : Promise<SpotifyAlbum[]>;
|
||||
export async function search( query: string, options: { source : { spotify : "playlist" } } & SearchOptions) : Promise<SpotifyPlaylist[]>;
|
||||
export async function search( query: string, options: { source : { spotify : "track" } } & SearchOptions) : Promise<SpotifyTrack[]>;
|
||||
export async function search( query: string, options: { source : { youtube : "channel" } } & SearchOptions) : Promise<YouTubeChannel[]>;
|
||||
export async function search( query: string, options: { source : { youtube : "playlist" } } & SearchOptions) : Promise<YouTubePlayList[]>;
|
||||
export async function search( query: string, options: { source : { youtube : "video" } } & SearchOptions) : Promise<YouTubeVideo[]>;
|
||||
export async function search(
|
||||
query: string,
|
||||
options: SearchOptions = {}
|
||||
@@ -90,7 +111,7 @@ export async function search(
|
||||
else if (options.source.spotify) return await sp_search(query, options.source.spotify, options.limit);
|
||||
else if (options.source.soundcloud) return await so_search(query, options.source.soundcloud, options.limit);
|
||||
else if (options.source.deezer)
|
||||
return await dz_search(query, { limit: options.limit, type: options.source.deezer });
|
||||
return await dz_search(query, { limit: options.limit, type: options.source.deezer, fuzzy : options.fuzzy });
|
||||
else throw new Error('Not possible to reach Here LOL. Easter Egg of play-dl if someone get this.');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user