Skip to content
Huy Vo
Side projects

Side project · R&D · Automated 9:16 product-review videos

Review video pipeline

A local pipeline that turns a script, real product photos and a music track into a finished vertical review video, gated by automated checks.

Rendered output

Role
Solo: research, pipeline, QC suite
Year
2026
Platforms
CLI
Stack
  • Python
  • Pillow
  • NumPy
  • ffmpeg
  • VieNeu-TTS
  • bash

Short review videos are repetitive to make by hand, and most automated ones look cheap or invent facts. How far can a small local pipeline go if product pixels come from real photos and every on-screen claim has a source?

My part. All of it: the research report, about 7,200 lines of Python for the audio, render and QC layers, and the docs.

At a glance

  • 25+

    automated checks on every finished file

    Source: QC suite

  • −14 LUFS

    loudness target, −1 dBTP true peak

    Source: audio QC

  • 18

    on-screen claims mapped to a source

    Source: claims audit

What I built

Script and template as the only truth

Beats, voice lines, number cards and colours live in a script file; every layout, timing and motion constant lives in a template. A new video is a new script, not new code.

Three frames of the finished video side by side: a 'LIGHTFORCE' card over a switch cutaway, '44.000 DPI' over the HERO 2 sensor chip, and a '2.590.000đ' price card over the mouse underside with its subtitle.

Audio that lands on the beat

Music sits on a bar grid, cuts snap to a beat within 80 ms, effects align on their peak, then ducking and two-pass loudness normalisation.

Five consecutive moments of one subtitle line, 'Chỗ trừ điểm nặng nhất là polling rate.', with the highlighted word moving from the first word to the last.

Frames drawn in code

Pillow draws every frame and pipes raw RGB into ffmpeg: product cut-out over a background plate that pans the other way for a 2.5D move, light sweep, grain and karaoke subtitles inside safe areas.

Key decisions

  1. A check is trusted only after it fails

    Every QC check has a negative control that breaks the video on purpose and must be caught, and the build passes only on a fresh render.

    Problem, choice and trade-off: A check is trusted only after it fails
    Problem
    Automated QC said a video passed when the report was 3.5 hours older than the render, and a layout check measured text at the origin instead of where it was drawn.
    Choice
    Every QC check got a negative control that breaks the video on purpose (text pushed out of its band, a 4.5 s shot, a subtitle declared 120 px off) and must be caught; build.sh reruns QC on the fresh render and exits 0 only when all pass.
    Why
    A green report from a check that has never been seen to fail proves nothing, and a stale report is worse than none.
    Trade-off
    Builds are slower and the negative controls need maintaining whenever a layout rule changes.
  2. Speak one sentence, show another

    One TTS call per sentence for natural phrasing and hard sync points, with the spoken form mapped to clean on-screen numbers.

    Problem, choice and trade-off: Speak one sentence, show another
    Problem
    Vietnamese TTS reads numbers and units badly, and per-word timings from one long TTS call drifted from the subtitles.
    Choice
    One TTS call per sentence gives exact sentence boundaries; inside a sentence, word timings are spread by a character-weighted rule, and a mapping turns the spoken form into the displayed form ("một nghìn héc" → 1.000 Hz, "hai triệu năm chín" → 2.590.000đ).
    Why
    Sentence-level calls keep natural phrasing and give hard sync points without a forced aligner, and the viewer reads clean numbers while hearing natural speech.
    Trade-off
    Word-level karaoke timing is an estimate within each sentence, not true alignment.

Credit. Solo R&D, not a published ad. The demo reviews a Logitech mouse using Logitech's product photos for a technical demonstration only, with no affiliation. The full reference video also uses three short AI-generated clips; none appear on this page.

Next side project

Serene

Free anti-motion-sickness app