It started with a collegue asking me for a way to make some animations for a marketing site.
Let me remind you that both my daughers claim that I in no way should be allowed near crayons or anything that would allow me to draw a horse. I do text and I do code. I do not do graphics.
I wanted the same thing I want from code: version control, repeatability, and no mystery timeline hidden in some UI state.
Eventually, I found Remotion and to test it, I made a tiny intro video/animation.
What I wanted
The video used on this site lives in:
/assets/video/code-and-cadence-intro.mp4/assets/video/code-and-cadence-intro.webm
Both are rendered in 1920x1080 at 30 fps, around 5 seconds long.
Why both formats? Browser compatibility and filesize flexibility. mp4 (H.264) still works everywhere, and webm (VP9) is a good modern fallback/alternative.
Where the Remotion project lives
The source project is not inside this repo. It can be found at https://github.com/ovelindstrom/code-and-cadence-intro.
That project is a standard Remotion setup with:
src/index.tsregistering the rootsrc/Root.tsxexposing the compositionsrc/Composition.tsxcontaining the actual animation logic
Why Remotion works so well for this
The biggest win is that timing becomes code.
In my intro I use frame-driven transitions and a small word-cycle sequence:
const WORD_CYCLE: { word: string; frames: number }[] = [
{ word: "pedal", frames: 10 },
{ word: "code", frames: 10 },
{ word: "pedal", frames: 10 },
{ word: "code", frames: 22 },
];
Then each word is mounted using Sequence, and animated with interpolate() and easing curves. No manual keyframe dragging. No “why did this move by 3 pixels when I touched that layer” moments. ;)
The composition itself is declared explicitly:
<Composition
id="Intro"
component={Intro}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
/>
That means the duration math is predictable: $150 / 30 = 5$ seconds.
Render commands I use
Inside the Remotion project:
npm install
npm run dev
Preview in Remotion Studio first, tweak timings, then render. What I do like is that when (not if) I do something in the Remotion Studio to mess things up, it shows as a code change and I can revert it using my standard git commands.
The render command is intuitive using npx remotion render and then the Id of the composition that is being rendered. The default codec is mp4 so no more on that command.
If I want to render in .webm format, I just need to define the codec. The definition and codec id was very easy to find so cudos to all of you who writes the documentation for Remotion.
Render commands used:
# MP4 (H.264)
npx remotion render Intro ~/Projects/ovelindstrom.github.io/assets/video/code-and-cadence-intro.mp4
# WebM (VP9)
npx remotion render Intro ~/Projects/ovelindstrom.github.io/assets/video/code-and-cadence-intro.webm --codec=vp9
This drops the files directly into this site repo so they are ready to publish.
Embedding in the site
In HTML/Markdown pages, I use a regular video tag with both sources:
<video autoplay loop muted playsinline preload="metadata" width="100%">
<source src="/assets/video/code-and-cadence-intro.webm" type="video/webm" />
<source src="/assets/video/code-and-cadence-intro.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
And this is the same tag rendered in the post:
The muted + playsinline combo matters a lot if you want autoplay to work on mobile.
Things I learned
- Keep the first animation visible quickly. If your first meaningful frame appears too late, it feels broken.
- Do all timing decisions in frames. It is easier to reason about and easier to review. Also, feels more natural for a developer.
- Render to final paths when possible. It removes a lot of “where did I put that export” friction.
- Use two formats unless you really know your browser matrix.
Final words
For me, Remotion is not “video editing”.
It is UI animation engineering with a render step.
And that fits my brain better than any timeline tool I have tried.
