YouTube examples
This commit is contained in:
parent
04770cc929
commit
06cc44d485
76
node-youtube-dl/YouTube/README.md
Normal file
76
node-youtube-dl/YouTube/README.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# YouTube Downloader/Search
|
||||||
|
### Downloades youtube videos, playlist and also searches song
|
||||||
|
|
||||||
|
This is a light-weight youtube downloader and searcher.
|
||||||
|
|
||||||
|
- searches by video, playlist, channel
|
||||||
|
- obtains audio playback url.
|
||||||
|
|
||||||
|
## Video commands usage :-
|
||||||
|
### 1. video_basic_info(url : `string`)
|
||||||
|
*This is what downloader gets first.*
|
||||||
|
```js
|
||||||
|
let video = await video_basic_info(url)
|
||||||
|
```
|
||||||
|
### 2. video_info(url : `string`)
|
||||||
|
*This contains everything with deciphered formats along with video_details.*
|
||||||
|
```js
|
||||||
|
let video = await video_info(url)
|
||||||
|
```
|
||||||
|
### 3. formats
|
||||||
|
*This shows all formats availiable of a video*
|
||||||
|
```js
|
||||||
|
let video = await video_info(url)
|
||||||
|
console.log(video.format)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Playlist commands usage :-
|
||||||
|
### 1. playlist_info(url : `string`)
|
||||||
|
*This containes every thing about a playlist*
|
||||||
|
```js
|
||||||
|
let playlist = await playlist_info(url) //This only fetches first 100 songs from a playlist
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. playlist.fetch()
|
||||||
|
*This fetches whole playlist.*
|
||||||
|
```js
|
||||||
|
let playlist = await playlist_info(url) //This only fetches first 100 songs from a playlist
|
||||||
|
await playlist.fetch() // This one fetches all songs from a playlist.
|
||||||
|
```
|
||||||
|
#### 3. playlist.page(page_number : `number`)
|
||||||
|
*This gives you no. of videos from a page*
|
||||||
|
> Pages : every 100 songs have been divided into pages.
|
||||||
|
> So for example: There is 782 songs in a playlist, so there will be 8 pages.
|
||||||
|
|
||||||
|
```js
|
||||||
|
let playlist = await playlist_info(url) //This only fetches first 100 songs from a playlist
|
||||||
|
await playlist.fetch() // This one fetches all songs from a playlist.
|
||||||
|
console.log(playlist.page(1)) // This displays first 100 songs of a playlist
|
||||||
|
```
|
||||||
|
#### 4. playlist.total_videos
|
||||||
|
*This tells you total no of videos that have been fetched so far.*
|
||||||
|
```js
|
||||||
|
let playlist = await playlist_info(url) //This only fetches first 100 songs from a playlist
|
||||||
|
await playlist.fetch() // This one fetches all songs from a playlist.
|
||||||
|
console.log(playlist.total_videos) // This displays total no. of videos fetched so far.
|
||||||
|
```
|
||||||
|
#### 5. playlist.videoCount
|
||||||
|
*This tells total no. of songs in a playlist.*
|
||||||
|
```js
|
||||||
|
let playlist = await playlist_info(url) //This only fetches first 100 songs from a playlist
|
||||||
|
await playlist.fetch() // This one fetches all songs from a playlist.
|
||||||
|
console.log(playlist.videoCount) // This displays total no. of videos in a playlist
|
||||||
|
```
|
||||||
|
|
||||||
|
## Search Command Usage :-
|
||||||
|
### 1. search(url : `string`, options? : `SearchOptions`)
|
||||||
|
*This enables all searching mechanism (video, channel, playlist)*
|
||||||
|
```js
|
||||||
|
let result = await search('Rick Roll')
|
||||||
|
console.log(result[0].url)
|
||||||
|
```
|
||||||
|
### SearchOptions
|
||||||
|
```
|
||||||
|
type?: "video" | "playlist" | "channel" | "all";
|
||||||
|
limit?: number;
|
||||||
|
```
|
||||||
@ -3,7 +3,6 @@ import { url_get } from "../utils/request";
|
|||||||
import { Thumbnail } from "./Thumbnail";
|
import { Thumbnail } from "./Thumbnail";
|
||||||
import { Channel } from "./Channel";
|
import { Channel } from "./Channel";
|
||||||
import { Video } from "./Video";
|
import { Video } from "./Video";
|
||||||
import fs from 'fs'
|
|
||||||
const BASE_API = "https://www.youtube.com/youtubei/v1/browse?key=";
|
const BASE_API = "https://www.youtube.com/youtubei/v1/browse?key=";
|
||||||
|
|
||||||
export class PlayList{
|
export class PlayList{
|
||||||
@ -16,7 +15,7 @@ export class PlayList{
|
|||||||
link?: string;
|
link?: string;
|
||||||
channel?: Channel;
|
channel?: Channel;
|
||||||
thumbnail?: Thumbnail;
|
thumbnail?: Thumbnail;
|
||||||
videos?: [];
|
private videos?: [];
|
||||||
private fetched_videos : Map<string, Video[]>
|
private fetched_videos : Map<string, Video[]>
|
||||||
private _continuation: { api?: string; token?: string; clientVersion?: string } = {};
|
private _continuation: { api?: string; token?: string; clientVersion?: string } = {};
|
||||||
private __count : number
|
private __count : number
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { url_get } from "./utils/request";
|
import { url_get } from "./utils/request";
|
||||||
import fs from 'fs'
|
|
||||||
import { ParseSearchInterface, ParseSearchResult } from "./utils/parser";
|
import { ParseSearchInterface, ParseSearchResult } from "./utils/parser";
|
||||||
import { Video } from "./classes/Video";
|
import { Video } from "./classes/Video";
|
||||||
import { Channel } from "./classes/Channel";
|
import { Channel } from "./classes/Channel";
|
||||||
|
|||||||
@ -153,10 +153,10 @@ function download_url(format: formatOptions, sig : string){
|
|||||||
format.url = parsed_url.toString();
|
format.url = parsed_url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function format_decipher(format: formatOptions[], html5player : string){
|
export async function format_decipher(formats: formatOptions[], html5player : string){
|
||||||
let body = await url_get(html5player)
|
let body = await url_get(html5player)
|
||||||
let tokens = js_tokens(body)
|
let tokens = js_tokens(body)
|
||||||
format.forEach((format) => {
|
formats.forEach((format) => {
|
||||||
let cipher = format.signatureCipher || format.cipher;
|
let cipher = format.signatureCipher || format.cipher;
|
||||||
if(cipher){
|
if(cipher){
|
||||||
Object.assign(format, querystring.parse(cipher))
|
Object.assign(format, querystring.parse(cipher))
|
||||||
@ -167,7 +167,9 @@ export async function format_decipher(format: formatOptions[], html5player : str
|
|||||||
if(tokens && format.s){
|
if(tokens && format.s){
|
||||||
sig = deciper_signature(tokens, format.s)
|
sig = deciper_signature(tokens, format.s)
|
||||||
download_url(format, sig)
|
download_url(format, sig)
|
||||||
|
delete format.s
|
||||||
|
delete format.sp
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return format
|
return formats
|
||||||
}
|
}
|
||||||
@ -3,30 +3,25 @@ import { format_decipher, js_tokens } from './cipher'
|
|||||||
import { Video } from '../classes/Video'
|
import { Video } from '../classes/Video'
|
||||||
import { RequestInit } from 'node-fetch'
|
import { RequestInit } from 'node-fetch'
|
||||||
import { PlayList } from '../classes/Playlist'
|
import { PlayList } from '../classes/Playlist'
|
||||||
import fs from 'fs'
|
|
||||||
|
|
||||||
const DEFAULT_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
const DEFAULT_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
||||||
const youtube_url = /https:\/\/www.youtube.com\//g
|
const youtube_url = /https:\/\/www.youtube.com\//g
|
||||||
const video_pattern = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/;
|
const video_pattern = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/;
|
||||||
|
|
||||||
export interface PlaylistOptions {
|
|
||||||
limit?: number;
|
|
||||||
requestOptions?: RequestInit;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function video_basic_info(url : string){
|
export async function video_basic_info(url : string){
|
||||||
if(!url.match(youtube_url) || !url.match(video_pattern)) throw new Error('This is not a YouTube URL')
|
if(!url.match(youtube_url) || !url.match(video_pattern)) throw new Error('This is not a YouTube URL')
|
||||||
let body = await url_get(url)
|
let video_id = url.split('watch?v=')[1].split('&')[0]
|
||||||
|
let new_url = 'https://www.youtube.com/watch?v=' + video_id
|
||||||
|
let body = await url_get(new_url)
|
||||||
let player_response = JSON.parse(body.split("var ytInitialPlayerResponse = ")[1].split(";</script>")[0])
|
let player_response = JSON.parse(body.split("var ytInitialPlayerResponse = ")[1].split(";</script>")[0])
|
||||||
if(player_response.playabilityStatus.status === 'ERROR') throw new Error(`While getting info from url \n ${player_response.playabilityStatus.reason}`)
|
if(player_response.playabilityStatus.status === 'ERROR') throw new Error(`While getting info from url \n ${player_response.playabilityStatus.reason}`)
|
||||||
let response = JSON.parse(body.split("var ytInitialData = ")[1].split(";</script>")[0])
|
|
||||||
let html5player = 'https://www.youtube.com' + body.split('"jsUrl":"')[1].split('"')[0]
|
let html5player = 'https://www.youtube.com' + body.split('"jsUrl":"')[1].split('"')[0]
|
||||||
let format = []
|
let format = []
|
||||||
format.push(player_response.streamingData.formats[0])
|
format.push(player_response.streamingData.formats[0])
|
||||||
format.push(...player_response.streamingData.adaptiveFormats)
|
format.push(...player_response.streamingData.adaptiveFormats)
|
||||||
let vid = player_response.videoDetails
|
let vid = player_response.videoDetails
|
||||||
let microformat = player_response.microformat.playerMicroformatRenderer
|
let microformat = player_response.microformat.playerMicroformatRenderer
|
||||||
let video_details = new Video ({
|
let video_details = {
|
||||||
id : vid.videoId,
|
id : vid.videoId,
|
||||||
url : 'https://www.youtube.com/watch?v=' + vid.videoId,
|
url : 'https://www.youtube.com/watch?v=' + vid.videoId,
|
||||||
title : vid.title,
|
title : vid.title,
|
||||||
@ -48,10 +43,8 @@ export async function video_basic_info(url : string){
|
|||||||
averageRating : vid.averageRating,
|
averageRating : vid.averageRating,
|
||||||
live : vid.isLiveContent,
|
live : vid.isLiveContent,
|
||||||
private : vid.isPrivate
|
private : vid.isPrivate
|
||||||
})
|
}
|
||||||
return {
|
return {
|
||||||
player_response,
|
|
||||||
response,
|
|
||||||
html5player,
|
html5player,
|
||||||
format,
|
format,
|
||||||
video_details
|
video_details
|
||||||
@ -69,9 +62,7 @@ export async function video_info(url : string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function playlist_info(url : string , options? : PlaylistOptions) {
|
export async function playlist_info(url : string) {
|
||||||
if (!options) options = { limit: 100, requestOptions: {} };
|
|
||||||
if(!options.limit) options.limit = 100
|
|
||||||
if (!url || typeof url !== "string") throw new Error(`Expected playlist url, received ${typeof url}!`);
|
if (!url || typeof url !== "string") throw new Error(`Expected playlist url, received ${typeof url}!`);
|
||||||
if(url.search('(\\?|\\&)list\\=') === -1) throw new Error('This is not a PlayList URL')
|
if(url.search('(\\?|\\&)list\\=') === -1) throw new Error('This is not a PlayList URL')
|
||||||
|
|
||||||
@ -87,7 +78,7 @@ export async function playlist_info(url : string , options? : PlaylistOptions) {
|
|||||||
let playlistDetails = JSON.parse(body.split('{"playlistSidebarRenderer":')[1].split("}};</script>")[0]).items;
|
let playlistDetails = JSON.parse(body.split('{"playlistSidebarRenderer":')[1].split("}};</script>")[0]).items;
|
||||||
|
|
||||||
let API_KEY = body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? DEFAULT_API_KEY;
|
let API_KEY = body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? DEFAULT_API_KEY;
|
||||||
let videos = getPlaylistVideos(parsed, options.limit);
|
let videos = getPlaylistVideos(parsed, 100);
|
||||||
|
|
||||||
let data = playlistDetails[0].playlistSidebarPrimaryInfoRenderer;
|
let data = playlistDetails[0].playlistSidebarPrimaryInfoRenderer;
|
||||||
if (!data.title.runs || !data.title.runs.length) return undefined;
|
if (!data.title.runs || !data.title.runs.length) return undefined;
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
import { Video } from "../classes/Video";
|
import { Video } from "../classes/Video";
|
||||||
import { PlayList } from "../classes/Playlist";
|
import { PlayList } from "../classes/Playlist";
|
||||||
import { Channel } from "../classes/Channel";
|
import { Channel } from "../classes/Channel";
|
||||||
import { RequestInit } from "node-fetch";
|
|
||||||
import fs from 'fs'
|
|
||||||
|
|
||||||
export interface ParseSearchInterface {
|
export interface ParseSearchInterface {
|
||||||
type?: "video" | "playlist" | "channel" | "all";
|
type?: "video" | "playlist" | "channel" | "all";
|
||||||
limit?: number;
|
limit?: number;
|
||||||
requestOptions?: RequestInit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ParseSearchResult(html :string, options? : ParseSearchInterface): (Video | PlayList | Channel)[] {
|
export function ParseSearchResult(html :string, options? : ParseSearchInterface): (Video | PlayList | Channel)[] {
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { playlist_info } from "./YouTube";
|
//This File is in testing stage, everything will change in this
|
||||||
|
import { playlist_info, video_basic_info, video_info, search } from "./YouTube";
|
||||||
|
|
||||||
let main = async() => {
|
let main = async() => {
|
||||||
let time_start = Date.now()
|
let time_start = Date.now()
|
||||||
let playlist = await playlist_info('https://www.youtube.com/watch?v=bM7SZ5SBzyY&list=PLzkuLC6Yvumv_Rd5apfPRWEcjf9b1JRnq')
|
let result = await search('Rick Roll')
|
||||||
|
console.log(result[0].url)
|
||||||
let time_end = Date.now()
|
let time_end = Date.now()
|
||||||
console.log(`Time Taken : ${(time_end - time_start)/1000} seconds`)
|
console.log(`Time Taken : ${(time_end - time_start)/1000} seconds`)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user