Stream refreshed media for playback and view full
This commit is contained in:
+41
-3
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
|
||||
import express, { type Request, type Response } from "express";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { Readable } from "node:stream";
|
||||
import http from "node:http";
|
||||
import https from "node:https";
|
||||
import { dirname } from "node:path";
|
||||
@@ -758,7 +759,7 @@ export function startWebUi(deps: WebUiDeps): WebUiHandle {
|
||||
"/api/media/:scrapeId/:itemId/thumb",
|
||||
wrap(async (req, res) => {
|
||||
const file = deps.media.getMediaThumb(String(req.params.scrapeId), Number(req.params.itemId));
|
||||
if (!file) throw new HttpError(404, "thumb not found");
|
||||
if (!file || !existsSync(file.path)) throw new HttpError(404, "thumb not found");
|
||||
res.type(file.contentType).sendFile(file.path);
|
||||
})
|
||||
);
|
||||
@@ -767,11 +768,48 @@ export function startWebUi(deps: WebUiDeps): WebUiHandle {
|
||||
"/api/media/:scrapeId/:itemId/file",
|
||||
wrap(async (req, res) => {
|
||||
const file = deps.media.getMediaFile(String(req.params.scrapeId), Number(req.params.itemId));
|
||||
if (!file) throw new HttpError(404, "file not found");
|
||||
if (!file || !existsSync(file.path)) throw new HttpError(404, "file not found");
|
||||
res.type(file.contentType).sendFile(file.path);
|
||||
})
|
||||
);
|
||||
|
||||
// Playback and full-view source: local file when downloaded, otherwise a refreshed remote URL.
|
||||
app.get(
|
||||
"/api/media/:scrapeId/:itemId/stream",
|
||||
wrap(async (req, res) => {
|
||||
const source = await deps.media.resolveMediaSource(
|
||||
String(req.params.scrapeId),
|
||||
Number(req.params.itemId)
|
||||
);
|
||||
if (!source) throw new HttpError(404, "media source not found");
|
||||
|
||||
if (source.kind === "file") {
|
||||
if (!existsSync(source.path)) throw new HttpError(404, "file not found");
|
||||
res.type(source.contentType).sendFile(source.path);
|
||||
return;
|
||||
}
|
||||
|
||||
const upstream = await fetch(source.url, {
|
||||
headers: req.headers.range ? { range: String(req.headers.range) } : {}
|
||||
});
|
||||
if (!upstream.ok && upstream.status !== 206) {
|
||||
throw new HttpError(502, `upstream ${upstream.status}`);
|
||||
}
|
||||
|
||||
res.status(upstream.status);
|
||||
for (const header of ["content-type", "content-length", "accept-ranges", "content-range"]) {
|
||||
const value = upstream.headers.get(header);
|
||||
if (value) res.setHeader(header, value);
|
||||
}
|
||||
|
||||
if (!upstream.body) {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
Readable.fromWeb(upstream.body as any).pipe(res);
|
||||
})
|
||||
);
|
||||
|
||||
app.get(
|
||||
"/api/media/storage",
|
||||
wrap(async (_req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user