{"slug": "i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things", "title": "I shipped a second render engine to make preview match export. It made things worse.", "summary": "Katto, an AI video clipper built by a solo developer, introduced a second render engine using headless Chromium (Remotion) to make previews match exports, but it worsened drift and slowed exports to 3-4 minutes per clip. The developer reverted to a single FFmpeg pipeline, cutting export times to about 30 seconds and eliminating silent fallbacks, while keeping the browser Player as a preview only.", "body_md": "Katto is an AI video clipper. You drop in a long video, it cuts the good moments into vertical shorts, and an editor lets you fix the framing, captions and layout before you export. I build it on my own, in public. This is the story of a mistake I made in that editor, and what fixing it taught me about \"what you see is what you get.\"\n\nA clip editor lives or dies on one promise. What you see in the preview is exactly what you download. If the caption sits a pixel higher in the export, if the crop drifts, if a color is off, the user stops trusting the tool. And trust is the whole product.\n\nMy preview is a React composition rendered in the browser. My exports were rendered on the server with FFmpeg. Two different renderers drawing the same clip. They drifted, as you would expect. Caption fonts, emoji rendering, the exact crop on a split screen. The classic \"preview does not match export.\"\n\nSo I did the obvious thing. I made the same React composition that draws the browser preview also render the export on the server, through a headless Chromium (Remotion). One component, one source of truth. Preview equals export, guaranteed.\n\nThis is not a knock on Remotion. It is excellent at what it is built for. The mistake was mine. I bolted it on as a second export engine next to an existing FFmpeg pipeline.\n\nMy initial clips, the ones the AI generates before you ever open the editor, were still rendered by FFmpeg. It is fast, it is proven, it runs the whole pipeline. I was not going to rip that out.\n\nSo now I had two engines producing files. FFmpeg for the generated clip, Chromium and Remotion for the edited re-export. The exact divergence I set out to kill was now worse. The clip you saw in your results list (FFmpeg) and the same clip re-exported after a tiny edit (Remotion) could come out subtly different. I had turned one renderer into two and called it parity.\n\nOn top of that, the Chromium render was slow. Three to four minutes per clip, against roughly 30 seconds for FFmpeg. And it failed now and then. When it failed, it silently fell back to FFmpeg and handed the user a file with their edits quietly dropped. The worst possible failure. Wrong, and quiet.\n\n\"Preview equals export\" is not achieved by making the preview be the renderer. It is achieved by having one source of truth for the render, and letting the preview be a faithful approximation of it.\n\nA browser Player is a great preview. It should never have become a second export engine. The moment it did, I had two implementations of the same geometry, drifting on every change.\n\n**FFmpeg is the one engine that produces files.** Generation and re-export run through the same pipeline. Exports for a typical sub-60s clip dropped to about 30 seconds (I measured 32s), down from the three to four minutes the Chromium path took.\n\n**The browser Player is back to what it is good at,** the interactive preview. It renders nothing that ships.\n\n**I ported the flourishes only the browser could do** into FFmpeg, the per-word color-cycling captions and the stacked layout's adjustable split ratio, so the fast path covers the common cases.\n\n**The silent fallback is dead.** If a render cannot be produced faithfully, the user gets a visible error, never a quietly wrong file.\n\n**One coordinate set, the last piece I am finishing.** When you drag a crop in the preview, those exact rectangles should be what FFmpeg uses, not a second geometry the server recomputes on its own. This is the subtle one. Even after unifying the engine, the preview computed crop rects one way and the export computed them another. I am closing it now, making FFmpeg consume the exact rects from the editor state, because the lesson is the same one level down. Any second computation of the same thing is a source of drift.\n\n**\"Make the preview the renderer\" is seductive and usually wrong.** You end up with two renderers the day you have any other render path. One source of truth for the output. The preview approximates it.\n\n**A second engine \"for parity\" becomes a hidden third source of divergence.** If two code paths compute the same geometry or format, they will drift. The only question is when.\n\n**Silent fallbacks are the cardinal sin.** A slightly wrong file with no warning costs more trust than an honest error. Fail loud.\n\n**Verify the artifact, not the logs.** My logs said \"rendered stacked layout.\" I only found the real bug by pulling the actual exported MP4 off storage and looking at a frame. The pixels are the truth.\n\nI am a solo founder shipping fast, in public. This one cost me a well-intentioned detour. If you are building any editor with a preview and an export, the shortest path to trust is boring. One renderer, honest errors, and check the frames.\n\nKatto is at [katto.tech](https://katto.tech). If you build video tooling, I would genuinely love to compare notes on preview and export parity.", "url": "https://wpnews.pro/news/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things", "canonical_source": "https://dev.to/anthony_builds/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things-worse-23p0", "published_at": "2026-09-03 17:04:58+00:00", "updated_at": "2026-09-03 17:25:25.807804+00:00", "lang": "en", "topics": ["ai-products", "developer-tools", "generative-ai"], "entities": ["Katto", "Remotion", "FFmpeg", "Chromium"], "alternates": {"html": "https://wpnews.pro/news/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things", "markdown": "https://wpnews.pro/news/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things.md", "text": "https://wpnews.pro/news/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things.txt", "jsonld": "https://wpnews.pro/news/i-shipped-a-second-render-engine-to-make-preview-match-export-it-made-things.jsonld"}}