Most upscaling tutorials tell you to enlarge first. Do that and the model learns the compression blocks and enlarges them too, which is how you get a 4K file that looks worse than the 540p original.
I built a browser upscaler while trying to rescue footage from an old phone, so this order is the one that survived testing rather than the one that reads well.
The order that works
Denoise → enlarge ≤ 2× → inspect at 100% → grade.
Four steps, and each one fails differently when skipped.
Denoise first. Compression does not add random noise, it adds regular blocks. Random grain is a property of the sensor; blocks are a property of the encoder. Feed blocks into an upscaler and you get larger, sharper blocks. Strip them first.
Cap at 2× per axis. Past 2× the model stops reconstructing and starts inventing. Faces go waxy, small text becomes meaningless strokes. On a 540p source, 2× is 1080p and that is where I stop.
Inspect at 100%. Not "looks fine at fit-to-window". 100% on the worst patch, specifically the hair edge and any text. If hair fuses into a solid mass, the denoise was too strong. If text resolves into nonsense, the enlargement was too far.
Grade last. Contrast on a blocky file makes the blocks more visible, so grading belongs after cleaning, not before.
Splitting anything over 30 seconds
The tool caps clips at 30 seconds. Cut at keyframes so the source is not re-encoded:
ffmpeg -ss 00:01:12 -to 00:01:38 -i input.mp4 -c copy damage.mp4 -c copy copies the bitstream instead of decoding it, so the cut is lossless. For batch work:
ffmpeg -i input.mp4 -c copy -f segment -segment_time 30 -reset_timestamps 1 seg-%03d.mp4 And join the results without a second encode:
printf "file '%s'\n" seg-*.mp4 > list.txt ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4 If segments drift out of sync, drop -c copy and encode once. Usually they do not, because -c copy preserves the original timestamps.
Three things that failed
Pushing 4K from a 480p source. The file got four times bigger and did not get sharper. Faces went plastic.
Denoising after upscaling. The blocks had already been enlarged, so the denoiser had four times the pixels of block edge to fight and smeared the real detail along with it.
One general model for everything. Night grain and anime line art need opposite treatment. A single model averages them and does neither well. Per-content presets are worth the extra complexity: the denoise strength and the edge handling are simply different problems.
Checking the result without fooling yourself
Three tests, in this order:
- Toggle the comparison at the same crop. If both versions look the same at 100%, the pass did nothing and the file is now larger for no reason.
- Look at the hair edge, not the face. Faces are forgiving because we expect faces to look smooth; hair falls apart first.
- Read small text if the frame has any. Text is the fastest tell between reconstruction and invention.
If all three are worse than the source, change the mode rather than increasing the strength. More strength mostly buys smoothing.
Where it still fails
Out-of-focus footage is gone. Nothing recovers detail the sensor never recorded, and every tool's marketing quietly promises otherwise. Motion blur from a whip pan is nearly as bad; the model cannot know which direction the frame moved.
If you are deciding whether to try: hold the original to your eye at 100%. If it looks like it could be sharpened into something, it can. If there is no edge structure at all, save the time.
The tool I built is UpgoLAB — browser-based, free during launch, no card. Photos up to 4 MP, clips up to 30 seconds. Eight modes, and the two worth knowing are Social Denoise for compression damage and Portrait Studio for faces; the rest are variations on how much edge you want.
Happy to answer questions about the pipeline, especially if you have a source type that breaks it.

