Add low-quality server video support
Include low-quality video file paths in movie settings, expose them through the admin UI, and add a player toggle that streams /api/video with quality=low when available. Extend both Node and Python video endpoints to serve the low-quality file. Test: not run (mark for testing)
This commit is contained in:
+9
-2
@@ -148,7 +148,7 @@ router.get("/", async (req, res) => {
|
||||
|
||||
const projection = isChecklist
|
||||
? "imdb_id title"
|
||||
: "imdb_id title description rating poster cam year category vod_link player_mode video_src embed_src video_file updatedAt createdAt";
|
||||
: "imdb_id title description rating poster cam year category vod_link player_mode video_src embed_src video_file video_file_low updatedAt createdAt";
|
||||
|
||||
const cacheKey = `movies:list:${year || "all"}:${isChecklist ? "checklist" : "films"}`;
|
||||
const cached = cacheGet(cacheKey);
|
||||
@@ -333,7 +333,7 @@ router.patch("/users/updateWatchedMovies", async (req, res) => {
|
||||
|
||||
// Add movie
|
||||
router.post("/add", async (req, res) => {
|
||||
const { imdb_id, category, vod_link, year, player_mode, video_src, embed_src, video_file, cam } = req.body;
|
||||
const { imdb_id, category, vod_link, year, player_mode, video_src, embed_src, video_file, video_file_low, cam } = req.body;
|
||||
|
||||
try {
|
||||
// Get the token from the Authorization header
|
||||
@@ -360,6 +360,7 @@ router.post("/add", async (req, res) => {
|
||||
const normalizedVideo = normalizeOptionalString(video_src, 4096);
|
||||
const normalizedEmbed = normalizeOptionalString(embed_src, 20000);
|
||||
const normalizedFile = normalizeVideoFile(video_file);
|
||||
const normalizedLowFile = normalizeVideoFile(video_file_low);
|
||||
const normalizedMode = normalizePlayerMode(player_mode);
|
||||
if (normalizedMode === null) {
|
||||
return res.status(400).json({ message: "player_mode invalide (auto|video|embed)" });
|
||||
@@ -398,6 +399,7 @@ router.post("/add", async (req, res) => {
|
||||
video_src: normalizedVideo || undefined,
|
||||
embed_src: normalizedEmbed || undefined,
|
||||
video_file: normalizedFile || undefined,
|
||||
video_file_low: normalizedLowFile || undefined,
|
||||
});
|
||||
|
||||
await movie.save();
|
||||
@@ -491,6 +493,7 @@ router.put("/:id", async (req, res) => {
|
||||
video_src,
|
||||
embed_src,
|
||||
video_file,
|
||||
video_file_low,
|
||||
refreshOmdb,
|
||||
cam,
|
||||
} = req.body || {};
|
||||
@@ -550,6 +553,10 @@ router.put("/:id", async (req, res) => {
|
||||
movie.video_src = `/api/video/${movie._id}`;
|
||||
}
|
||||
}
|
||||
if (video_file_low !== undefined) {
|
||||
const v = normalizeVideoFile(video_file_low);
|
||||
movie.video_file_low = v ? v : null;
|
||||
}
|
||||
|
||||
if (year !== undefined && year !== null && year !== "") {
|
||||
movie.year = parseOscarYear(year);
|
||||
|
||||
+11
-5
@@ -119,17 +119,23 @@ async function streamMovieFile(req, res) {
|
||||
return res.status(400).json({ message: "Invalid movie id" });
|
||||
}
|
||||
|
||||
const movie = await Movie.findById(id).select("video_file").lean();
|
||||
const qualityRaw = typeof req.query?.quality === "string" ? req.query.quality.trim().toLowerCase() : "";
|
||||
const wantsLow = qualityRaw === "low";
|
||||
|
||||
const movie = await Movie.findById(id).select("video_file video_file_low").lean();
|
||||
const videoFile = typeof movie?.video_file === "string" ? movie.video_file.trim() : "";
|
||||
if (!videoFile) {
|
||||
return res.status(404).json({ message: "No server video file configured for this movie" });
|
||||
const videoFileLow = typeof movie?.video_file_low === "string" ? movie.video_file_low.trim() : "";
|
||||
|
||||
const chosen = wantsLow ? videoFileLow : videoFile;
|
||||
if (!chosen) {
|
||||
return res.status(404).json({ message: wantsLow ? "No low-quality server video file configured for this movie" : "No server video file configured for this movie" });
|
||||
}
|
||||
if (!isSafeRelativeFile(videoFile)) {
|
||||
if (!isSafeRelativeFile(chosen)) {
|
||||
return res.status(400).json({ message: "Invalid video_file path" });
|
||||
}
|
||||
|
||||
const baseDir = getVideoBaseDir();
|
||||
const fullPath = path.resolve(baseDir, videoFile);
|
||||
const fullPath = path.resolve(baseDir, chosen);
|
||||
if (!fullPath.startsWith(baseDir + path.sep) && fullPath !== baseDir) {
|
||||
return res.status(400).json({ message: "Invalid video_file path" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user