ytdl-core
Advanced tools
Comparing version 4.1.0 to 4.1.1
@@ -9,3 +9,3 @@ const PassThrough = require('stream').PassThrough; | ||
const m3u8stream = require('m3u8stream'); | ||
const parseTime = require('m3u8stream/dist/parse-time'); | ||
const { parseTimestamp } = require('m3u8stream'); | ||
@@ -73,3 +73,3 @@ | ||
let err = utils.playError(info.player_response, ['UNPLAYABLE', 'LIVE_STREAM_OFFLINE']); | ||
let err = utils.playError(info.player_response, ['UNPLAYABLE', 'LIVE_STREAM_OFFLINE', 'LOGIN_REQUIRED']); | ||
if (err) { | ||
@@ -164,3 +164,3 @@ stream.emit('error', err); | ||
if (options.begin) { | ||
format.url += `&begin=${parseTime.humanStr(options.begin)}`; | ||
format.url += `&begin=${parseTimestamp(options.begin)}`; | ||
} | ||
@@ -167,0 +167,0 @@ if (options.range && (options.range.start || options.range.end)) { |
const utils = require('./utils'); | ||
const qs = require('querystring'); | ||
const urllib = require('url'); | ||
const parseTime = require('m3u8stream/dist/parse-time'); | ||
const { parseTimestamp } = require('m3u8stream'); | ||
@@ -192,3 +192,3 @@ | ||
length_seconds: details.lengthText ? | ||
Math.floor(parseTime.humanStr(getText(details.lengthText)) / 1000) : | ||
Math.floor(parseTimestamp(getText(details.lengthText)) / 1000) : | ||
rvsParams && `${rvsParams.length_seconds}`, | ||
@@ -195,0 +195,0 @@ thumbnails: details.thumbnail.thumbnails, |
@@ -38,3 +38,4 @@ const urllib = require('url'); | ||
const isValid = info => | ||
info.player_response && (info.player_response.streamingData || isRental(info.player_response)); | ||
info.player_response && (utils.playError(info.player_response, ['LOGIN_REQUIRED']) || | ||
info.player_response.streamingData || isRental(info.player_response)); | ||
let info = await pipeline([id, options], retryOptions, isValid, [ | ||
@@ -52,7 +53,9 @@ getJSONWatchPage, | ||
// Add additional properties to info. | ||
const media = extras.getMedia(info); | ||
let additional = { | ||
author: extras.getAuthor(info), | ||
media: extras.getMedia(info), | ||
media, | ||
likes: extras.getLikes(info), | ||
dislikes: extras.getDislikes(info), | ||
age_restricted: /Age-restricted video/.test(media.notice), | ||
@@ -87,5 +90,5 @@ // Give the standard link to the video. | ||
const getWatchURL = (id, options) => `${VIDEO_URL + id}&hl=${options.lang || 'en'}`; | ||
const getWatchPage = (id, options) => { | ||
const url = getWatchURL(id, options); | ||
const getHTMLWatchURL = (id, options) => `${VIDEO_URL + id}&hl=${options.lang || 'en'}`; | ||
const getHTMLWatchPageBody = (id, options) => { | ||
const url = getHTMLWatchURL(id, options); | ||
return exports.watchPageCache.getOrSet(url, () => miniget(url, options.requestOptions).text()); | ||
@@ -105,3 +108,3 @@ }; | ||
exports.cookieCache.getOrSet(key, async() => { | ||
let page = await getWatchPage(id, options); | ||
let page = await getHTMLWatchPageBody(id, options); | ||
let match = page.match(/(["'])ID_TOKEN\1[:,]\s?"([^"]+)"/); | ||
@@ -130,8 +133,6 @@ if (!match && throwIfNotFound) { | ||
const newInfo = await retryFunc(func, args.concat([info]), retryOptions); | ||
if (newInfo.player_response) { | ||
newInfo.player_response.videoDetails = assign( | ||
info && info.player_response && info.player_response.videoDetails, | ||
newInfo.player_response.videoDetails); | ||
newInfo.player_response = assign(info && info.player_response, newInfo.player_response); | ||
} | ||
newInfo.player_response.videoDetails = assign( | ||
info && info.player_response && info.player_response.videoDetails, | ||
newInfo.player_response.videoDetails); | ||
newInfo.player_response = assign(info && info.player_response, newInfo.player_response); | ||
info = assign(info, newInfo); | ||
@@ -225,9 +226,9 @@ if (isValid(info)) { | ||
const getWatchJSONURL = (id, options) => `${getWatchURL(id, options)}&pbj=1`; | ||
const getWatchJSONURL = (id, options) => `${getHTMLWatchURL(id, options)}&pbj=1`; | ||
const getJSONWatchPage = async(id, options) => { | ||
const reqOptions = Object.assign({ headers: {} }, options.requestOptions); | ||
let cookie = reqOptions.headers.Cookie || reqOptions.headers.cookie; | ||
reqOptions.headers = Object.assign({}, { | ||
reqOptions.headers = Object.assign({ | ||
'x-youtube-client-name': '1', | ||
'x-youtube-client-version': '2.20200701.03.01', | ||
'x-youtube-client-version': '2.20201117.05.00', | ||
'x-youtube-identity-token': exports.cookieCache.get(cookie || 'browser') || '', | ||
@@ -253,7 +254,6 @@ }, reqOptions.headers); | ||
if (parsedBody.reload === 'now' || !Array.isArray(parsedBody)) { | ||
throw Error('Unable to retrieve video metadata'); | ||
throw Error('Unable to retrieve video metadata in watch.json'); | ||
} | ||
let info = parsedBody.reduce((part, curr) => Object.assign(curr, part), {}); | ||
info.player_response = findPlayerResponse('watch.json `player_response`', info); | ||
info.player_response.videoDetails = Object.assign({}, info.player_response.videoDetails, { age_restricted: false }); | ||
info.html5player = info.player && info.player.assets && info.player.assets.js; | ||
@@ -281,15 +281,12 @@ | ||
const getEmbedURL = (id, options) => `${EMBED_URL + id}?hl=${options.lang || 'en'}`; | ||
const getEmbedPage = async(id, options, watchPageInfo) => { | ||
const getEmbedPage = async(id, options) => { | ||
const embedUrl = getEmbedURL(id, options); | ||
let body = await miniget(embedUrl, options.requestOptions).text(); | ||
let jsonStr = utils.between(body, /(['"])PLAYER_(CONFIG|VARS)\1:\s?/, '</script>'); | ||
if (!jsonStr) { | ||
throw Error('Could not find player config'); | ||
let configJson = utils.between(body, /(['"])PLAYER_(CONFIG|VARS)\1:\s?/, '</script>'); | ||
if (!configJson) { | ||
throw Error('Could not find player config in embed.html'); | ||
} | ||
let config = parseJSON('embed config', utils.cutAfterJSON(jsonStr)); | ||
let config = parseJSON('embed config', utils.cutAfterJSON(configJson)); | ||
let info = config.args || config; | ||
info.player_response = findPlayerResponse('embed `player_response`', info); | ||
info.player_response.videoDetails = Object.assign({}, info.player_response.videoDetails, { | ||
age_restricted: watchPageInfo && !!utils.playError(watchPageInfo.player_response, ['LOGIN_REQUIRED']), | ||
}); | ||
info.html5player = getHTML5player(body); | ||
@@ -354,3 +351,3 @@ return info; | ||
if (info.formats.length) { | ||
info.html5player = info.html5player || getHTML5player(await getWatchPage(id, options)); | ||
info.html5player = info.html5player || getHTML5player(await getHTMLWatchPageBody(id, options)); | ||
if (!info.html5player) { | ||
@@ -357,0 +354,0 @@ throw Error('Unable to find html5player file'); |
@@ -9,3 +9,3 @@ { | ||
], | ||
"version": "4.1.0", | ||
"version": "4.1.1", | ||
"repository": { | ||
@@ -40,3 +40,3 @@ "type": "git", | ||
"html-entities": "^1.3.1", | ||
"m3u8stream": "^0.8.2", | ||
"m3u8stream": "^0.8.3", | ||
"miniget": "^4.0.0", | ||
@@ -43,0 +43,0 @@ "sax": "^1.1.3" |
@@ -149,2 +149,3 @@ # node-ytdl-core | ||
* Rentals (if you have access, requires [cookies](example/cookies.js)) | ||
* Age restricted, requires [cookies](example/cookies.js)) | ||
@@ -151,0 +152,0 @@ Generated download links are valid for 6 hours, and may only be downloadable from the same IP address. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
204
85351
2299
Updatedm3u8stream@^0.8.3