From 068a1e9b9c103ec72720b9541c7d6a956e4a32a2 Mon Sep 17 00:00:00 2001 From: Renn F Date: Mon, 6 Jul 2026 02:17:57 +0200 Subject: [PATCH] chore(video): rename sidecar to video-renderer + add system ffmpeg for HyperFrames --- .dockerignore | 6 ++-- .github/workflows/release.yml | 2 +- .gitignore | 4 +-- Makefile | 2 +- docker-compose.registry.yml | 22 +++++++------- docker-compose.yaml | 28 ++++++++--------- docker-compose.yml | 28 ++++++++--------- ...n.Dockerfile => video-renderer.Dockerfile} | 30 +++++++++++-------- motion/README.md | 2 +- .../ensure-browser.mjs | 0 .../package.json | 2 +- .../pnpm-lock.yaml | 0 .../pnpm-workspace.yaml | 0 .../render.js | 0 .../server.js | 0 15 files changed, 66 insertions(+), 60 deletions(-) rename docker/{remotion.Dockerfile => video-renderer.Dockerfile} (61%) rename {remotion-renderer => video-renderer}/ensure-browser.mjs (100%) rename {remotion-renderer => video-renderer}/package.json (95%) rename {remotion-renderer => video-renderer}/pnpm-lock.yaml (100%) rename {remotion-renderer => video-renderer}/pnpm-workspace.yaml (100%) rename {remotion-renderer => video-renderer}/render.js (100%) rename {remotion-renderer => video-renderer}/server.js (100%) diff --git a/.dockerignore b/.dockerignore index 0c9fbffb..088af4b6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -33,13 +33,13 @@ panel/out panel/coverage panel/tsconfig.tsbuildinfo -# motion/ (Remotion compositions) + remotion-renderer (its render sidecar) — +# motion/ (HyperFrames compositions) + video-renderer (its render sidecar) — # re-generated by pnpm install; each Dockerfile installs its own inside the # image, and every build shares this root context, so an un-ignored # node_modules here would bloat every image's build-context upload, not -# just remotion.Dockerfile's. +# just video-renderer.Dockerfile's. motion/node_modules -remotion-renderer/node_modules +video-renderer/node_modules # Local stateful data (postgres, redis, ollama, workspaces) — never in images data/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de6ff7a0..9f852115 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: declare -A IMAGES=( [roboco-orchestrator]=docker/orchestrator.Dockerfile [roboco-panel]=docker/panel.Dockerfile - [roboco-remotion]=docker/remotion.Dockerfile + [roboco-video-renderer]=docker/video-renderer.Dockerfile [roboco-agent-pm]=docker/agent-pm.Dockerfile [roboco-agent-dev-be]=docker/agent-dev-be.Dockerfile [roboco-agent-dev-fe]=docker/agent-dev-fe.Dockerfile diff --git a/.gitignore b/.gitignore index b55b0e86..d01228dc 100644 --- a/.gitignore +++ b/.gitignore @@ -104,9 +104,9 @@ panel/tsconfig.tsbuildinfo panel/.env.local panel/.env.*.local -# motion/ (Remotion compositions) + remotion-renderer (its render sidecar) +# motion/ (HyperFrames compositions) + video-renderer (its render sidecar) motion/node_modules/ -remotion-renderer/node_modules/ +video-renderer/node_modules/ # hyperframes lint/preview generates index.html in each composition dir — # regenerated locally as needed, not tracked (the sidecar renders # .html directly, never index.html) diff --git a/Makefile b/Makefile index 36a2fe9b..49935162 100644 --- a/Makefile +++ b/Makefile @@ -449,7 +449,7 @@ clean: @cd .. @cd motion && rm -rf node_modules/ @cd .. - @cd remotion-renderer && rm -rf node_modules/ + @cd video-renderer && rm -rf node_modules/ @cd .. # Security diff --git a/docker-compose.registry.yml b/docker-compose.registry.yml index 01e04ff2..0cc5ba23 100644 --- a/docker-compose.registry.yml +++ b/docker-compose.registry.yml @@ -116,15 +116,15 @@ services: echo "=== All models ready! ===" # -------------------------------------------------------------------------- - # Remotion Renderer - sidecar for the video-generation engine (bundles + - # renders motion/ compositions to MP4). Harmless when idle — it only - # renders when POSTed; the video_engine_* feature flags (off by default in - # this compose) gate whether the orchestrator ever sends it work. No DB - # access, no git, no credentials. + # Video Renderer - sidecar for the video-generation engine (renders + # motion/ compositions to MP4 with HyperFrames). Harmless when idle — it + # only renders when POSTed; the video_engine_* feature flags (off by + # default in this compose) gate whether the orchestrator ever sends it + # work. No DB access, no git, no credentials. # -------------------------------------------------------------------------- - remotion-renderer: - image: ${ROBOCO_REGISTRY:-ghcr.io/rennf93}/roboco-remotion:${ROBOCO_VERSION:-latest} - container_name: roboco-remotion + video-renderer: + image: ${ROBOCO_REGISTRY:-ghcr.io/rennf93}/roboco-video-renderer:${ROBOCO_VERSION:-latest} + container_name: roboco-video-renderer restart: unless-stopped networks: - default @@ -249,10 +249,10 @@ services: ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434 - # Remotion renderer sidecar (use container name). The video engine + # Video renderer sidecar (use container name). The video engine # itself is default-off (video_engine_enabled); this just points the # client at the sidecar for when it's armed. - ROBOCO_REMOTION_BASE_URL: http://roboco-remotion:3001 + ROBOCO_VIDEO_RENDERER_BASE_URL: http://roboco-video-renderer:3001 # Spawn the PRE-BUILT agent images from the same registry instead of # building them from source (the orchestrator pulls any it lacks). ROBOCO_AGENT_IMAGE_REGISTRY: ${ROBOCO_REGISTRY:-ghcr.io/rennf93} @@ -289,7 +289,7 @@ services: ROBOCO_SELF_HEAL_ORIGINATE_ENABLED: ${ROBOCO_SELF_HEAL_ORIGINATE_ENABLED:-false} ROBOCO_SELF_HEAL_PROJECT_SLUG: ${ROBOCO_SELF_HEAL_PROJECT_SLUG:-roboco-api} ROBOCO_SELF_HEAL_CI_WORKFLOW: ${ROBOCO_SELF_HEAL_CI_WORKFLOW:-ci.yml} - # Video engine (Remotion): NAS-default-on, OFF in public registry — + # Video engine (HyperFrames): NAS-default-on, OFF in public registry — # heavier optional feature. Arm via .env + uncomment the video-renders # bind mount above so renders persist. ROBOCO_VIDEO_ENGINE_ENABLED: ${ROBOCO_VIDEO_ENGINE_ENABLED:-false} diff --git a/docker-compose.yaml b/docker-compose.yaml index 5ca3cc7f..d3ee41ea 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -152,19 +152,19 @@ services: echo "=== All models ready! ===" # ========================================================================== - # Remotion Renderer - sidecar for the video-generation engine (bundles + - # renders motion/ compositions to MP4). Mirrors the ollama sidecar pattern: - # a plain HTTP service the orchestrator talks to, nothing more. Harmless - # when idle — it only renders when POSTed; the video_engine_* feature - # flags gate whether the orchestrator ever sends it work. No DB access, no - # git, no credentials — it only ever reads what it's POSTed. + # Video Renderer - sidecar for the video-generation engine (renders + # motion/ compositions to MP4 with HyperFrames). Mirrors the ollama sidecar + # pattern: a plain HTTP service the orchestrator talks to, nothing more. + # Harmless when idle — it only renders when POSTed; the video_engine_* + # feature flags gate whether the orchestrator ever sends it work. No DB + # access, no git, no credentials — it only ever reads what it's POSTed. # ========================================================================== - remotion-renderer: + video-renderer: build: context: . - dockerfile: docker/remotion.Dockerfile - image: roboco-remotion - container_name: roboco-remotion + dockerfile: docker/video-renderer.Dockerfile + image: roboco-video-renderer + container_name: roboco-video-renderer restart: unless-stopped networks: - default @@ -396,10 +396,10 @@ services: ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434 - # Remotion renderer sidecar (use container name). The video engine + # Video renderer sidecar (use container name). The video engine # itself is default-off (video_engine_enabled); this just points the # client at the sidecar for when it's armed. - ROBOCO_REMOTION_BASE_URL: http://roboco-remotion:3001 + ROBOCO_VIDEO_RENDERER_BASE_URL: http://roboco-video-renderer:3001 # MinIO object storage for rendered videos (use container name). Empty # endpoint = disabled (FileResponse fallback); armed here for the NAS # deploy, left OFF in docker-compose.registry.yml. @@ -486,9 +486,9 @@ services: # the Product Owner, who proposes a themed cycle of roadmap items; # the CEO approves each item individually into the backlog. ROBOCO_ROADMAP_ENGINE_ENABLED: ${ROBOCO_ROADMAP_ENGINE_ENABLED:-true} - # Video-generation engine: a UX/UI dev authors a bespoke Remotion video + # Video-generation engine: a UX/UI dev authors a bespoke HyperFrames video # per release/spotlight/on-demand trigger through the normal delivery - # lifecycle; the render loop above renders it via the remotion-renderer + # lifecycle; the render loop above renders it via the video-renderer # sidecar and holds the clip as a CEO-approval draft — nothing # auto-posts. Config default is OFF; ARMED here for the NAS deploy like # the rest. Left OFF in docker-compose.registry.yml so the published diff --git a/docker-compose.yml b/docker-compose.yml index 5ca3cc7f..d3ee41ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -152,19 +152,19 @@ services: echo "=== All models ready! ===" # ========================================================================== - # Remotion Renderer - sidecar for the video-generation engine (bundles + - # renders motion/ compositions to MP4). Mirrors the ollama sidecar pattern: - # a plain HTTP service the orchestrator talks to, nothing more. Harmless - # when idle — it only renders when POSTed; the video_engine_* feature - # flags gate whether the orchestrator ever sends it work. No DB access, no - # git, no credentials — it only ever reads what it's POSTed. + # Video Renderer - sidecar for the video-generation engine (renders + # motion/ compositions to MP4 with HyperFrames). Mirrors the ollama sidecar + # pattern: a plain HTTP service the orchestrator talks to, nothing more. + # Harmless when idle — it only renders when POSTed; the video_engine_* + # feature flags gate whether the orchestrator ever sends it work. No DB + # access, no git, no credentials — it only ever reads what it's POSTed. # ========================================================================== - remotion-renderer: + video-renderer: build: context: . - dockerfile: docker/remotion.Dockerfile - image: roboco-remotion - container_name: roboco-remotion + dockerfile: docker/video-renderer.Dockerfile + image: roboco-video-renderer + container_name: roboco-video-renderer restart: unless-stopped networks: - default @@ -396,10 +396,10 @@ services: ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434 - # Remotion renderer sidecar (use container name). The video engine + # Video renderer sidecar (use container name). The video engine # itself is default-off (video_engine_enabled); this just points the # client at the sidecar for when it's armed. - ROBOCO_REMOTION_BASE_URL: http://roboco-remotion:3001 + ROBOCO_VIDEO_RENDERER_BASE_URL: http://roboco-video-renderer:3001 # MinIO object storage for rendered videos (use container name). Empty # endpoint = disabled (FileResponse fallback); armed here for the NAS # deploy, left OFF in docker-compose.registry.yml. @@ -486,9 +486,9 @@ services: # the Product Owner, who proposes a themed cycle of roadmap items; # the CEO approves each item individually into the backlog. ROBOCO_ROADMAP_ENGINE_ENABLED: ${ROBOCO_ROADMAP_ENGINE_ENABLED:-true} - # Video-generation engine: a UX/UI dev authors a bespoke Remotion video + # Video-generation engine: a UX/UI dev authors a bespoke HyperFrames video # per release/spotlight/on-demand trigger through the normal delivery - # lifecycle; the render loop above renders it via the remotion-renderer + # lifecycle; the render loop above renders it via the video-renderer # sidecar and holds the clip as a CEO-approval draft — nothing # auto-posts. Config default is OFF; ARMED here for the NAS deploy like # the rest. Left OFF in docker-compose.registry.yml so the published diff --git a/docker/remotion.Dockerfile b/docker/video-renderer.Dockerfile similarity index 61% rename from docker/remotion.Dockerfile rename to docker/video-renderer.Dockerfile index 128b5127..9ab7f6ce 100644 --- a/docker/remotion.Dockerfile +++ b/docker/video-renderer.Dockerfile @@ -1,18 +1,23 @@ -# remotion-renderer sidecar — untars a motion/ composition source, bundles -# it, renders one MP4 cut with Remotion, and streams the bytes back. +# video-renderer sidecar — untars a motion/ composition source, renders one +# MP4 cut with HyperFrames, and streams the bytes back. # # Debian (not Alpine): musl slows renders past 10s and has known Chrome -# Headless Shell compatibility issues (verified against Remotion's own -# Docker guidance). FFmpeg is bundled inside @remotion/renderer since v4 — -# no system ffmpeg package here. +# Headless Shell compatibility issues (verified against upstream +# headless-Chrome Docker guidance). HyperFrames' @hyperframes/producer +# encodes via a system ffmpeg binary — unlike @remotion/renderer (which +# bundled ffmpeg), the producer shells out to ffmpeg on PATH, so install +# it here. # # Build context is the project root, like every other service under # docker/ — paths below are relative to the repo root. FROM node:22-bookworm-slim -# Chrome/Puppeteer runtime libraries — Remotion's documented Debian -# dependency list for headless rendering. A missing one surfaces as an -# opaque Puppeteer "Target closed" crash, not a clear missing-library error. +# Chrome/Puppeteer runtime libraries — the documented Debian dependency +# list for headless rendering (per Puppeteer/Chrome guidance). A missing +# one surfaces as an opaque Puppeteer "Target closed" crash, not a clear +# missing-library error. +# ffmpeg: required by @hyperframes/producer's local render mode — see top +# comment; without it renders fail with "FFmpeg not found". RUN apt-get update && apt-get install -y --no-install-recommends \ libnss3 \ libdbus-1-3 \ @@ -28,10 +33,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpango-1.0-0 \ libcairo2 \ libcups2 \ + ffmpeg \ ca-certificates \ && rm -rf /var/lib/apt/lists/* -# Activate the exact version remotion-renderer/package.json pins +# Activate the exact version video-renderer/package.json pins # (packageManager: pnpm@11.10.0) rather than trusting corepack's bundled # default — a future node:22-alpine shipping a different pnpm would silently # change the build's package manager. @@ -50,15 +56,15 @@ ENV CI=true # pnpm-workspace.yaml carries the `allowBuilds: esbuild: true` approval — # without it pnpm 11 hard-errors with [ERR_PNPM_IGNORED_BUILDS] (exit 1) # because esbuild's postinstall is unapproved, breaking the image build. -COPY remotion-renderer/package.json remotion-renderer/pnpm-lock.yaml remotion-renderer/pnpm-workspace.yaml ./ +COPY video-renderer/package.json video-renderer/pnpm-lock.yaml video-renderer/pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile # Pre-warm Chrome Headless Shell at build time so the container's first # real render isn't also the first time it downloads a browser. -COPY remotion-renderer/ensure-browser.mjs ./ +COPY video-renderer/ensure-browser.mjs ./ RUN node ensure-browser.mjs -COPY remotion-renderer/server.js remotion-renderer/render.js ./ +COPY video-renderer/server.js video-renderer/render.js ./ EXPOSE 3001 ENV PORT=3001 diff --git a/motion/README.md b/motion/README.md index 105f0ae7..bcae7496 100644 --- a/motion/README.md +++ b/motion/README.md @@ -1,6 +1,6 @@ # motion -In-repo [HyperFrames](https://github.com/heygen-com/hyperframes) composition package. UX/UI devs author bespoke marketing-video compositions here on a normal delivery branch; once a composition merges, the orchestrator's render loop tars this directory and POSTs it to the `remotion-renderer` sidecar (T1 rewrote its render core to `@hyperframes/producer`), which renders the HTML to MP4 with Chromium. This package never renders itself — its own gate (`pnpm test`) is static: a vitest HTML-structure smoke against the authored files. The render-truth check happens on the sidecar, against the merged files. +In-repo [HyperFrames](https://github.com/heygen-com/hyperframes) composition package. UX/UI devs author bespoke marketing-video compositions here on a normal delivery branch; once a composition merges, the orchestrator's render loop tars this directory and POSTs it to the `video-renderer` sidecar (T1 rewrote its render core to `@hyperframes/producer`), which renders the HTML to MP4 with Chromium. This package never renders itself — its own gate (`pnpm test`) is static: a vitest HTML-structure smoke against the authored files. The render-truth check happens on the sidecar, against the merged files. ## Adding a composition diff --git a/remotion-renderer/ensure-browser.mjs b/video-renderer/ensure-browser.mjs similarity index 100% rename from remotion-renderer/ensure-browser.mjs rename to video-renderer/ensure-browser.mjs diff --git a/remotion-renderer/package.json b/video-renderer/package.json similarity index 95% rename from remotion-renderer/package.json rename to video-renderer/package.json index f8705f7c..cf1bc852 100644 --- a/remotion-renderer/package.json +++ b/video-renderer/package.json @@ -1,5 +1,5 @@ { - "name": "remotion-renderer", + "name": "video-renderer", "version": "1.0.0", "private": true, "packageManager": "pnpm@11.10.0", diff --git a/remotion-renderer/pnpm-lock.yaml b/video-renderer/pnpm-lock.yaml similarity index 100% rename from remotion-renderer/pnpm-lock.yaml rename to video-renderer/pnpm-lock.yaml diff --git a/remotion-renderer/pnpm-workspace.yaml b/video-renderer/pnpm-workspace.yaml similarity index 100% rename from remotion-renderer/pnpm-workspace.yaml rename to video-renderer/pnpm-workspace.yaml diff --git a/remotion-renderer/render.js b/video-renderer/render.js similarity index 100% rename from remotion-renderer/render.js rename to video-renderer/render.js diff --git a/remotion-renderer/server.js b/video-renderer/server.js similarity index 100% rename from remotion-renderer/server.js rename to video-renderer/server.js