diff --git a/lib/Controller/DownloadController.php b/lib/Controller/DownloadController.php index 4eef3716..b4e939e8 100644 --- a/lib/Controller/DownloadController.php +++ b/lib/Controller/DownloadController.php @@ -125,9 +125,9 @@ class DownloadController extends GenericApiController * * @PublicPage */ - public function one(int $fileid, bool $resumable = true): Http\Response + public function one(int $fileid, bool $resumable = true, int $numChunks = 0): Http\Response { - return Util::guardEx(function () use ($fileid, $resumable) { + return Util::guardEx(function () use ($fileid, $resumable, $numChunks) { $file = $this->fs->getUserFile($fileid); // check if http_range is sent by browser @@ -157,11 +157,19 @@ class DownloadController extends GenericApiController // Default to 64MB $maxLen = 64 * 1024 * 1024; - // For videos, use 4MB + // For videos, use a max of 8MB if ('video' === $this->request->getHeader('Sec-Fetch-Dest')) { - $maxLen = 4 * 1024 * 1024; + $maxLen = 8 * 1024 * 1024; } + // Check if the client sent a hint for the chunk size + if ($numChunks) { + $maxLen = min(ceil($size / $numChunks), $maxLen * 3); + } + + // No less than 1MB; this is just wasteful + $maxLen = max($maxLen, 1024 * 1024); + $seekEnd = min($seekEnd, $seekStart + $maxLen); } diff --git a/src/components/viewer/PsVideo.ts b/src/components/viewer/PsVideo.ts index d6f0aa4b..0e0ee777 100644 --- a/src/components/viewer/PsVideo.ts +++ b/src/components/viewer/PsVideo.ts @@ -126,6 +126,15 @@ class VideoContentSetup { }); } + getDirectSrc(content: VideoContent) { + const numChunks = + Math.ceil((content.data.photo?.video_duration || 0) / 3) || undefined; + return { + src: API.Q(content.data.src, { numChunks }), + type: "video/mp4", // chrome refuses to play video/quicktime, so fool it + }; + } + getHLSsrc(content: VideoContent) { // Get base URL const fileid = content.data.photo.fileid; @@ -169,10 +178,7 @@ class VideoContentSetup { sources.push(this.getHLSsrc(content)); } - sources.push({ - src: content.data.src, - type: "video/mp4", - }); + sources.push(this.getDirectSrc(content)); const overrideNative = !vidjs.browser.IS_SAFARI; const vjs = (content.videojs = vidjs(content.videoElement, { @@ -208,10 +214,7 @@ class VideoContentSetup { if (!directFailed) { console.warn("PsVideo: Trying direct video stream"); - vjs.src({ - src: content.data.src, - type: "video/mp4", - }); + vjs.src(this.getDirectSrc(content)); this.updateRotation(content, 0); } } else { @@ -350,6 +353,8 @@ class VideoContentSetup { qualityList = content.videojs?.qualityLevels(); if (!qualityList || !content.videojs) return; + const isHLS = content.videojs.src(undefined).includes("m3u8"); + if (quality === -2) { // Direct playback // Prevent any useless transcodes @@ -358,16 +363,13 @@ class VideoContentSetup { } // Set the source to the original video - if (content.videojs.src(undefined).includes("m3u8")) { - content.videojs.src({ - src: content.data.src, - type: "video/mp4", - }); + if (isHLS) { + content.videojs.src(this.getDirectSrc(content)); } return; } else { // Set source to HLS - if (!content.videojs.src(undefined).includes("m3u8")) { + if (!isHLS) { content.videojs.src(this.getHLSsrc(content)); } } diff --git a/src/services/API.ts b/src/services/API.ts index b572e2e5..1b672629 100644 --- a/src/services/API.ts +++ b/src/services/API.ts @@ -51,6 +51,9 @@ export class API { } }); + // Check if nothing in query + if (!Object.keys(query).length) return url; + // Convert to search params query = new URLSearchParams(query); }