From ac1d7e1e1f4f566ebc0878baf72155ee20d87c4d Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Thu, 4 Jun 2026 12:51:32 +0000 Subject: [PATCH] fix(growing): read SMB params from env at mount time, not module load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of growing producing .mov instead of XDCAM HD422 .mxf: mountGrowingShare() used module-level consts (GROWING_SMB_MOUNT etc.) captured from process.env at IMPORT time. Standby capture containers boot with these unset and receive the SMB mount/credentials per-session over /capture/start (capture.js sets process.env right before start()). Because the consts were already frozen empty, mountGrowingShare() saw no mount source, returned false, and growing silently fell back to S3 streaming — producing an HEVC .mov while the asset key said .mxf. Fix: growingSmbConfig() reads process.env fresh at mount time. Also drop the stale const guard in unmountGrowingShare(). --- services/capture/src/capture-manager.js | 33 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/services/capture/src/capture-manager.js b/services/capture/src/capture-manager.js index ffe40ba..89baa72 100644 --- a/services/capture/src/capture-manager.js +++ b/services/capture/src/capture-manager.js @@ -39,10 +39,18 @@ function toUncShare(raw) { if (!s.startsWith('//')) s = '//' + s.replace(/^\/+/, ''); // host/share -> //host/share return s; } -const GROWING_SMB_MOUNT = toUncShare(process.env.GROWING_SMB_MOUNT || ''); -const GROWING_SMB_USERNAME = process.env.GROWING_SMB_USERNAME || ''; -const GROWING_SMB_PASSWORD = process.env.GROWING_SMB_PASSWORD || ''; -const GROWING_SMB_VERS = process.env.GROWING_SMB_VERS || '3.0'; +// Growing SMB params are read FRESH from process.env at mount time, NOT cached +// at module load. Standby capture containers boot with these unset and receive +// them per-session over /capture/start (capture.js sets process.env before +// captureManager.start()). Caching them in module-level consts at import time +// captured the empty boot values, so the mount silently no-op'd and growing +// fell back to S3 — producing .mov instead of the XDCAM HD422 .mxf. +const growingSmbConfig = () => ({ + mount: toUncShare(process.env.GROWING_SMB_MOUNT || ''), + username: process.env.GROWING_SMB_USERNAME || '', + password: process.env.GROWING_SMB_PASSWORD || '', + vers: process.env.GROWING_SMB_VERS || '3.0', +}); const SMB_CREDS_FILE = '/run/smb-creds'; // True when GROWING_PATH is already a mountpoint (e.g. a prior session left it @@ -57,7 +65,11 @@ function isMounted(path) { // Returns true on success (or if already mounted), false on failure — callers // fall back to S3 streaming so a recording is never lost. function mountGrowingShare() { - if (!GROWING_SMB_MOUNT) return false; + const cfg = growingSmbConfig(); + if (!cfg.mount) { + console.warn('[capture] growing requested but GROWING_SMB_MOUNT is empty — falling back to S3'); + return false; + } try { if (isMounted(GROWING_PATH)) { console.log('[capture] growing share already mounted at', GROWING_PATH); @@ -70,14 +82,14 @@ function mountGrowingShare() { // username/password mount inline and smbclient lists the share fine. Inline // user=/password= is the reliable form here. const opts = [ - `username=${GROWING_SMB_USERNAME}`, - `password=${GROWING_SMB_PASSWORD}`, + `username=${cfg.username}`, + `password=${cfg.password}`, 'uid=0', 'gid=0', 'file_mode=0664', 'dir_mode=0775', - `vers=${GROWING_SMB_VERS}`, + `vers=${cfg.vers}`, ].join(','); - execFileSync('mount', ['-t', 'cifs', GROWING_SMB_MOUNT, GROWING_PATH, '-o', opts], + execFileSync('mount', ['-t', 'cifs', cfg.mount, GROWING_PATH, '-o', opts], { stdio: ['ignore', 'ignore', 'pipe'] }); - console.log('[capture] mounted CIFS growing share', GROWING_SMB_MOUNT, '->', GROWING_PATH); + console.log('[capture] mounted CIFS growing share', cfg.mount, '->', GROWING_PATH); return true; } catch (err) { const stderr = err.stderr ? err.stderr.toString().trim() : err.message; @@ -88,7 +100,6 @@ function mountGrowingShare() { // Best-effort unmount on session stop. Ignores "not mounted". function unmountGrowingShare() { - if (!GROWING_SMB_MOUNT) return; try { if (isMounted(GROWING_PATH)) { execFileSync('umount', [GROWING_PATH], { stdio: ['ignore', 'ignore', 'pipe'] });