Build Vyravid

KINDAreplaces $19.99/mosaves $239.88/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A local pipeline turning a script into a short video: synthetic voiceover with word timings, the script split into scenes, media assigned per scene from a library whose licences you recorded, captions generated from the real word timings rather than estimated, and a deterministic render you can re-run after a change.

estimated effort multi-daythe files for this build are in the project pack

Renderffmpeg driven by a filter graph built from the timelineRuntimePython 3.12 with SQLiteVoiceA speech engine that returns word-level timingsMediaA local library with licence recorded per assetTimelineScenes and clips as data, never a rendered intermediate

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the pipeline and builds the filter graph.

    Get it python.org or your package manager, then a virtual environment.

    Verify python3 --version prints 3.12 or higher

  2. installfree

    Why The render is one filter graph through it. A build missing an encoder fails at the last step.

    Get it brew install ffmpeg or your package manager. Confirm your target encoder is present. open ↗

    Verify ffmpeg -encoders lists your video and audio encoders

  3. API keylocal engines are free and slower; hosted ones are priced per character

    Why Captions and scene boundaries both derive from them, and estimated timings drift visibly within a minute.

    Get it Choose an engine that reports word-level timings, or plan a forced alignment step. Confirm the timings exist before building on them.

    Verify Generated speech comes with per-word start and end times

  4. have readyfree with openly licensed material

    Why A render is blocked on a licence mismatch by design, so material with unknown terms cannot be used at all.

    Get it Openly licensed libraries, material you created, or stock you have bought. Record the terms per asset as you import.

    Verify At least ten assets are imported with licences and check dates

  5. have readyfree

    Why Caption safe areas and legibility are only judgeable where the video will be watched, and a desktop player hides the platform interface that covers the edges.

    Get it Any phone. Play the export and watch for captions behind interface elements.

    Verify An export has been checked on a phone

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- projects(id, title, aspect, fps, created_at)
- scripts(id, project_id, text, version, created_at)
- scenes(id, project_id, ordinal, text, start_ms, end_ms, media_asset_id, effect_json)
- voice_words(scene_id, ordinal, word, start_ms, end_ms) · the spine captions and scene timing both use
- assets(id, path, kind, source, licence, commercial_use, attribution_required, checked_on)
- renders(id, project_id, settings_hash, output_path, rendered_at, duration_ms)
- provenance(project_id, note) · what was synthesised, recorded because it cannot be reconstructed
- Scene boundaries come from word timings rather than from a guess at reading speed, which is what keeps captions and cuts aligned.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
OUTPUT_DIRrequired./rendersWhere renders and reports are written. Never the source directory.
ASPECTrequired9:16Output aspect. Vertical for most short video destinations.
FPSrequired30Frame rate. Fixed per project so captions and cuts land on frames.
SCENE_MIN_MSrequired1800Shortest scene before merging with a neighbour.
SCENE_MAX_MSrequired7000Longest scene before splitting at an internal sentence boundary.
CAPTION_SAFE_MARGIN_PCTrequired12Margin from every edge, so captions clear platform interface elements.
DECLARED_USErequiredcommercialChecked against asset licences. A mismatch blocks the render.

The build, in order

  1. Voice with real word timings

    The voiceover exists and you know when every word was spoken.

    1. With word timings if the engine offers them, or align afterwards if it does not.

      Files src/voice.py

    2. The spine that scenes and captions both derive from.

      Files src/timings.py

    3. From the middle of a sentence. Estimated timings fail this immediately.

    done when · tick each as it passes
    watch out
    • Estimating word timings from a reading speed drifts, and by the end of a sixty second video the captions are a phrase behind. Get real timings, either from the speech engine or from a forced alignment pass, and check by playing one word from the middle.
  2. Scenes derived from the speech

    The script splits into scenes whose boundaries land at real pauses.

    1. Then take times from the word timings for those sentences.

      Files src/scenes.py

    2. Merge short scenes, split long ones at an internal boundary rather than arbitrarily.

      Files src/scenes.py

    3. Check three boundaries against the audio. A cut mid-word is the visible failure.

    done when · tick each as it passes
    watch out
    • Dividing the total duration by the number of scenes produces cuts in the middle of sentences, which reads as a mistake to a viewer even when they cannot say why. Take boundaries from the word timings, so a cut always lands in a gap between words.
  3. Media with its licence recorded

    Every clip has an answer to where it came from and what you may do with it.

    1. Source, terms, commercial use, attribution, check date. Not optional.

      Files src/assets.py

    2. Against the project's declared use. A warning gets clicked through.

      Files src/render.py

    3. Automatically, so the requirement is met by construction rather than by memory.

      Files src/attribution.py

    done when · tick each as it passes
    watch out
    • Recording the licence later never happens, and a video that did well is exactly when someone checks. Require it at import, block the render on a mismatch rather than warning, and collect attribution text automatically so the requirement is met rather than remembered.
  4. Captions from the timings you already have

    Captions appear exactly when the words are spoken and are readable.

    1. Maximum characters and minimum on-screen time. Two constraints, both needed.

      Files src/captions.py

    2. Margins from every edge. Verify on a phone, not in a desktop player.

      Files src/captions.py

    3. Not everyone wants burned captions, and the file is also an accessibility artefact.

      Files src/captions.py

    done when · tick each as it passes
    watch out
    • Burning captions into the frame without a safe area margin puts them behind the platform's own interface elements on a phone, where they are unreadable exactly where most people will watch. Keep a margin from every edge and check on a real device rather than in a desktop player.
  5. A render you can repeat

    The video renders from the timeline, and the same timeline renders the same video.

    1. Concatenation, overlays and audio in a single invocation.

      Files src/render.py

    2. Seeds and encoder settings, so two renders match byte for byte.

      Files tests/test_determinism.py

    3. With its settings hash. Overwriting loses the version someone already saw.

      Files src/renders.py

    done when · tick each as it passes
    watch out
    • Rendering scene by scene into intermediate files and concatenating them re-encodes the material twice and introduces a quality loss plus a seam at every join. Build one filter graph and render once, which is faster and better.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more ai video.