Skip to content

Commit

Permalink
Proxy live streams when "Proxy Videos Through Invidious" is enabled (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
absidue authored Sep 10, 2024
1 parent 42fc2a5 commit da1514b
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const HTTP_IN_HEX = 0x68747470
const USE_OVERFLOW_MENU_WIDTH_THRESHOLD = 600

const RequestType = shaka.net.NetworkingEngine.RequestType
const AdvancedRequestType = shaka.net.NetworkingEngine.AdvancedRequestType
const TrackLabelFormat = shaka.ui.Overlay.TrackLabelFormat

/** @type {Map<string, string>} */
Expand Down Expand Up @@ -1232,7 +1233,47 @@ export default defineComponent({
response.data = new TextEncoder().encode(cleaned).buffer
}
}
} else if (type === RequestType.MANIFEST && context.type === AdvancedRequestType.MEDIA_PLAYLIST) {
const url = new URL(response.uri)

// Fixes proxied HLS manifests, as Invidious replaces the path parameters with query parameters,
// so shaka-player isn't able to infer the mime type from the `/file/seg.ts` part like it does for non-proxied HLS manifests.
// Shaka-player does attempt to detect it with HEAD request but the `Content-Type` header is `application/octet-stream`,
// which still doesn't tell shaka-player how to handle the stream because that's the equivalent of saying "binary data".
if (url.searchParams.has('local')) {
const stringBody = new TextDecoder().decode(response.data)
const fixed = stringBody.replaceAll(/https?:\/\/.+$/gm, hlsProxiedUrlReplacer)

response.data = new TextEncoder().encode(fixed).buffer
}
}
}

/**
* @param {string} match
*/
function hlsProxiedUrlReplacer(match) {
const url = new URL(match)

let fileValue
for (const [key, value] of url.searchParams) {
if (key === 'file') {
fileValue = value
continue
} else if (key === 'hls_chunk_host') {
// Add the host parameter so some Invidious instances stop complaining about the missing host parameter
// Replace .c.youtube.com with .googlevideo.com as the built-in Invidious video proxy only accepts host parameters with googlevideo.com
url.pathname += `/host/${encodeURIComponent(value.replace('.c.youtube.com', '.googlevideo.com'))}`
}

url.pathname += `/${key}/${encodeURIComponent(value)}`
}

// This has to be right at the end so that shaka-player can read the file extension
url.pathname += `/file/${encodeURIComponent(fileValue)}`

url.search = ''
return url.toString()
}

// #endregion request/response filters
Expand Down
22 changes: 20 additions & 2 deletions src/renderer/views/Watch/Watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,16 @@ export default defineComponent({
// this.manifestSrc = src
// this.manifestMimeType = MANIFEST_TYPE_DASH
// } else {
this.manifestSrc = result.streaming_data.hls_manifest_url
let hlsManifestUrl = result.streaming_data.hls_manifest_url

if (this.proxyVideos) {
const url = new URL(hlsManifestUrl)
url.searchParams.set('local', 'true')

hlsManifestUrl = url.toString().replace(url.origin, this.currentInvidiousInstanceUrl)
}

this.manifestSrc = hlsManifestUrl
this.manifestMimeType = MANIFEST_TYPE_HLS
// }
}
Expand Down Expand Up @@ -808,7 +817,16 @@ export default defineComponent({
// // Proxying doesn't work for live or post live DVR DASH, so use HLS instead
// // https://github.com/iv-org/invidious/pull/4589
// if (this.proxyVideos) {
this.manifestSrc = result.hlsUrl

let hlsManifestUrl = result.hlsUrl

if (this.proxyVideos) {
const url = new URL(hlsManifestUrl)
url.searchParams.set('local', 'true')
hlsManifestUrl = url.toString()
}

this.manifestSrc = hlsManifestUrl
this.manifestMimeType = MANIFEST_TYPE_HLS

// The HLS manifests only contain combined audio+video streams, so we can't do audio only
Expand Down

0 comments on commit da1514b

Please sign in to comment.