I have a system that turns US public-domain archive material into original documentary video without a person in the loop. The part I would most want read is the licence check that decides whether an asset is allowed into the pipeline at all, and specifically the direction that check fails in. The rendering matters less.

Automated content generation from archive material has one obvious way to end badly: publishing something that is legally someone else's. Most systems in this space treat that as a review step. Somebody checks afterwards, or nobody does. Both scale badly, and the second one fails invisibly, because the absence of a rights problem looks exactly like the absence of anybody having looked.

Two directions of failure

Consider the same bug under two designs. An archive API changes its response shape and a licence field arrives as null instead of a string.

Under default-allow, an asset is usable because nothing said it was forbidden. The null reads as "no restriction found", the asset enters the pipeline, gets composited into a film, and the film is published. The failure surfaces weeks later as a message from a rights holder.

Under default-deny, an asset is usable only when provenance and licence have been affirmatively established. The null fails the check, the asset is rejected with a logged reason, and if nothing else qualifies, the run stops. The failure surfaces immediately as a job that did not produce a video.

Those are the same bug. One of them is a legal exposure discovered by someone else. The other is an empty output directory and a log line. Choosing which one you get is the design decision, and it is made once, in the shape of the check rather than in its contents.

This is why I describe rights in Archive Engineering as a structural property of the pipeline, a condition an asset must satisfy to enter, rather than a check applied to what came out.

What the gate does

An asset candidate has to clear four things before it is eligible for use.

Its source has to be in an allowed registry. Assets come only from archives that are public domain by origin: DVIDS, the US Department of Defense visual information service; NASA; and Archive.org.

The distinction between those three is the part that is easy to get wrong. DVIDS and NASA are safe by category. Works of the US federal government are public domain by statute, with documented exceptions the gate accounts for. Archive.org is not safe by category at all. It is a host, and it hosts material under many licences, so items from it are checked individually rather than assumed. Treating those two cases identically is the mistake that makes an "only public domain" claim untrue while sounding rigorous. You make it by writing a source allowlist and stopping there.

Licence fields have to be affirmatively present. "Not forbidden" does not count. The field has to be there, readable, and saying something.

Every downloaded asset is hashed with SHA-256, and the hash is recorded alongside its source, its licence determination and a timestamp in a rights ledger that travels in git. That makes provenance verifiable after the fact. Given a finished video, each piece of footage in it traces back to a specific archive record and a specific licence determination made at a specific time. If a rights question ever arises, the answer is a record, which is the difference between an afternoon and a problem.

Rejections at any of those four points are logged. That matters for the same reason it matters in a notification gate: a rule that fails silently is indistinguishable from a rule that is not running.

The other kind of republishing

Rights clearance stops the system republishing somebody else's work. It does nothing about the system republishing its own, which is the failure that destroys the value of an autonomous catalogue rather than its legality.

So a second ledger records everything the pipeline has ever produced, and candidate topics are checked against it on two axes. Exact comparison catches the same subject proposed again. Semantic comparison, using MiniLM sentence-embedding similarity, catches a subject too close to one already covered.

The second axis is the one that earns its place. Exact matching is defeated by rephrasing: "The Panama Canal Expansion" and "How Panama Widened Its Canal" are different strings and the same video. Embedding similarity catches the near-duplicate, and the near-duplicate is the case that degrades a catalogue, because nobody notices it as a bug. They just notice the channel has nothing new on it.

Both checks run at stage 2 of 13, immediately after topic selection and before any generation. That placement follows the same reasoning as the licence gate. Rejecting a duplicate at stage 2 costs an embedding comparison. Discovering it after script generation, narration, subtitles and a render costs the whole pipeline. The archive-availability check sits in topic selection for the same reason. A subject with no rights-clear footage is rejected before a script is written, because discovering that at the asset stage means throwing away work that has already been paid for.

Clearing rights on the inputs establishes that the pipeline is not stealing. It does not establish that the output is a work rather than a re-upload, and I think that distinction is where most "AI content pipeline" projects are weakest.

Three things push the output towards genuine authorship. Research and script are generated from primary source material: the system reads archive records, and it does not watch other people's documentaries about the subject. Editorial direction is generated per production, with a seeded PRNG choosing card type, placement, tone and timing, so two films about adjacent subjects do not share a visual grammar and turn into recognisable template output. And composition is treated as the product. Public-domain footage is raw material, while the narration, structure, information cards, scientific visualisations and pacing are authored, and that composition is what makes the result new.

The same reasoning drove the resolution decision. Output is 1440p with archive restoration enabled and generative upscaling switched off. Repairing detail that is present in historical footage is worth the render cost. Inventing detail that is not there is expensive, and for something claiming evidential accuracy it is arguably dishonest. A system whose value rests on being evidence-based should not fabricate visual detail, even flattering detail.

Licences apply to your dependencies too

The build-versus-buy roadmap for this project records a decision per layer with licence analysis attached, and the row I would point at is the finishing layer. One referenced project that solved part of it is AGPL. Vendoring an AGPL library into a system that produces published output creates an obligation most people building this kind of pipeline never think about. Reading the licence and reimplementing the technique instead cost time and removed a risk that would otherwise have been discovered far too late. It is the same trade as the rights gate, applied to the codebase rather than the footage.

There is a related decision about where the rules live. The pipeline splits into a thin orchestrator and a thick runner. n8n does only cron, HTTP, branching and looping, and every piece of state and all heavy compute lives in a FastAPI service. I made that split deliberately, and it is the decision in the project I would most want to be questioned about. Workflow orchestrators are attractive because they make a pipeline visible, and dangerous because they make it easy to put state and logic inside a tool you cannot unit-test, version meaningfully, or leave. A default-deny licence check that lived inside an orchestrator's UI would be a rule I could not test and could not read in a diff. Keeping n8n to control flow means the whole system stays an ordinary Python codebase.

What this is evidence of

I would not offer this project as a video pipeline. Video pipelines are common. I would offer it as evidence of a habit: when a system has a constraint that is expensive to violate, the constraint belongs in the architecture, upstream of any review step.

The numbers, for what they are worth. There are thirteen stages, of which eleven were timed on a real production run rather than estimated, on a single 16 GB Mac with sequential execution and no CPU contention. Those figures are only valid under that condition. The network-bound stages among them are given as ranges rather than single figures, because one measurement of a network operation is not a measurement of anything. There are two card-rendering stages and it is worth keeping them apart. The per-frame information cards at stage 10 take 101 seconds, and the Manim scientific visualisations at stage 11 take five. The first is the bottleneck, roughly a third of the local compute budget, and more than speech synthesis, transcription and the Manim stage combined. It was not my suspect before I measured. Speech synthesis was, because it feels expensive, and it takes 34 seconds. 25 design specifications are committed alongside the code. And 257 of the 289 commits are mine; the remaining 31 were made by AI coding tools working under my direction, which I would rather state plainly than have somebody notice in a log.

The same instinct produced the delivery gate in LILA: one enforcement point, ordered checks, every rejection logged. Different domain, same conviction. The important rule is the one the system cannot accidentally skip.


Full write-up, including the stage timings and the orchestration split: Archive Engineering.