diff --git a/README.md b/README.md index 5a18d6d..865f99c 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ A media host specialized in producing visually appealing embeds for services lik $ export EBPASS=changeme $ export EBPORT=3000 $ export EBAPI_KEY=changeme # For ShareX support +$ export EB_PROCESS_VIDEO=true # Enable video processing $ npm install $ npm start @@ -57,22 +58,38 @@ Enabled at `/upload`. Requires authentication with key. `expire` key specifies d ### Configuration -This project uses environmental variables to configure functions. +This project uses environmental variables for configuration: -`EBPASS` configures the password for the admin account. +| Variable | Description | Default | +|----------|-------------|---------| +| `EBPASS` | Password for the admin account | required | +| `EBAPI_KEY` | Key for API uploading (ShareX) | required | +| `EBPORT` | Port the server runs on | required | +| `EB_PROCESS_VIDEO` | Enable video processing/optimization | `true` | +| `EB_ENCODER` | Video encoder to use (CPU, NVENC, QSV, etc.) | `CPU` | +| `EB_FFMPEG_PATH` | Path to ffmpeg binary | auto-detected or bundled | +| `EB_FFPROBE_PATH` | Path to ffprobe binary | auto-detected or bundled | +| `EB_RANDOMIZE_NAMES` | Randomize uploaded file names | `false` | -`EBAPI_KEY` configures the key for API uploading support typically used for ShareX. +#### Video Processing -`EBPORT` configures the port the server runs on. +When `EB_PROCESS_VIDEO` is enabled (which is the default), Embedder will: -`EB_FFMPEG_PATH` and `EB_FFPROBE_PATH` configures the path to the ffmpeg and ffprobe binaries respectively. If not set, it uses installed binaries set in the PATH. If none are detected, it will default to preinstalled binaries from the [node-ffmpeg-installer](https://www.npmjs.com/package/@ffmpeg-installer/ffmpeg) package. +1. Process uploaded videos to create optimized 720p versions +2. Show "Copy as GIFv" links for video files +3. Display a processing spinner while videos are being optimized -`EB_RANDOMIZE_NAMES` configures whether or not to randomize file names. If set to `true`, file names will be randomized. If not set or set to false, it will be `false`. +If disabled by setting `EB_PROCESS_VIDEO=false`, videos will be served directly without processing, which can be useful on systems with limited resources. ### Using Docker ```bash -docker run -d -p "3000:3000" -e EBPORT=3000 -e EBPASS=changeme -e EBAPI_KEY=changeme ghcr.io/waveringana/embedder:1.13 +docker run -d -p "3000:3000" \ + -e EBPORT=3000 \ + -e EBPASS=changeme \ + -e EBAPI_KEY=changeme \ + -e EB_PROCESS_VIDEO=true \ + ghcr.io/waveringana/embedder:1.13 ``` ### Docker Compose @@ -86,6 +103,7 @@ services: - EBPORT=3000 - EBPASS=changeme - EBAPI_KEY=changeme + - EB_PROCESS_VIDEO=true volumes: - ./db:/var/db - ./uploads:/uploads diff --git a/app/app.ts b/app/app.ts index 689414e..e008db2 100644 --- a/app/app.ts +++ b/app/app.ts @@ -92,6 +92,8 @@ function onListening() { const bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; + const processVideo = process.env["EB_PROCESS_VIDEO"] === "true" ? true : false; + console.log("Process video: " + processVideo); console.log("Embedder version: " + version); console.log("Listening on " + bind); } diff --git a/app/public/js/index.js b/app/public/js/index.js index ba3609f..864e25c 100644 --- a/app/public/js/index.js +++ b/app/public/js/index.js @@ -24,7 +24,10 @@ class FileUploader { this.dropArea = document.getElementById('dropArea'); this.gallery = document.getElementById('gallery'); this.setupEventListeners(); - this.setupProgressUpdates(); // SSE logic for transcoding + // Only set up SSE if we're processing videos + if (document.body.dataset.processVideo === 'true') { + this.setupProgressUpdates(); + } } setupEventListeners() { diff --git a/app/routes/index.ts b/app/routes/index.ts index 7a0bf26..33c5b8a 100644 --- a/app/routes/index.ts +++ b/app/routes/index.ts @@ -26,6 +26,8 @@ import { processUploadedMedia, } from "../lib/middleware"; +const processVideo: boolean = process.env["EB_PROCESS_VIDEO"] !== "false"; + const upload = multer({ storage: fileStorage /**, fileFilter: fileFilter**/ }); //maybe make this a env variable? /**Middleware to grab media from media database */ @@ -65,6 +67,11 @@ const fetchMedia: Middleware = (req, res, next) => { const router = express.Router(); router.get('/progress-updates', (req, res) => { + if (!processVideo) { + res.status(404).send('Video processing is disabled'); + return; + } + console.log("SSE connection requested"); // Debug log res.setHeader('Content-Type', 'text/event-stream'); @@ -96,12 +103,12 @@ router.get( fetchMedia, (req: Request, res: Response) => { res.locals.filter = null; - res.render("index", { user: req.user }); + res.render("index", { user: req.user, processVideo }); } ); router.get("/media-list", fetchMedia, (req: Request, res: Response) => { - res.render("partials/_fileList", { user: req.user }); + res.render("partials/_fileList", { user: req.user, processVideo }); }); router.get( @@ -189,21 +196,36 @@ router.get("/oembed/:file", } ); -router.post( - "/", - [ - checkAuth, - upload.array("fileupload"), - handleUpload, - fetchMedia, - processUploadedMedia, - createEmbedData, - ], - (req: Request, res: Response) => { - return res.render("partials/_fileList", { user: req.user }); // Render only the file list partial - } -); - +if (processVideo) { + router.post( + "/", + [ + checkAuth, + upload.array("fileupload"), + handleUpload, + fetchMedia, + processUploadedMedia, + createEmbedData, + ], + (req: Request, res: Response) => { + return res.render("partials/_fileList", { user: req.user, processVideo }); // Render only the file list partial + } + ); +} else { + router.post( + "/", + [ + checkAuth, + upload.array("fileupload"), + handleUpload, + fetchMedia, + createEmbedData + ], + (req: Request, res: Response) => { + return res.render("partials/_fileList", { user: req.user, processVideo }); // Render only the file list partial + } + ); +} router.post( "/sharex", [checkSharexAuth, upload.single("fileupload"), createEmbedData, handleUpload], diff --git a/app/services/ProgressManager.ts b/app/services/ProgressManager.ts index 1c9d9f1..2603b8a 100644 --- a/app/services/ProgressManager.ts +++ b/app/services/ProgressManager.ts @@ -11,10 +11,12 @@ class ProgressManager { private static instance: ProgressManager; private emitter: EventEmitter; private activeJobs: Map; + private processVideo: boolean; private constructor() { this.emitter = new EventEmitter(); this.activeJobs = new Map(); + this.processVideo = process.env["EB_PROCESS_VIDEO"] === "true"; } static getInstance(): ProgressManager { @@ -25,19 +27,27 @@ class ProgressManager { } updateProgress(update: ProgressUpdate) { + if (!this.processVideo) return; + this.activeJobs.set(update.filename, update); this.emitter.emit('progress', update); } subscribeToUpdates(callback: (update: ProgressUpdate) => void) { + if (!this.processVideo) return; + this.emitter.on('progress', callback); } unsubscribeFromUpdates(callback: (update: ProgressUpdate) => void) { + if (!this.processVideo) return; + this.emitter.off('progress', callback); } getJobStatus(filename: string): ProgressUpdate | undefined { + if (!this.processVideo) return undefined; + return this.activeJobs.get(filename); } } diff --git a/app/views/index.ejs b/app/views/index.ejs index 1cb3564..f40a1dc 100644 --- a/app/views/index.ejs +++ b/app/views/index.ejs @@ -15,7 +15,7 @@ - +

Embedder

diff --git a/app/views/partials/_fileList.ejs b/app/views/partials/_fileList.ejs index 4761756..b18e570 100644 --- a/app/views/partials/_fileList.ejs +++ b/app/views/partials/_fileList.ejs @@ -23,6 +23,7 @@ function sanitizeId(filename) {
<% const sanitizedId = file.path.replace(/[^a-z0-9]/gi, '_'); %> + <% if (processVideo) { %>
Optimizing Video for Sharing... @@ -30,8 +31,12 @@ function sanitizeId(filename) {
+ <% } else { %> +
+ <% } %>
@@ -40,7 +45,9 @@ function sanitizeId(filename) { <%= file.username %>
<% } %> - Copy as GIFv + <% if (processVideo) { %> + Copy as GIFv + <% } %>
<% } else if (mediaType === 'image') { %> diff --git a/bun.lockb b/bun.lockb index f92a79b..eb11124 100755 Binary files a/bun.lockb and b/bun.lockb differ