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 { Channel } from "./Channel";
|
||||
import { Video } from "./Video";
|
||||
import fs from 'fs'
|
||||
const BASE_API = "https://www.youtube.com/youtubei/v1/browse?key=";
|
||||
|
||||
export class PlayList{
|
||||
@ -16,7 +15,7 @@ export class PlayList{
|
||||
link?: string;
|
||||
channel?: Channel;
|
||||
thumbnail?: Thumbnail;
|
||||
videos?: [];
|
||||
private videos?: [];
|
||||
private fetched_videos : Map<string, Video[]>
|
||||
private _continuation: { api?: string; token?: string; clientVersion?: string } = {};
|
||||
private __count : number
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { url_get } from "./utils/request";
|
||||
import fs from 'fs'
|
||||
import { ParseSearchInterface, ParseSearchResult } from "./utils/parser";
|
||||
import { Video } from "./classes/Video";
|
||||
import { Channel } from "./classes/Channel";
|
||||
|
||||
@ -153,10 +153,10 @@ function download_url(format: formatOptions, sig : string){
|
||||
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 tokens = js_tokens(body)
|
||||
format.forEach((format) => {
|
||||
formats.forEach((format) => {
|
||||
let cipher = format.signatureCipher || format.cipher;
|
||||
if(cipher){
|
||||
Object.assign(format, querystring.parse(cipher))
|
||||
@ -167,7 +167,9 @@ export async function format_decipher(format: formatOptions[], html5player : str
|
||||
if(tokens && format.s){
|
||||
sig = deciper_signature(tokens, format.s)
|
||||
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 { RequestInit } from 'node-fetch'
|
||||
import { PlayList } from '../classes/Playlist'
|
||||
import fs from 'fs'
|
||||
|
||||
const DEFAULT_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
||||
const youtube_url = /https:\/\/www.youtube.com\//g
|
||||
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){
|
||||
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])
|
||||
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 format = []
|
||||
format.push(player_response.streamingData.formats[0])
|
||||
format.push(...player_response.streamingData.adaptiveFormats)
|
||||
let vid = player_response.videoDetails
|
||||
let microformat = player_response.microformat.playerMicroformatRenderer
|
||||
let video_details = new Video ({
|
||||
let video_details = {
|
||||
id : vid.videoId,
|
||||
url : 'https://www.youtube.com/watch?v=' + vid.videoId,
|
||||
title : vid.title,
|
||||
@ -48,10 +43,8 @@ export async function video_basic_info(url : string){
|
||||
averageRating : vid.averageRating,
|
||||
live : vid.isLiveContent,
|
||||
private : vid.isPrivate
|
||||
})
|
||||
}
|
||||
return {
|
||||
player_response,
|
||||
response,
|
||||
html5player,
|
||||
format,
|
||||
video_details
|
||||
@ -69,9 +62,7 @@ export async function video_info(url : string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function playlist_info(url : string , options? : PlaylistOptions) {
|
||||
if (!options) options = { limit: 100, requestOptions: {} };
|
||||
if(!options.limit) options.limit = 100
|
||||
export async function playlist_info(url : string) {
|
||||
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')
|
||||
|
||||
@ -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 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;
|
||||
if (!data.title.runs || !data.title.runs.length) return undefined;
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import { Video } from "../classes/Video";
|
||||
import { PlayList } from "../classes/Playlist";
|
||||
import { Channel } from "../classes/Channel";
|
||||
import { RequestInit } from "node-fetch";
|
||||
import fs from 'fs'
|
||||
|
||||
export interface ParseSearchInterface {
|
||||
type?: "video" | "playlist" | "channel" | "all";
|
||||
limit?: number;
|
||||
requestOptions?: RequestInit;
|
||||
}
|
||||
|
||||
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 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()
|
||||
console.log(`Time Taken : ${(time_end - time_start)/1000} seconds`)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user