---
title: "Rendering verbs"
description: "ralphy render plus the audio, video, voice, editor utility verbs that bracket the render."
---

`ralphy render <project>` is the one-shot path from a populated workspace to a finished mp4. The `editor`, `audio`, `video`, and `voice` verbs are the observability and post-processing helpers that bracket it — preflight checks before the render, ffmpeg recipes after. Per [AGENTS.md invariant #5](https://github.com/alecs5am/ralphy/blob/main/AGENTS.md), there is no auto-launched Studio; iterations happen via `ralphy generate` + `ralphy render`, not Studio scrubbing.

## ralphy render

Reads `scenario.json` + `asset-manifest.json`, drives HyperFrames (Puppeteer rasterizer + FFmpeg muxer) against `.ralphy/workspaces/<ws>/projects/<id>/index.html`, optionally post-processes with EBU R128 loudnorm.

```bash
ralphy render demo-001
ralphy render demo-001 --loudnorm
ralphy render demo-001 --output ./out.mp4
ralphy render demo-001 --fps 60 --quality high
```

Output lands at `.ralphy/workspaces/<ws>/projects/<id>/render/final.mp4`. With `--loudnorm`, the raw render writes to `final.raw.mp4` and the ffmpeg pass produces `final.mp4` at `-16 LUFS` (TikTok/Reels target).

<ParamField path="--output <path>" type="string">
  Custom output path. Default: `.ralphy/workspaces/<ws>/projects/<id>/render/final.mp4`.
</ParamField>

<ParamField path="--loudnorm" type="boolean">
  Post-process with `loudnorm=I=-16:TP=-1.5:LRA=11`. Adds a few seconds, fixes the "too quiet on mobile" problem.
</ParamField>

<ParamField path="--fps <fps>" type="number">
  Frame rate. Default: 30.
</ParamField>

<ParamField path="--quality <quality>" type="string">
  Quality preset: `draft` | `standard` | `high`. Default: `standard`.
</ParamField>

<ParamField path="--dry-run" type="boolean">
  Print the resolved render plan; skip the actual render.
</ParamField>

Full surface: [`/reference/cli/render`](/reference/cli/render).

### When it fails

HyperFrames render exits non-zero → the log line goes to `generations.jsonl` with `status: "error"` and `E_INTERNAL` raises with the last 500 bytes of stderr. Loudnorm failure → same, with the ffmpeg tail.

## ralphy editor

Editor-stage observability — preflight every clip with ffprobe, sum durations, flag missing slots, surface aspect / fps / codec mismatches before the render.

```bash
ralphy editor preflight demo-001
ralphy editor preflight demo-001 --expected-aspect 9:16 --expected-fps 30
ralphy editor trim-analyze demo-001    # per-clip gemini-vision dead-head/tail
```

`preflight` exits 1 on red — wire it into CI ahead of `ralphy render` and you'll catch wrong-aspect leftovers from a model swap, missing scenes, codec drift. Full surface: [`/reference/cli/editor`](/reference/cli/editor).

## ralphy audio

Audio recipes wrapping `cli/lib/ffmpeg-recipes.ts`. Three recipes ship in v1:

```bash
# EBU R128 loudnorm
ralphy audio loudnorm --in vo.mp3 --out vo.norm.mp3 --target -16

# Duck music under VO with a sidechain compressor → single mixed file
ralphy audio sidechain \
  --voice vo.norm.mp3 \
  --music bed.mp3 \
  --out scene-04-mix.mp3 \
  --ratio 8 --threshold 0.05

# Lossless concat via the concat demuxer
ralphy audio concat --files a.mp3,b.mp3,c.mp3 --out full.mp3
```

Each recipe appends a structured log line to `generations.jsonl` when `--project` is set. Full surface: [`/reference/cli/audio`](/reference/cli/audio).

## ralphy video

Video recipes — also `cli/lib/ffmpeg-recipes.ts`. Common subset:

```bash
ralphy video extract-segment --in clip.mp4 --out cut.mp4 --start 2.4 --end 7.1
ralphy video optimize --in big.mp4 --out small.mp4 --crf 23 --tune grain
ralphy video burn-subs --in clip.mp4 --subs caps.srt --out subbed.mp4
ralphy video tonemap-hdr --in hdr.mp4 --out sdr.mp4
ralphy video concat --files a.mp4,b.mp4 --out full.mp4
ralphy video add-music-bed --in clip.mp4 --music bed.mp3 --out scored.mp4
```

`optimize` reports the compression ratio in the result. Full surface: [`/reference/cli/video`](/reference/cli/video).

## ralphy voice

Pre-flight checks against the ElevenLabs voice library. The single most common mid-batch failure is a deleted voice ID; the `exists` verb catches it before the batch commits.

```bash
ralphy voice exists pNInz6obpgDQGcFmaJgB    # 200 + metadata or hard exit
ralphy voice list                            # the user's library + clones
```

Full surface: [`/reference/cli/voice`](/reference/cli/voice).

## The render → eval → publish loop

```bash
ralphy editor preflight demo-001
ralphy render demo-001 --loudnorm
ralphy eval video .ralphy/workspaces/<ws>/projects/demo-001/render/final.mp4
```

`eval` is the quality gate after the render; see [Eval and research](/cli/eval-research). When eval flags issues, the agent regenerates the offending slots and re-runs `render` — iterations are CLI-native.

## Related

- [Rendering a project](/working/rendering) — the end-to-end walkthrough
- [Generation verbs](/cli/generation-verbs) — what feeds into the render
- [Eval and research](/cli/eval-research) — post-render QA
- [Editor playbook](https://github.com/alecs5am/ralphy/blob/main/docs/playbooks/editor.md), [HyperFrames playbook](https://github.com/alecs5am/ralphy/blob/main/docs/playbooks/hyperframes.md)
- [cli/commands/render.ts](https://github.com/alecs5am/ralphy/blob/main/cli/commands/render.ts), [cli/commands/editor.ts](https://github.com/alecs5am/ralphy/blob/main/cli/commands/editor.ts)
