[object Object]

← back to Dw Marketing Reels

video-runner: give renders narrated audio via auto-resolved HYPERFRAMES_PYTHON

8227e20da7c603b2986ad0e6ef971ddb60d481e4 · 2026-07-22 07:33:08 -0700 · Steve

Auto-resolve the local HyperFrames TTS venv (~/.hyperframes/tts-venv/bin/python)
and inject it only into the render child's env — so auto-rendered reels get
voiceover/BGM without arming or mutating the pm2/server environment. Honours an
explicit HYPERFRAMES_PYTHON if already set.

Files touched

Diff

commit 8227e20da7c603b2986ad0e6ef971ddb60d481e4
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jul 22 07:33:08 2026 -0700

    video-runner: give renders narrated audio via auto-resolved HYPERFRAMES_PYTHON
    
    Auto-resolve the local HyperFrames TTS venv (~/.hyperframes/tts-venv/bin/python)
    and inject it only into the render child's env — so auto-rendered reels get
    voiceover/BGM without arming or mutating the pm2/server environment. Honours an
    explicit HYPERFRAMES_PYTHON if already set.
---
 scripts/video-runner.mjs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/scripts/video-runner.mjs b/scripts/video-runner.mjs
index 8d5ab6b..fdc4fef 100644
--- a/scripts/video-runner.mjs
+++ b/scripts/video-runner.mjs
@@ -15,10 +15,16 @@ import { existsSync } from 'node:fs';
 import { spawn } from 'node:child_process';
 import { fileURLToPath } from 'node:url';
 import { dirname, join } from 'node:path';
+import { homedir } from 'node:os';
 
 const ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
 const JOBS = join(ROOT, 'data', 'video-jobs.json');
 const ARMED = process.env.VIDEO_AUTORUN === '1';
+// HyperFrames needs a Python venv for TTS/BGM audio. Honour an explicit env var if set,
+// else auto-resolve the standard local venv so auto-rendered reels get narrated audio
+// (no arming/env change needed — this only affects the render child's environment).
+const HF_PY = process.env.HYPERFRAMES_PYTHON
+  || (existsSync(join(homedir(), '.hyperframes/tts-venv/bin/python')) ? join(homedir(), '.hyperframes/tts-venv/bin/python') : '');
 // A single transient Anthropic API blip ("Server is temporarily limiting requests",
 // overloaded, 429/529) used to permanently kill a render. Retry those with backoff.
 const MAX_TRIES = Math.max(1, Number(process.env.VIDEO_MAX_TRIES || 3));
@@ -31,7 +37,9 @@ const isTransient = s => /rate limit|temporarily limiting|overloaded|Overloaded|
 function runClaude(CLAUDE_BIN, pr) {
   return new Promise(resolve => {
     let err = '';
-    const ch = spawn(CLAUDE_BIN, ['-p', pr], { cwd: ROOT, stdio: ['ignore', 'inherit', 'pipe'] });
+    // Give the render its audio toolchain without mutating the pm2/server env.
+    const env = { ...process.env, ...(HF_PY ? { HYPERFRAMES_PYTHON: HF_PY } : {}) };
+    const ch = spawn(CLAUDE_BIN, ['-p', pr], { cwd: ROOT, env, stdio: ['ignore', 'inherit', 'pipe'] });
     ch.stderr.on('data', d => { err += d; process.stderr.write(d); });
     ch.on('close', code => resolve({ ok: code === 0, code, err }));
     ch.on('error', e => resolve({ ok: false, code: -1, err: String(e.message) }));

← 6eb3061 Harden video-runner: retry transient API rate-limits before  ·  back to Dw Marketing Reels  ·  auto-save: 2026-07-22T07:42:20 (3 files) — data/video-jobs.j f9fdb8f →