chore(video): rename sidecar to video-renderer + add system ffmpeg for HyperFrames

This commit is contained in:
Renn F
2026-07-06 02:17:57 +02:00
parent 608051e2ca
commit 068a1e9b9c
15 changed files with 66 additions and 60 deletions
+3 -3
View File
@@ -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/
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
# <orientation>.html directly, never index.html)
+1 -1
View File
@@ -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
+11 -11
View File
@@ -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}
+14 -14
View File
@@ -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
+14 -14
View File
@@ -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
@@ -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
+1 -1
View File
@@ -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
@@ -1,5 +1,5 @@
{
"name": "remotion-renderer",
"name": "video-renderer",
"version": "1.0.0",
"private": true,
"packageManager": "pnpm@11.10.0",