GithubHelp home page GithubHelp logo

yt-mix-playlist's Introduction

yt-mix-playlist

Node module for fetching YouTube Mix playlists.

Install

npm install yt-mix-playlist --save

Usage

Import module:

// ESM
import ytmpl from 'yt-mix-playlist';

// CJS
const ytmpl = require('yt-mix-playlist');

Fetch Mix playlist for a video:

const videoId = 'XCcN-IoYIJA';
const mixPlaylist = await ytmpl(videoId);
console.log(mixPlaylist);

Result:

MixPlaylist {
  id: 'RDXCcN-IoYIJA',
  title: 'Mix - Wiljan & Xandra - Woodlands',
  author: 'YouTube',
  url: 'http://www.youtube.com/watch?v=XCcN-IoYIJA&list=RDXCcN-IoYIJA',
  videoCount: '50+ videos',
  thumbnails: [
    Thumbnail {
      url: 'https://i.ytimg.com/vi/XCcN-IoYIJA/hqdefault.jpg?sqp=-oaymwEXCNACELwBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLARuI_29dvrA_u7pQj4xs8X_HUwDw',
      width: 336,
      height: 188
    },
    Thumbnail {
      url: 'https://i.ytimg.com/vi/XCcN-IoYIJA/hqdefault.jpg?sqp=-oaymwEWCKgBEF5IWvKriqkDCQgBFQAAiEIYAQ==&rs=AOn4CLCnA4XJbGLUcY1BPiU3TjMhKj1VXA',
      width: 168,
      height: 94
    }
  ],
  currentIndex: 0,
  items: [
    MixPlaylistItem {
      id: 'XCcN-IoYIJA',
      title: 'Wiljan & Xandra - Woodlands',
      author: [Author],
      url: 'https://www.youtube.com/watch?v=XCcN-IoYIJA&list=RDXCcN-IoYIJA&index=1',
      selected: true,
      duration: '5:30',
      thumbnails: [Array]
    },
    MixPlaylistItem {
      id: '_jYoI4rR_fg',
      title: 'Waking Dreams - Someone Else',
      author: [Author],
      url: 'https://www.youtube.com/watch?v=_jYoI4rR_fg&list=RDXCcN-IoYIJA&index=2',
      selected: false,
      duration: '4:49',
      thumbnails: [Array]
    },
    ...
  ]
}

items array contains videos currently in the playlist. currentIndex refers to the position of the selected video in the array.

On YouTube, when you select a video in a Mix playlist, the contents of the list may refresh depending on the position of the selected video. With this module, you can programatically 'select' a video and obtain an updated playlist with possibly changed contents.

To change selected video:

// Select by video Id or index from current list
const updatedPlaylist = await mixPlaylist.select(videoIdOrIndex);

or:

// Select the last video in current list
const updatedPlaylist = await mixPlaylist.selectLast();

or:

// Select the first video in current list
const updatedPlaylist = await mixPlaylist.selectFirst();

Each of the 'select' methods returns a new playlist. The original playlist remains unchanged.

Example:

// Select last video in the list
const updatedPlaylist = await mixPlaylist.selectLast();
console.log(updatedPlaylist);

Result:

MixPlaylist {
  id: 'RDXCcN-IoYIJA',
  title: 'Mix - Wiljan & Xandra - Woodlands',
  author: 'YouTube',
  url: 'http://www.youtube.com/watch?v=XXYlFuWEuKI&list=RDXCcN-IoYIJA',
  videoCount: '50+ videos',
  thumbnails: [
    Thumbnail {
      url: 'https://i.ytimg.com/vi/XCcN-IoYIJA/hqdefault.jpg?sqp=-oaymwEXCNACELwBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLARuI_29dvrA_u7pQj4xs8X_HUwDw',
      width: 336,
      height: 188
    },
    Thumbnail {
      url: 'https://i.ytimg.com/vi/XCcN-IoYIJA/hqdefault.jpg?sqp=-oaymwEWCKgBEF5IWvKriqkDCQgBFQAAiEIYAQ==&rs=AOn4CLCnA4XJbGLUcY1BPiU3TjMhKj1VXA',
      width: 168,
      height: 94
    }
  ],
  currentIndex: 24,
  items: [
    MixPlaylistItem {
      id: 'XCcN-IoYIJA',
      title: 'Wiljan & Xandra - Woodlands',
      author: [Author],
      url: 'https://www.youtube.com/watch?v=XCcN-IoYIJA&list=RDXCcN-IoYIJA&index=1',
      selected: false,
      duration: '5:30',
      thumbnails: [Array]
    },
    ...
    MixPlaylistItem {
      id: 'XXYlFuWEuKI',
      title: 'The Weeknd - Save Your Tears (Official Music Video)',
      author: [Author],
      url: 'https://www.youtube.com/watch?v=XXYlFuWEuKI&list=RDXCcN-IoYIJA&index=25',
      selected: true,
      duration: '4:09',
      thumbnails: [Array]
    },
    MixPlaylistItem {
      id: 'pxirHB4Hyzk',
      title: 'Maya Bay',
      author: [Author],
      url: 'https://www.youtube.com/watch?v=pxirHB4Hyzk&list=RDXCcN-IoYIJA&index=26',
      selected: false,
      duration: '3:13',
      thumbnails: [Array]
    },
    ...
  ]
}

Most times, we would be interested in obtaining new items from the playlist. We can do so as follows:

const updatedPlaylist = await mixPlaylist.selectLast();

// selectLast() will definitely return a list with new items.
// There will be some items carried over from the original list.
// To get the new items not in the original list, do this:

const newItems = updatedPlaylist.getItemsAfterSelected();

API

ytmpl(videoId: string, options?: { gl?: string, hl?: string }): Promise<MixPlaylist | null>

Options:

  • hl: language
  • gl: region

Example:

const mixPlaylist = await ytmpl('XCcN-IoYIJA', { hl: 'en', gl: 'US' });

Returns a Promise that resolves to a MixPlaylist instance representing the Mix playlist for the video, or null if none found.

MixPlaylist methods

select(index: number): Promise<MixPlaylist | null>
select(videoId: string): Promise<MixPlaylist | null>

Selects video in the playlist by its index or videoId. Returns a Promise that resolves to a new MixPlaylist instance representing the updated playlist after selection. Original playlist is not changed.

selectFirst(): Promise<MixPlaylist | null>

Convenience method that passes the first item in the playlist to select() and returns the result.

selectLast(): Promise<MixPlaylist | null>

Convenience method that passes the last item in the playlist to select() and returns the result.

getSelected(): MixPlaylistItem

Returns a MixPlaylistItem object representing the selected item in the playlist. Same as calling playlist.items[playlist.currentIndex].

getItemsBeforeSelected(): Array<MixPlaylistItem>

Returns playlist items as an array of MixPlaylistItem objects up to but not including the selected one.

getItemsAfterSelected(): Array<MixPlaylistItem>

Returns playlist items as an array of MixPlaylistItem objects after the selected one.

Properties

Property Remark
id Id of the Mix playlist
title
author 'YouTube'
url Share URL
items Array<MixPlaylistItem>: videos in the playlist
currentIndex Index of the selected item
videoCount '50+ ...'
thumbnails Array<Thumbnail>: {url, width, height}

Each item in the items array is a MixPlaylistItem object with the following properties:

Property Remark
id Video Id
title
url
author Author: { name, channelId, url }
selected Whether item is selected in the playlist
duration
thumbnails Array<Thumbnail>: {url, width, height}

Changelog

1.0.1:

  • Fix fetching of continuation data
  • Fix silly bug with reading undefined data

1.0.0:

  • Rewrite with Typescript and as ESM + CJS hybrid module
  • Replace request dependency with node-fetch + fetch-cookie, as 'request' is deprecated and contains critical vulnerability.
  • Changed license to MIT (not that it really affects anything...)

0.1.2-b.2:

  • Fix regression bug

0.1.2-b:

  • More robust fetching of mix playlists (using continuation tokens if necessary)
  • Use semantic versioning from now on

0.1.1b:

  • Fix dependencies

0.1.0b:

  • Initial release

License

MIT

yt-mix-playlist's People

Contributors

patrickkfkan avatar

Stargazers

うさみょん/myon2019 avatar  avatar

Watchers

 avatar

Forkers

lovehifi tyfangxv

yt-mix-playlist's Issues

Doesn't work on Heroku

Hi,

when I use it in my code and host the bot on my pc everything works fine and as intended, but when I push it to Heroku await ytmpl(videoId); suddenly returns null for some reason. Any idea why and how I can fix it?

Both my pc and heroku is running Node v16.15.0 and npm 8.5.5

Thanks in advance

Not working anymore

Hi, using the exemple.js i get :

Obtaining Mix playlist for video XCcN-IoYIJA...

Failed to obtain playlist

Do you know why it doesn't work ?
Have a nice day.

Returns null on collapsed playlist

E.g.

https://www.youtube.com/watch?v=O4irXQhgMqg&list=RDO4irXQhgMqg&start_radio=1

I solved it by changing the getCollapsedPlaylistInfo method to this:

function getCollapsedPlaylistInfo(json) {
     let results;
     let playlistId;
 
     try {
         results = json.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results;
         const playlistResult = results.filter(
             result => result["compactPlaylistRenderer"]
         );
 
         playlistId = playlistResult[0].compactPlaylistRenderer.playlistId;
     } catch (e) {
         return null;
     }
     
     if (Array.isArray(results)) {
         for(let i = 0; i < results.length; i++) {
             let result = results[i];
             let info = result.compactVideoRenderer;
             if (info) {
                 return {
                     id: playlistId,
                     title: parseText(info.title),
                     author: parseText(info.longBylineText),
                     url: URL.resolve(BASE_URL, info.navigationEndpoint.commandMetadata.webCommandMetadata.url),
                     thumbnails: prepImg(info.thumbnail.thumbnails)
                 };
             }
         }
     }
     return null;
 }

I removed videoCount because it seems to be not available and I don't need it.

Having error when inputting the videoID into ytmpl

I tried executing the example script and I got this error

node example.js

Obtaining Mix playlist for video XCcN-IoYIJA...

/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/lib/parser.js:72
    return txt.simpleText || txt.runs.map(a => a.text).join('');
               ^

TypeError: Cannot read properties of undefined (reading 'simpleText')
    at parseText (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/lib/parser.js:72:16)
    at Object.getCollapsedPlaylistInfo (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/lib/parser.js:95:29)
    at getCollapsedList (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/lib/index.js:51:32)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async getMixPlaylist (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/lib/index.js:37:25)
    at async getMixPlaylist (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/example/example.js:5:12)
    at async main (/home/ubuntu/DiscordBot_v1/node_modules/yt-mix-playlist/example/example.js:41:14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.