add bulk remux script, add docs for remux configuration

aria 1 month ago
parent 1b9374cb37
commit bcac42135c
Signed by: a
GPG Key ID: E851AE999FFCBC37

@ -2,6 +2,13 @@
"port": 8182,
"db-url": "mongodb://",
"media-folder": "private/",
"remux": {
"enabled": true,
"folder": "remux/",
"video-codec": "libx264",
"audio-codec": "aac",
"container": "mp4"
"meta": {
"name": "Media Host",
"tagline": "Your one stop shop to host images, videos, audio and more.",

@ -11,6 +11,13 @@ Here's the [`config.example.json`](../../config.example.json) file, if this suff
"port": 8182,
"db-url": "mongodb://",
"media-folder": "private/",
"remux": {
"enabled": true,
"folder": "remux/",
"video-codec": "libx264",
"audio-codec": "aac",
"container": "mp4"
"meta": {
"name": "Media Host",
"tagline": "Your one stop shop to host images, videos, audio and more.",
@ -47,6 +54,12 @@ If you're a bit confused, don't worry. This will help you understand each part o
- `port` is the HTTP port the server will run on. If `port` is set to `8182`, the server should be at [``](
- `db-url` is the URL to the MongoDB server you want the metadata to be stored on. If you haven't messed with MongoDB's settings at all, leave this as is.
- `media-folder` is where the files themselves are stored. If it's set to `private/`, the files should be inside `private/` folder in the root of the `media-host` folder.
- `remux` is an object where you can set up remuxing a video via FFMPEG to be playable on the web, when not compatible.
- `enabled` is to enable or disable remuxing
- `folder` is the folder where remuxes live
- `video-codec` is the video codec it remuxes to
- `audio-codec` is the autio codec it remuxes to
- `container` is the container it remuxes to
- `meta` is an object where basic metadata of the server is stored.
- `name` is the name of the server, shown at the top of the page on every page.
- `tagline` is the text under the title on every page.

@ -0,0 +1,63 @@
This is not a server file, but a command to remux files on your server.
Usage (in the root of the folder): node ./scripts/remux-unplayable.js
const config = require("../config.json")
const {MongoClient} = require("mongodb");
const client = new MongoClient(config["db-url"], {useUnifiedTopology: true});
const fs = require("fs");
const {spawn} = require("child_process");
const ffmpegStatic = require("ffmpeg-static");
if (!config["media-folder"].startsWith("/")) {
config["media-folder"] = `${__dirname.split("/scripts")[0]}/${config["media-folder"]}`;
(async function() {
console.log("Connecting to DB...");
await client.connect();
console.log("- Connected to DB.");
let db = await client.db("mediahost");
let files = await db.collection("uploads");
let f = await files.find({}).toArray();
let a = [];
if (!fs.existsSync(config?.["remux"]?.["folder"])) fs.mkdirSync(config?.["remux"]?.["folder"]);
for (let c in f) {
if (f[c].mime.startsWith("video/")) {
if (
f[c].mime != "video/mp4" &&
f[c].mime != "video/webm" &&
!f[c].transcodedFile || !fs.existsSync(f[c].transcodedFile)
) {
console.log(`Remuxing ${f[c].id} [${f[c].name}]`);
await ffmpeg(f[c]);
console.log(`Remuxed ${a.length} unplayable files from database.`)
async function ffmpeg(file) {
let db = await client.db("mediahost");
let files = await db.collection("uploads");
return new Promise(function(resolve, reject) {
let originalFile = `${config["media-folder"]}/${}/${}`;
let transFile = `${config["remux"]["folder"]}/${}/${}.${config["remux"]["container"]}`; // based file
if (!fs.existsSync(`${config["remux"]["folder"]}/${}`)) fs.mkdirSync(`${config["remux"]["folder"]}/${}`);
let ffmpegProcess = spawn(ffmpegStatic, [`-i`, originalFile, `-vcodec`, config["remux"]["video-codec"], `-acodec`, config["remux"]["audio-codec"], `-preset`, `ultrafast`, transFile]);
ffmpegProcess.on("close", async function(code) {
if (code == 0) {
file.transcodedFile = `/transcoded/${}/${}.${config["remux"]["container"]}`;
await files.findOneAndReplace({id:}, file);
console.log(`- Remuxed ${} [${}]`);
} else console.log(`ffmpeg failed on ${}`);

@ -30,7 +30,7 @@ app.set("view engine", "ejs");
if (config["remux"]["folder"]) app.use("/transcoded/", express.static(config["remux"]["folder"]));
if (config?.["remux"]?.["folder"]) app.use("/transcoded/", express.static(config?.["remux"]?.["folder"]));
app.use("/temp", express.static(`temp/`));
app.use(async function(req, res, next) {
@ -87,7 +87,7 @@ app.use("/f/:id/dl", function(req, res, next) {
if (!fs.existsSync(config["media-folder"])) fs.mkdirSync(config["media-folder"])
if (!fs.existsSync(config["remux"]["folder"])) fs.mkdirSync(config["remux"]["folder"])
if (!fs.existsSync(config?.["remux"]?.["folder"])) fs.mkdirSync(config?.["remux"]?.["folder"])
@ -513,7 +513,7 @@"/upload", async function (req, res, next) {
mime: files.file.mimetype,
if (data.mime.startsWith("video/")) data.needsTranscode = true;
if (data.mime.startsWith("video/") && data.mime != "video/mp4" && data.mime != "video/webm") data.needsTranscode = true;
if (acc !== null && acc !== undefined) {
data.uploader = acc._id;
@ -1887,7 +1887,7 @@ async function initTranscode(id, mime) {
let file = await files.findOne({id});
if (mime == "video/mp4" || mime == "video/webm") {
if (config["remux"]["enabled"] == true) {
if (config?.["remux"]?.["enabled"] == true) {
let originalFile = `${config["media-folder"]}/${id}/${}`;
let transFile = `${config["remux"]["folder"]}/${id}/${}.${config["remux"]["container"]}`; // based file