Build Reel Farm

KINDAreplaces $95/mosaves $1,140/yrback to the verdict

0%0 of 17 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 pipeline turning a topic into short-form video posts, where the interesting engineering is the render pipeline and caption timing, and the design constraints are that every output is labelled as synthetic and the posting rate is bounded by a constant you cannot raise at runtime.

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

SourcingContent from sources you record with a licenceRenderingffmpeg with a declarative scene descriptionCaptionsTimings derived from synthesised speech, never estimatedMarkingProvenance metadata embedded at render, plus platform disclosure on uploadPublishingA rate-limited queue against official APIs only

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 Orchestrates generation, rendering and publishing.

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

    Verify python3 --version prints 3.12 or higher

  2. installfree

    Why Rendering, and each platform has its own container, codec and aspect requirements.

    Get it Your package manager, then check each target platform's published encoding requirements. open ↗

    Verify A rendered file uploads to your target platform without re-encoding

  3. decidefree to read

    Why The EU transparency obligations have applied since 2 August 2026 with marking requirements following, and every platform has its own rule. The build enforces both, so you need to know what both say.

    Get it Read the transparency obligations for your jurisdiction and the synthetic content policy of every platform you will post to. Write down what each requires. open ↗

    Verify A written note states the marking and disclosure requirements per jurisdiction and platform

  4. free, but approval takes time

    Why Publishing through anything other than the official API violates the terms and removes accounts, and API access often needs review before it is granted.

    Get it Apply for developer access on one platform and read its rate limits and synthetic content requirements before building the publish path.

    Verify A test post publishes through the official API with the disclosure flag set

  5. have readyfree for your own work; a subscription for a stock library

    Why Volume turns one unlicensed image into hundreds of infringing posts, and the licence record is required before an asset can be used.

    Get it Assets you created, or a library whose licence explicitly permits commercial derivative use. Save the licence text with them.

    Verify Twenty assets exist, each with a licence record permitting your use

Data model

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

- topics(id, text, created_at)
- scripts(id, topic_id, body, model, generated_at, reviewed_at, reviewed_by) · nothing renders unreviewed
- assets(id, kind, path, source, licence_id, licence_allows_commercial, licence_allows_derivative)
- renders(id, script_id, scene_json, output_path, duration_ms, synthetic_marked, at)
- captions(render_id, ordinal, start_ms, end_ms, text) · from speech timings, never estimated
- posts(id, render_id, platform, account_id, disclosure_set, scheduled_for, posted_at, external_id, declined_reason)
- rate_state(platform, account_id, window_start, posted_count) · the cap, enforced in the publish path
- A render carries its synthetic marking as a stored fact, so a post whose render is unmarked cannot be published.

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
DAILY_POST_CAPrequired3Per account. Enforced as a constant in the publish path, not read from configuration at runtime.
REQUIRE_SCRIPT_APPROVALrequiredalwaysPresent as a constant so the answer is visible. There is no other value.
SYNTHETIC_MARKINGrequiredalwaysEmbedded at render. An unmarked file is unpublishable.
RENDER_DIRrequired./rendersOutput files, each carrying provenance metadata.
PLATFORM_API_KEYsecretrequireda platform-issued keyOfficial API only. Anything else violates the terms.
TTS_ENGINErequiredlocalProvides the word timings captions are built from. Estimation is not an option.

The build, in order

  1. Scripts a person has read

    Nothing reaches a render without a human having looked at it.

    1. Not in the interface. Interface gates get bypassed by scripts.

      Files src/render.py

    2. A slow review is a review that gets removed.

      Files src/review.py

    3. Both approvals and rejections. The rejections are the useful data.

      Files src/scripts.py

    done when · tick each as it passes
    watch out
    • A review step that is slow or tedious gets skipped by the person who added it, usually within a fortnight, and the tool reverts to publishing whatever the model produced. Make approving a good script take seconds, so the friction lands only on the ones that need attention.
  2. Assets you are allowed to use

    Every image and clip in an output has a recorded licence permitting it.

    1. Enforced at inclusion. Volume turns one mistake into hundreds.

      Files src/assets.py

    2. Different permissions. A licence allowing one may forbid the other.

      Files src/licences.py

    3. Model and prompt. Not an absent question, a different one.

      Files src/assets.py

    done when · tick each as it passes
    watch out
    • Pulling images from search results puts unlicensed photographs into published videos, and the volume this tool produces turns one mistake into hundreds of infringing posts before anyone notices. Require a licence record before an asset can be used, and treat a generated image as having a provenance question rather than no question.
  3. Rendering, with captions that stay in sync

    A video renders reproducibly and its captions match the speech.

    1. Reproducible. The same inputs must give the same file.

      Files src/render.py

    2. Never estimate. Estimation drifts within a minute.

      Files src/captions.pytests/test_sync.py

    3. Drift accumulates. The first ten seconds always look fine.

      Files tests/test_sync.py

    done when · tick each as it passes
    watch out
    • Estimating caption timing from word count and an assumed reading speed drifts audibly within the first minute, and by the end of a two minute video the captions are a full phrase behind. Take the timings from the speech synthesis itself, which knows exactly when each word was spoken.
  4. Marking, which is not optional

    Every output is machine readable as synthetic and discloses itself to a viewer.

    1. Machine readable, in the file. Not a database column.

      Files src/marking.py

    2. A separate obligation from the metadata. Both are required.

      Files src/publish.py

    3. Enforced where publishing happens, tested with a crafted unmarked file.

      Files src/publish.pytests/test_marking.py

    done when · tick each as it passes
    watch out
    • Treating the platform's disclosure toggle as sufficient misses the machine readable marking requirement, and treating the embedded metadata as sufficient misses the human disclosure. They are two separate obligations and you need both, so implement them as two checks rather than one setting.
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.