Topaz upscale
Give it a clip and a target width; get back the same clip at that width, with the same
frames and the same faces. Topaz's Proteus model enhances what the render already has
rather than generating new detail, so it is safe on people. It is a cost saver, not a
quality route: Seedance 2.5 renders at 720p in about 6 minutes against 6–30 minutes at
1080p, so 720p plus a 1.5× upscale is cheaper, but it softens fine detail. Use it only on
shots where quality matters less; when the whole frame ships at 1080p quality, render
at 1080p natively, and when only part of the frame is used, render that part's size and
don't upscale (guide-prepare-renders-for-delivery). It won't add what the render never
had: a soft or smeared take stays one.
Inputs
- The untrimmed render, straight from the model. Upscale before trimming
(
ffmpeg-frame-exact-trim), never after. - Its width (
ffprobe-inspect-media). Skip any clip already at the target width. - The target width: 1920 for a 16:9 delivery.
Run it
Call describe("fal/fal-ai/topaz/upscale/video") before the first run in a job and check
the fields below against it; they are the ones proven on real jobs.
run(
model="fal/fal-ai/topaz/upscale/video",
input={
"video_url": "<job>/video/raw/shot09_seedancei2v_j.mp4",
"upscale_factor": 1.5,
"model": "Proteus",
"H264_output": true
},
into="<job>/video/upscaled",
unit="shot09_seedancei2v_j"
)
video_urltakes the local path; the gateway uploads it.upscale_factoris target width / source width, rounded to 4 decimals (1920 / 1280 = 1.5).model:Proteus. Not SeedVR, which generates detail and changes faces.H264_output: truereturns H.264, which every later ffmpeg step reads.
The output's video is downloaded into into.
What you get
The clip at the target size. Put it where the take's name points
(shot09_seedancei2v_j.mp4) and keep the original beside it as
raw/shot09_seedancei2v_j_source.mp4, so a later round can go back to it. Record the
upscale (model, factor) in the take's notes.
Tips and traps
- Order: render, upscale, trim, grain. Trimming re-encodes; upscale the model's own output, then trim the upscaled file, then grain at delivery size if a texture note needs it.
- Rendering natively at 1080p skips this step, at the cost of the wait: on the first job, a wide shot's first round was 720p plus Topaz, came back soft with its logo illegible, and its second round rendered at 1080p directly.
Check it
- Size:
exec ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate -of csv=p=0 <out>gives the target size and the source's frame rate. - Frames: the frame count equals the source's
(
exec ffmpeg -v error -i <out> -map 0:v -f framemd5 -, counting lines that don't start with#). - Faces: crop a face at 100% from the same frame of the source and the upscale, and
look. Compare
python-measure-detailon that face between the two.


