Skip to content

Commit f4467c4

Browse files
Merge commit '54e85f8616bd10ea73d4e64f4d896018a7a4e2d5' into release
2 parents fa08f63 + 54e85f8 commit f4467c4

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "freetube",
33
"productName": "FreeTube",
44
"description": "A private YouTube client",
5-
"version": "0.23.12",
5+
"version": "0.23.14",
66
"license": "AGPL-3.0-or-later",
77
"main": "./dist/main.js",
88
"private": true,

src/renderer/helpers/api/local.js

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ async function createInnertube({ withPlayer = false, location = undefined, safet
109109
user_agent: navigator.userAgent,
110110

111111
retrieve_player: !!withPlayer,
112+
player_id: '9f4cc5e4',
112113
location: location,
113114
enable_safety_mode: !!safetyMode,
114115
client_type: clientType,
@@ -412,15 +413,11 @@ export async function getLocalVideoInfo(id) {
412413
}
413414

414415
if (info.streaming_data.dash_manifest_url) {
415-
let url = info.streaming_data.dash_manifest_url
416-
417-
if (url.includes('?')) {
418-
url += `&pot=${encodeURIComponent(contentPoToken)}&mpd_version=7`
419-
} else {
420-
url += `${url.endsWith('/') ? '' : '/'}pot/${encodeURIComponent(contentPoToken)}/mpd_version/7`
421-
}
422-
423-
info.streaming_data.dash_manifest_url = url
416+
info.streaming_data.dash_manifest_url = await decipherDashManifestUrl(
417+
info.streaming_data.dash_manifest_url,
418+
webInnertube.session.player,
419+
contentPoToken
420+
)
424421
}
425422
}
426423

@@ -472,6 +469,49 @@ async function decipherFormats(formats, player) {
472469
}
473470
}
474471

472+
/**
473+
* @param {string} url
474+
* @param {import('youtubei.js').Player} player
475+
* @param {string} poToken
476+
*/
477+
async function decipherDashManifestUrl(url, player, poToken) {
478+
const urlObject = new URL(url)
479+
480+
if (urlObject.searchParams.size > 0) {
481+
urlObject.searchParams.set('pot', poToken)
482+
urlObject.searchParams.set('mpd_version', '7')
483+
484+
return await player.decipher(urlObject.toString())
485+
}
486+
487+
// Convert path params to query params
488+
const pathParts = urlObject.pathname
489+
.replace('/api/manifest/dash', '')
490+
.split('/')
491+
.filter(part => part.length > 0)
492+
493+
urlObject.pathname = '/api/manifest/dash'
494+
495+
for (let i = 0; i + 1 < pathParts.length; i += 2) {
496+
urlObject.searchParams.set(pathParts[i], decodeURIComponent(pathParts[i + 1]))
497+
}
498+
499+
// decipher
500+
const deciphered = await player.decipher(urlObject.toString())
501+
502+
// convert query parameters back to path parameters
503+
const decipheredUrlObject = new URL(deciphered)
504+
505+
for (const [key, value] of decipheredUrlObject.searchParams) {
506+
decipheredUrlObject.pathname += `/${key}/${encodeURIComponent(value)}`
507+
}
508+
509+
decipheredUrlObject.search = ''
510+
decipheredUrlObject.pathname += `/pot/${encodeURIComponent(poToken)}/mpd_version/7`
511+
512+
return decipheredUrlObject.toString()
513+
}
514+
475515
export async function getLocalChannelId(url) {
476516
try {
477517
const innertube = await createInnertube()

0 commit comments

Comments
 (0)