DEV Community

Alex Shev
Alex Shev

Posted on

Product Videos Should Be Build Artifacts, Not Manual Exports

Every product launch needs the same small pile of video assets:

  • a 16:9 demo clip for the launch page
  • a square cut for social
  • a GIF preview for the changelog
  • a poster image for email

The weird part is how often that still means opening a video editor by hand.

Someone updates the product copy. Someone swaps the screen recording. Someone exports a new MP4. Someone crops another version. Then two weeks later the same release video cannot be reproduced exactly because the editor timeline, font version, plugin state, or export preset drifted.

For product teams, that is the wrong abstraction.

The launch video should be closer to a build artifact.

Change the source. Open a PR. Let CI render the exact same video every time.

The useful idea: HTML as the video source

Most product launch videos are not cinema.

They are structured compositions:

  • headline
  • short subcopy
  • screen recording
  • background audio
  • a few transitions
  • a logo or CTA

That maps surprisingly well to HTML and CSS.

Instead of keeping the source of truth in a visual editor, the source can live in a normal index.html file:

<div
  id="stage"
  data-composition-id="release-2-4"
  data-start="0"
  data-width="1920"
  data-height="1080"
>
  <video
    data-start="0"
    data-duration="8"
    src="assets/screencast.mp4"
  ></video>

  <h1
    id="headline"
    data-start="1"
    data-duration="5"
  >
    v2.4 - Realtime Collaboration
  </h1>

  <p
    id="sub"
    data-start="2"
    data-duration="4"
  >
    Comment, mention, resolve - live.
  </p>

  <audio
    data-start="0"
    data-duration="8"
    data-volume="0.7"
    src="assets/bed.wav"
  ></audio>
</div>
Enter fullscreen mode Exit fullscreen mode

That one file now carries things a video editor usually hides:

  • canvas size
  • timing
  • copy
  • media references
  • animation hooks
  • composition id

And because it is text, it can be reviewed like any other product change.

The important part is deterministic rendering

Rendering HTML to video is only useful if the result is reproducible.

If a CI job renders a different file every time, the system is just another flaky media tool.

The better workflow is frame-seeking:

  1. Load the HTML composition in headless Chrome.
  2. Seek to each timestamp.
  3. Capture the frame.
  4. Encode the frames into MP4.
  5. Produce the same output from the same source.

That is the reason HyperFrames is interesting here. It treats HTML, CSS, media, and seekable animation as a renderable video composition.

Then FFmpeg handles the boring but necessary production work:

# master render
npx hyperframes lint
npx hyperframes render

# 1:1 social cut
ffmpeg -i out/release-2-4.mp4 \
  -vf "crop=1080:1080:420:0" \
  -c:a copy \
  out/release-2-4-square.mp4

# lightweight GIF for changelog
ffmpeg -i out/release-2-4.mp4 \
  -vf "fps=12,scale=640:-1:flags=lanczos" \
  out/release-2-4.gif

# poster frame for email
ffmpeg -ss 2 \
  -i out/release-2-4.mp4 \
  -frames:v 1 \
  out/release-2-4-poster.jpg
Enter fullscreen mode Exit fullscreen mode

One master render becomes every format the team needs.

Why CI is the right place for this

For a small SaaS team, the release note is already part of the engineering workflow.

The video can be too.

name: Render launch video

on:
  push:
    tags: ["v*"]

jobs:
  render:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"

      - run: sudo apt-get update && sudo apt-get install -y ffmpeg

      - working-directory: launch-video
        run: |
          npx hyperframes lint
          npx hyperframes render
          ffmpeg -i out/release-2-4.mp4 -vf "crop=1080:1080:420:0" -c:a copy out/square.mp4

      - uses: actions/upload-artifact@v4
        with:
          name: launch-video
          path: launch-video/out/*.mp4
Enter fullscreen mode Exit fullscreen mode

Now the video is attached to the release process:

  • copy changes are visible in PRs
  • timing changes are versioned
  • release tags regenerate the same artifacts
  • reviewers can inspect the rendered output
  • social cuts come from the same master file

The team is not replacing creative work with CI.

It is removing the repetitive export layer around a video that is mostly structured product information.

Where this fits

This works best for videos that are template-driven:

  • product launch clips
  • changelog videos
  • feature teasers
  • onboarding explainers
  • social demos
  • doc/video snippets

It is probably the wrong tool for a cinematic brand film.

But most weekly product videos are not cinematic. They are release communication.

And release communication should be repeatable.

The agent angle

The interesting part is what happens when an AI coding agent can edit the video source.

An agent can:

  • update the release copy
  • swap in a new screencast
  • adjust timing
  • add a maintained transition block
  • run the lint step
  • render the preview
  • post-process the output

That is much more useful than asking an AI tool to generate a random video from a prompt.

The agent is working inside the same system as the product team: files, PRs, CI, artifacts, and review.

That is where AI video automation starts to feel practical.

I wrote up the full workflow here:

https://terminalskills.io/use-cases/automate-product-videos-from-html

The short version:

If the video changes every release, put the video source next to the release.

Then let the build system render it.

Top comments (1)

Collapse
 
alexshev profile image
Alex Shev

Quick follow-up: I tested the same idea as a real social asset after publishing this.

The pipeline was:

  • use-case page screenshot
  • presenter still generated from the page context
  • Veo native dialogue for the short spoken line
  • Lyria music bed under the voice
  • HyperFrames overlays for the final vertical cut

The useful lesson was the same as the article: the creative layer still matters, but the repeatable export layer should become a build step. Once the source composition is structured, the same asset can be rendered, checked, resized, and shipped without reopening a manual editor every time.