Skip to main content

The Render Pipeline

ViralSync's render pipeline distributes video rendering across multiple cloud workers using a scene-based execution model. This page explains each phase, what status and phase values you'll see in the API, and how to interpret timing.


Pipeline overview

POST /v1/render/jobs


┌─────────────┐
│ 1. Compile │ Parse movie JSON → create render plan
└──────┬──────┘

┌──────▼──────┐
│ 2. Dispatch │ Create one scene job per scene
└──────┬──────┘
│ (parallel)
┌──────▼──────────────────────────┐
│ 3. Execute (per scene) │ FFmpeg renders each scene → intermediate MP4
│ scene_001 scene_002 scene_003 │
└──────┬──────────────────────────┘
│ (all scenes complete)
┌──────▼──────┐
│ 4. Assemble │ FFmpeg concat → final video
└──────┬──────┘

┌──────▼──────┐
│ 5. Finalize │ Upload to R2, extract metadata
└──────┬──────┘

outputUrl available in job response

Phase details with API status mapping

PhasestatusphaseWhat's happening
CompilerunningplanningMovie JSON is parsed. Render plan written to render-plans/{jobId}/plan.json.
DispatchrunningdispatchingChild render.scene jobs created and queued.
ExecutewaitingrenderingScene workers running in parallel. Parent waits. Progress aggregated from child jobs.
AssemblerunningassemblingAll scene clips concatenated via FFmpeg concat.
FinalizerunninguploadingFinal MP4 uploaded to Cloudflare R2. Thumbnail extracted.
DonedoneoutputUrl is populated. Render minutes quota updated.
Failedfailederror field explains the failure. No render minutes consumed.

Scene parallelism and quality presets

The number of scene workers active simultaneously is controlled by the qualityPreset field in renderOptions:

PresetParallel scene workersWall-clock speedupBest for
stable2ModerateDebugging; predictable logging
balanced3GoodGeneral use (default)
fast4BetterShort videos (≤5 scenes)
turbo6BestLong videos on Business+ plans

Example: A 12-scene video on turbo preset starts 6 scene workers simultaneously. The first 6 scenes render in parallel; as each finishes, the next queued scene starts. Wall-clock time ≈ 2 × (time to render a single scene).

You can also override with requestedConcurrency (integer 1–32):

"renderOptions": { "requestedConcurrency": 5 }

Actual concurrency is always min(requestedConcurrency, sceneCount).


Timing expectations

These are approximate benchmarks for a 1080p video with typical media layers (video background + text overlays):

PhaseTypical duration
Compile< 1 second
Dispatch1–5 seconds
Scene render (per scene)~0.5–3× real-time (a 10s scene takes 5–30s)
Assemble~5–30 seconds (proportional to total video duration)
Upload3–15 seconds (depends on file size)

Total for a 10-scene, 5-second-per-scene video (50s total) on balanced preset:

  • Dispatch: ~3s
  • Scene render: ~4 rounds of parallel workers × ~10s per round = ~40s
  • Assemble + upload: ~20s
  • Total: ~60–80 seconds wall-clock time

Text-only scenes render significantly faster (~0.2× real-time). Video and image layers with transforms take longer.


Scene caching

If you re-render a movie where some scenes are unchanged, the renderer detects identical scene content and reuses the previously rendered intermediate clip — skipping those scene jobs entirely.

Caching is keyed on a deterministic hash of the scene's full content (layers, sources, timing, transforms). Any change to any layer property invalidates the cache for that scene only.

This means iterating on the end of a long video (editing scene 20 of 20) is much faster than re-rendering from scratch.


Storage locations

ArtifactLocation
Render planrender-plans/{jobId}/plan.json (internal R2)
Scene intermediatesintermediates/{jobId}/scene_{index}.mp4 (internal R2)
Final outputoutputs/{jobId}/output.mp4 (public R2, returned as outputUrl)

Scene intermediates are cleaned up after successful assembly. The final output URL is available for the duration defined by your plan's output retention policy.


Technical limits

ParameterLimitNotes
Scene job timeout30 minutesPer scene. Exceeded → RENDER_TIMEOUT error.
Assemble job timeout30 minutesFor the concat phase.
Max scenes per jobUnlimitedWorker pool scales dynamically.
Max scene parallelism32Hard cap; preset/plan limits apply below this.
Max video duration (Free/Pro)10 minutesPlan limit, not engine limit.
Max video duration (Business)20 minutes
Max video duration (Enterprise)120 minutes
Max resolution3840 × 2160 (4K)Enterprise. Plan-specific limits apply.
FPS range1–60Any integer value.

What happens when a scene fails

  1. The render.scene child job transitions to failed
  2. The parent render.movie job transitions to failed
  3. The error field on the parent job references the failed scene
  4. No partial output is produced; no render minutes are consumed
  5. Retry the parent job by submitting a new render job — cached scenes will not be re-rendered

See Error Reference → for SCENE_RENDER_FAILED, RENDER_TIMEOUT, and other render-specific error codes.