mirror of https://github.com/FreeTubeApp/FreeTube
Upgrade YouTube.js from 4.3 to 5.0.2 (fixes throttling) (#3474)
* Upgrade YouTube.js from 4.3 to 5.0.1 (fixes throttling) * Fix typo * Upgrade YouTube.js from 5.0.1 to 5.0.2 (fixes watch page views)
This commit is contained in:
parent
d3dcaaac53
commit
170df2a054
|
@ -75,7 +75,7 @@
|
|||
"vue-router": "^3.6.5",
|
||||
"vue-tiny-slider": "^0.1.39",
|
||||
"vuex": "^3.6.2",
|
||||
"youtubei.js": "^4.3.0"
|
||||
"youtubei.js": "^5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.5",
|
||||
|
|
|
@ -170,7 +170,7 @@ export default defineComponent({
|
|||
|
||||
getCommentDataLocal: async function (more) {
|
||||
try {
|
||||
/** @type {import('youtubei.js/dist/src/parser/youtube/Comments').default} */
|
||||
/** @type {import('youtubei.js').YT.Comments} */
|
||||
let comments
|
||||
if (more) {
|
||||
comments = await this.nextPageToken.getContinuation()
|
||||
|
@ -210,7 +210,7 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
const comment = this.commentData[index]
|
||||
/** @type {import('youtubei.js/dist/src/parser/classes/comments/CommentThread').default} */
|
||||
/** @type {import('youtubei.js').YTNodes.CommentThread} */
|
||||
const commentThread = comment.replyToken
|
||||
|
||||
if (comment.replies.length > 0) {
|
||||
|
|
|
@ -200,12 +200,12 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/livechat/items/LiveChatTextMessage').default} comment
|
||||
* @param {import('youtubei.js').YTNodes.LiveChatTextMessage} comment
|
||||
*/
|
||||
parseLiveChatComment: function (comment) {
|
||||
/**
|
||||
* can also be undefined if there is no badge
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/LiveChatAuthorBadge').default}
|
||||
* @type {import('youtubei.js').YTNodes.LiveChatAuthorBadge}
|
||||
*/
|
||||
const badge = comment.author.badges.find(badge => badge.type === 'LiveChatAuthorBadge' && badge.custom_thumbnail)
|
||||
|
||||
|
@ -231,7 +231,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/livechat/items/LiveChatPaidMessage').default} superChat
|
||||
* @param {import('youtubei.js').YTNodes.LiveChatPaidMessage} superChat
|
||||
*/
|
||||
parseLiveChatSuperChat: function (superChat) {
|
||||
const parsedComment = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Innertube, ClientType, Misc, Utils, YT } from 'youtubei.js'
|
||||
import { ClientType, Endpoints, Innertube, Misc, Utils, YT } from 'youtubei.js'
|
||||
import Autolinker from 'autolinker'
|
||||
import { join } from 'path'
|
||||
|
||||
|
@ -65,14 +65,10 @@ export async function getLocalPlaylist(id) {
|
|||
return await innertube.getPlaylist(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/core/TabbedFeed').default} TabbedFeed
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} location
|
||||
* @param {string} tab
|
||||
* @param {TabbedFeed|null} instance
|
||||
* @param {import('youtubei.js').Mixins.TabbedFeed|null} instance
|
||||
*/
|
||||
export async function getLocalTrending(location, tab, instance) {
|
||||
if (instance === null) {
|
||||
|
@ -107,11 +103,7 @@ export async function getLocalSearchResults(query, filters, safetyMode) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/youtube/Search').default} Search
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Search} continuationData
|
||||
* @param {YT.Search} continuationData
|
||||
*/
|
||||
export async function getLocalSearchContinuation(continuationData) {
|
||||
const response = await continuationData.getContinuation()
|
||||
|
@ -151,8 +143,8 @@ export async function getLocalComments(id, sortByNewest = false) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/misc/Format').default[]} formats
|
||||
* @param {import('youtubei.js/dist/index').Player} player
|
||||
* @param {Misc.Format[]} formats
|
||||
* @param {import('youtubei.js').Player} player
|
||||
*/
|
||||
function decipherFormats(formats, player) {
|
||||
for (const format of formats) {
|
||||
|
@ -206,12 +198,12 @@ export async function getLocalChannelVideos(id) {
|
|||
const innertube = await createInnertube()
|
||||
|
||||
try {
|
||||
const response = await innertube.actions.execute('/browse', {
|
||||
browseId: id,
|
||||
const response = await innertube.actions.execute(Endpoints.BrowseEndpoint.PATH, Endpoints.BrowseEndpoint.build({
|
||||
browse_id: id,
|
||||
params: 'EgZ2aWRlb3PyBgQKAjoA'
|
||||
// protobuf for the videos tab (this is the one that YouTube uses,
|
||||
// it has some empty fields in the protobuf but it doesn't work if you remove them)
|
||||
})
|
||||
}))
|
||||
|
||||
const videosTab = new YT.Channel(null, response)
|
||||
|
||||
|
@ -233,8 +225,8 @@ export async function getLocalChannelVideos(id) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/Video').default[]} videos
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/misc/Author').default} author
|
||||
* @param {import('youtubei.js').YTNodes.Video[]} videos
|
||||
* @param {Misc.Author} author
|
||||
*/
|
||||
export function parseLocalChannelVideos(videos, author) {
|
||||
const parsedVideos = videos.map(parseLocalListVideo)
|
||||
|
@ -249,13 +241,13 @@ export function parseLocalChannelVideos(videos, author) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/Playlist').default} Playlist
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/GridPlaylist').default} GridPlaylist
|
||||
* @typedef {import('youtubei.js').YTNodes.Playlist} Playlist
|
||||
* @typedef {import('youtubei.js').YTNodes.GridPlaylist} GridPlaylist
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Playlist|GridPlaylist} playlist
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/misc/Author').default} author
|
||||
* @param {Misc.Author} author
|
||||
*/
|
||||
export function parseLocalListPlaylist(playlist, author = undefined) {
|
||||
let channelName
|
||||
|
@ -290,7 +282,7 @@ export function parseLocalListPlaylist(playlist, author = undefined) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Search} response
|
||||
* @param {YT.Search} response
|
||||
*/
|
||||
function handleSearchResponse(response) {
|
||||
if (!response.results) {
|
||||
|
@ -313,11 +305,7 @@ function handleSearchResponse(response) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/PlaylistVideo').default} PlaylistVideo
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {PlaylistVideo} video
|
||||
* @param {import('youtubei.js').YTNodes.PlaylistVideo} video
|
||||
*/
|
||||
export function parseLocalPlaylistVideo(video) {
|
||||
return {
|
||||
|
@ -333,7 +321,7 @@ export function parseLocalPlaylistVideo(video) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/Video').default} video
|
||||
* @param {import('youtubei.js').YTNodes.Video} video
|
||||
*/
|
||||
export function parseLocalListVideo(video) {
|
||||
return {
|
||||
|
@ -344,7 +332,7 @@ export function parseLocalListVideo(video) {
|
|||
authorId: video.author.id,
|
||||
description: video.description,
|
||||
viewCount: extractNumberFromString(video.view_count.text),
|
||||
publishedText: video.published.text !== 'N/A' ? video.published.text : null,
|
||||
publishedText: video.published.isEmpty() ? null : video.published.text,
|
||||
lengthSeconds: isNaN(video.duration.seconds) ? '' : video.duration.seconds,
|
||||
liveNow: video.is_live,
|
||||
isUpcoming: video.is_upcoming || video.is_premiere,
|
||||
|
@ -353,14 +341,14 @@ export function parseLocalListVideo(video) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/helpers').YTNode} item
|
||||
* @param {import('youtubei.js').Helpers.YTNode} item
|
||||
*/
|
||||
function parseListItem(item) {
|
||||
switch (item.type) {
|
||||
case 'Video':
|
||||
return parseLocalListVideo(item)
|
||||
case 'Channel': {
|
||||
/** @type {import('youtubei.js/dist/src/parser/classes/Channel').default} */
|
||||
/** @type {import('youtubei.js').YTNodes.Channel} */
|
||||
const channel = item
|
||||
|
||||
// see upstream TODO: https://github.com/LuanRT/YouTube.js/blob/main/src/parser/classes/Channel.ts#L33
|
||||
|
@ -370,17 +358,17 @@ function parseListItem(item) {
|
|||
let subscribers = null
|
||||
let videos = null
|
||||
let handle = null
|
||||
if (channel.subscribers.text?.startsWith('@')) {
|
||||
handle = channel.subscribers.text
|
||||
if (channel.subscriber_count.text?.startsWith('@')) {
|
||||
handle = channel.subscriber_count.text
|
||||
|
||||
if (channel.videos.text !== 'N/A') {
|
||||
subscribers = channel.videos.text
|
||||
if (!channel.video_count.isEmpty()) {
|
||||
subscribers = channel.video_count.text
|
||||
}
|
||||
} else {
|
||||
videos = extractNumberFromString(channel.videos.text)
|
||||
videos = extractNumberFromString(channel.video_count.text)
|
||||
|
||||
if (channel.subscribers.text !== 'N/A') {
|
||||
subscribers = channel.subscribers.text
|
||||
if (!channel.subscriber_count.isEmpty()) {
|
||||
subscribers = channel.subscriber_count.text
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,11 +391,7 @@ function parseListItem(item) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/CompactVideo').default} CompactVideo
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CompactVideo} video
|
||||
* @param {import('youtubei.js').YTNodes.CompactVideo} video
|
||||
*/
|
||||
export function parseLocalWatchNextVideo(video) {
|
||||
return {
|
||||
|
@ -417,7 +401,7 @@ export function parseLocalWatchNextVideo(video) {
|
|||
author: video.author.name,
|
||||
authorId: video.author.id,
|
||||
viewCount: extractNumberFromString(video.view_count.text),
|
||||
publishedText: video.published.text === 'N/A' ? null : video.published.text,
|
||||
publishedText: video.published.isEmpty() ? null : video.published.text,
|
||||
lengthSeconds: isNaN(video.duration.seconds) ? '' : video.duration.seconds,
|
||||
liveNow: video.is_live,
|
||||
isUpcoming: video.is_premiere
|
||||
|
@ -452,12 +436,7 @@ function convertSearchFilters(filters) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/misc/TextRun').default} TextRun
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/misc/EmojiRun').default} EmojiRun
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {(TextRun|EmojiRun)[]} runs
|
||||
* @param {(Misc.TextRun|Misc.EmojiRun)[]} runs
|
||||
* @param {number} emojiSize
|
||||
* @param {{looseChannelNameDetection: boolean}} options
|
||||
*/
|
||||
|
@ -527,7 +506,7 @@ export function parseLocalTextRuns(runs, emojiSize = 16, options = { looseChanne
|
|||
break
|
||||
case 'WEB_PAGE_TYPE_UNKNOWN':
|
||||
default: {
|
||||
const url = new URL(endpoint.payload?.content?.confirmDialogRenderer?.confirmButton?.buttonRenderer?.command?.urlEndpoint?.url || endpoint.payload.url)
|
||||
const url = new URL((endpoint.dialog?.type === 'ConfirmDialog' && endpoint.dialog.confirm_button.endpoint.payload.url) || endpoint.payload.url)
|
||||
if (url.hostname === 'www.youtube.com' && url.pathname === '/redirect' && url.searchParams.has('q')) {
|
||||
// remove utm tracking parameters
|
||||
const realURL = new URL(url.searchParams.get('q'))
|
||||
|
@ -569,11 +548,7 @@ export function parseLocalTextRuns(runs, emojiSize = 16, options = { looseChanne
|
|||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/misc/Format').default} Format
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Format} format
|
||||
* @param {Misc.Format} format
|
||||
*/
|
||||
export function mapLocalFormat(format) {
|
||||
return {
|
||||
|
@ -589,8 +564,8 @@ export function mapLocalFormat(format) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/comments/Comment').default} comment
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/comments/CommentThread').default} commentThread
|
||||
* @param {import('youtubei.js').YTNodes.Comment} comment
|
||||
* @param {import('youtubei.js').YTNodes.CommentThread} commentThread
|
||||
*/
|
||||
export function parseLocalComment(comment, commentThread = undefined) {
|
||||
let hasOwnerReplied = false
|
||||
|
@ -625,7 +600,7 @@ export function parseLocalComment(comment, commentThread = undefined) {
|
|||
/**
|
||||
* video.js only supports MP4 DASH not WebM DASH
|
||||
* so we filter out the WebM DASH formats
|
||||
* @param {Format[]} formats
|
||||
* @param {Misc.Format[]} formats
|
||||
* @param {boolean} allowAv1 Use the AV1 formats if they are available
|
||||
*/
|
||||
export function filterLocalFormats(formats, allowAv1 = false) {
|
||||
|
@ -683,7 +658,7 @@ export function parseLocalSubscriberCount(text) {
|
|||
|
||||
/**
|
||||
* Parse community posts
|
||||
* @param {import('youtubei.js/dist/src/parser/classes/BackstagePost').default} post
|
||||
* @param {import('youtubei.js').YTNodes.BackstagePost} post
|
||||
*/
|
||||
export function parseLocalCommunityPost(post) {
|
||||
let replyCount = post.action_buttons?.reply_button?.text ?? null
|
||||
|
|
|
@ -412,7 +412,7 @@ export default defineComponent({
|
|||
this.setErrorMessage(channel.alert)
|
||||
return
|
||||
} else if (channel.memo.has('ChannelAgeGate')) {
|
||||
/** @type {import('youtubei.js/dist/src/parser/classes/ChannelAgeGate').default} */
|
||||
/** @type {import('youtubei.js').YTNodes.ChannelAgeGate} */
|
||||
const ageGate = channel.memo.get('ChannelAgeGate')[0]
|
||||
|
||||
channelName = ageGate.channel_title
|
||||
|
@ -444,7 +444,7 @@ export default defineComponent({
|
|||
// https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw
|
||||
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/C4TabbedHeader').default}
|
||||
* @type {import('youtubei.js').YTNodes.C4TabbedHeader}
|
||||
*/
|
||||
const header = channel.header
|
||||
|
||||
|
@ -460,12 +460,12 @@ export default defineComponent({
|
|||
// https://www.youtube.com/channel/UCOpNcN46UbXVtpKMrmU4Abg
|
||||
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/CarouselHeader').default}
|
||||
* @type {import('youtubei.js').YTNodes.CarouselHeader}
|
||||
*/
|
||||
const header = channel.header
|
||||
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/TopicChannelDetails').default}
|
||||
* @type {import('youtubei.js').YTNodes.TopicChannelDetails}
|
||||
*/
|
||||
const topicChannelDetails = header.contents.find(node => node.type === 'TopicChannelDetails')
|
||||
channelName = topicChannelDetails.title.text
|
||||
|
@ -484,7 +484,7 @@ export default defineComponent({
|
|||
// https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg
|
||||
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/InteractiveTabbedHeader').default}
|
||||
* @type {import('youtubei.js').YTNodes.InteractiveTabbedHeader}
|
||||
*/
|
||||
const header = channel.header
|
||||
channelName = header.title.text
|
||||
|
@ -597,19 +597,19 @@ export default defineComponent({
|
|||
getChannelAboutLocal: async function () {
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default}
|
||||
* @type {import('youtubei.js').YT.Channel}
|
||||
*/
|
||||
const channel = this.channelInstance
|
||||
const about = await channel.getAbout()
|
||||
|
||||
this.description = about.description.text !== 'N/A' ? autolinker.link(about.description.text) : ''
|
||||
this.description = about.description.isEmpty() ? '' : autolinker.link(about.description.text)
|
||||
|
||||
const views = extractNumberFromString(about.views.text)
|
||||
const views = extractNumberFromString(about.view_count.text)
|
||||
this.views = isNaN(views) ? null : views
|
||||
|
||||
this.joined = about.joined.text !== 'N/A' ? new Date(about.joined.text.replace('Joined').trim()) : 0
|
||||
this.joined = about.joined_date.isEmpty() ? 0 : new Date(about.joined_date.text.replace('Joined').trim())
|
||||
|
||||
this.location = about.country.text !== 'N/A' ? about.country.text : null
|
||||
this.location = about.country.isEmpty() ? null : about.country.text
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
const errorMessage = this.$t('Local API Error (Click to copy)')
|
||||
|
@ -631,7 +631,7 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default}
|
||||
* @type {import('youtubei.js').YT.Channel}
|
||||
*/
|
||||
const channel = this.channelInstance
|
||||
let videosTab = await channel.getVideos()
|
||||
|
@ -668,7 +668,7 @@ export default defineComponent({
|
|||
channelLocalNextPage: async function () {
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').ChannelListContinuation|import('youtubei.js/dist/src/parser/youtube/Channel').FilteredChannelList}
|
||||
* @type {import('youtubei.js').YT.ChannelListContinuation|import('youtubei.js').YT.FilteredChannelList}
|
||||
*/
|
||||
const continuation = await this.videoContinuationData.getContinuation()
|
||||
|
||||
|
@ -689,7 +689,7 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default}
|
||||
* @type {import('youtubei.js').YT.Channel}
|
||||
*/
|
||||
const channel = this.channelInstance
|
||||
let liveTab = await channel.getLiveStreams()
|
||||
|
@ -726,7 +726,7 @@ export default defineComponent({
|
|||
getChannelLiveLocalMore: async function () {
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').ChannelListContinuation|import('youtubei.js/dist/src/parser/youtube/Channel').FilteredChannelList}
|
||||
* @type {import('youtubei.js').YT.ChannelListContinuation|import('youtubei.js').YT.FilteredChannelList}
|
||||
*/
|
||||
const continuation = await this.liveContinuationData.getContinuation()
|
||||
|
||||
|
@ -909,7 +909,7 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default}
|
||||
* @type {import('youtubei.js').YT.Channel}
|
||||
*/
|
||||
const channel = this.channelInstance
|
||||
let playlistsTab = await channel.getPlaylists()
|
||||
|
@ -919,7 +919,7 @@ export default defineComponent({
|
|||
|
||||
if (playlistsTab.content_type_filters.length > 1) {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/classes/ChannelSubMenu').default}
|
||||
* @type {import('youtubei.js').YTNodes.ChannelSubMenu}
|
||||
*/
|
||||
const menu = playlistsTab.current_tab.content.sub_menu
|
||||
const createdPlaylistsFilter = menu.content_type_sub_menu_items.find(contentType => {
|
||||
|
@ -964,7 +964,7 @@ export default defineComponent({
|
|||
getChannelPlaylistsLocalMore: async function () {
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').ChannelListContinuation}
|
||||
* @type {import('youtubei.js').YT.ChannelListContinuation}
|
||||
*/
|
||||
const continuation = await this.playlistContinuationData.getContinuation()
|
||||
|
||||
|
@ -1054,12 +1054,12 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default}
|
||||
* @type {import('youtubei.js').YT.Channel}
|
||||
*/
|
||||
const channel = this.channelInstance
|
||||
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').default|import('youtubei.js/dist/src/parser/youtube/Channel').ChannelListContinuation}
|
||||
* @type {import('youtubei.js').YT.Channel|import('youtubei.js').YT.ChannelListContinuation}
|
||||
*/
|
||||
let communityTab = await channel.getCommunity()
|
||||
if (expectedId !== this.id) {
|
||||
|
@ -1095,7 +1095,7 @@ export default defineComponent({
|
|||
getCommunityPostsLocalMore: async function () {
|
||||
try {
|
||||
/**
|
||||
* @type {import('youtubei.js/dist/src/parser/youtube/Channel').ChannelListContinuation}
|
||||
* @type {import('youtubei.js').YT.ChannelListContinuation}
|
||||
*/
|
||||
let continuation = await this.communityContinuationData.getContinuation()
|
||||
|
||||
|
|
|
@ -268,8 +268,7 @@ export default defineComponent({
|
|||
|
||||
if (playabilityStatus.status === 'UNPLAYABLE') {
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/classes/PlayerErrorMessage').default} PlayerErrorMessage
|
||||
* @type {PlayerErrorMessage}
|
||||
* @type {import ('youtubei.js').YTNodes.PlayerErrorMessage}
|
||||
*/
|
||||
const errorScreen = playabilityStatus.error_screen
|
||||
throw new Error(`[${playabilityStatus.status}] ${errorScreen.reason.text}: ${errorScreen.subreason.text}`)
|
||||
|
@ -1217,10 +1216,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
/**
|
||||
* @typedef {import('youtubei.js/dist/src/parser/youtube/VideoInfo').default} VideoInfo
|
||||
*/
|
||||
/**
|
||||
* @param {VideoInfo} videoInfo
|
||||
* @param {import('youtubei.js').YT.VideoInfo} videoInfo
|
||||
*/
|
||||
createLocalDashManifest: async function (videoInfo) {
|
||||
const xmlData = await videoInfo.toDash()
|
||||
|
|
|
@ -8446,10 +8446,10 @@ yocto-queue@^0.1.0:
|
|||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
youtubei.js@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/youtubei.js/-/youtubei.js-4.3.0.tgz#2872ba878c3ee32c77152015267a47275da49459"
|
||||
integrity sha512-HdU6Awdr1nUWy0Ph7WdmoYPWL0ovx+S4w40eeTzAENr5xiUENsLuXcvULRc2fRCIxi+n7Q6142VVhmM4yK/g5g==
|
||||
youtubei.js@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/youtubei.js/-/youtubei.js-5.0.2.tgz#2ce14dcb041fc18ff3ceb86c53abd78ce763f4f1"
|
||||
integrity sha512-Fw2W0TaK50Vqkln3kr7DQ/b5Ve/f9UPh7DizPa4AWtabEyVJ68LNRaEbJp+5oSshbutHs8Q86zMtz+hxy2oQdw==
|
||||
dependencies:
|
||||
jintr "^1.0.0"
|
||||
linkedom "^0.14.12"
|
||||
|
|
Loading…
Reference in New Issue