an.credits#
What a rendered video owes, and to whom.
an composes work it did not create into a video its user ships. Recording where
that work came from (an.ir.assets.AssetSource) is half the job; the other half
is being able to produce the credits, because **a licence recorded and never
displayed is not compliance** — it is a note to oneself.
So this module walks a project’s reachable assets and answers three questions a user actually has:
what third-party work is in this video?
may I ship it at all? (an#211 — material that is all rights reserved, used for private study only, is recognised and said LOUDLY: the report opens with it, and a render that uses it ends with a warning that it is not publishable);
what must I display, verbatim, to ship it?
is anything in here unverified?
The last is the one that matters most and is easiest to lose. An asset with no licence is reported as UNKNOWN, never as “nothing owed”: those are different answers, and collapsing them is exactly how an obligation goes missing.
Public domain (pd, public-domain, cc-pdm-1.0, cc0-*) is recognised as
nothing owed, and an environment’s planes may each carry their own source,
so a composite stage — a carved plate plus a CC0 prop — credits both. A
character’s (or prop’s) attachments may too (an#220): a figure composed from
parts carved out of several clips credits each clip, part by part.
Functions
|
Whether a source is the character factory's own stamp (an#236, an#251). |
|
Whether a descriptor's source was written by a generator rather than a person. |
|
Walk a project mall and gather every recorded |
|
Credits for the project at |
|
Credits for exactly the assets |
|
One entry per voice whose lines a render synthesized with a named provider (an#271). |
|
Warn, loudly, when |
Classes
|
Everything a project owes, split by whether we actually know. |
Exceptions
A render used material that is all rights reserved, private study only. |
- class an.credits.CreditsReport(entries=<factory>, conflicts=<factory>)[source]#
Bases:
objectEverything a project owes, split by whether we actually know.
- property commercial: bool#
Whether a COMMERCIAL video may contain everything here (publishable, and nothing non-commercial).
- conflicts: list[tuple[str, dict[str, Any]]]#
rights conflicts a library check-out carried (an#357) — a statement about some bytes freer than the one that binds them. Informative: the binding statement is already among the entries.
- Type:
(asset, conflict)
- property noncommercial: list[CreditEntry]#
fine in a personal or private video, never in a monetised, sponsored or client one. Flagged, never blocking.
- Type:
Entries for NON-COMMERCIAL use only (an#373)
- property owed: list[CreditEntry]#
Entries that definitely require an attribution (a non-commercial licence owes one too).
- property private: list[CreditEntry]#
all rights reserved, private study only (an#211). A video containing any of them is not shippable, whatever else it credits.
- Type:
Entries that may NOT be published
- property unverified: list[CreditEntry]#
Entries whose licence we could not classify.
Deliberately its own list rather than folded into
owed. Folding them in cries wolf; folding them into “nothing owed” hides a real obligation. Neither is honest, so they are counted separately — the same reasonpriv’s upkeep keepsunavailableapart fromfindings.
- exception an.credits.PrivateStudyWarning[source]#
Bases:
UserWarningA render used material that is all rights reserved, private study only.
Raised as a warning at the END of a render (an#211), so the last thing the author reads about the mp4 is that it must not be published.
- an.credits.collect_credits(mall, *, only=None)[source]#
Walk a project mall and gather every recorded
AssetSource.onlyrestricts the walk to thosestore/keynames (what a render used,credits_for_scene()) — nothing else is read.Four stores carry provenance: characters, props (an#108), environments (an#110) and sounds. Each was added by the PR that gave that store real art, which is the rule rather than a coincidence — a walk that skips a store holding third-party plates does not return less information, it returns an affirmative false statement to exactly the people who need the opposite. Sounds joined with the sound layer (an#163) — a sound is third-party work more often than any other asset. Styles will join when a StylePack has art (#112).
Legacy reconstruction runs on characters only: it recovers a DiceBear record from
metadata.dicebear_*, which no other store has ever written.- Return type:
- an.credits.credits_for_project(project_dir)[source]#
Credits for the project at
project_dir.- Return type:
- an.credits.credits_for_scene(mall, scene)[source]#
Credits for exactly the assets
scenedraws or plays (an#211).collect_credits()walks the whole project; a render owes only what it used, and a private-study plate sitting unused in the store must not make an unrelated render “not publishable”. Kept: every entry under astore/refsome shot’s entity names, and every sound a cue names.- Return type:
- an.credits.is_factory_stamp(raw)[source]#
Whether a source is the character factory’s own stamp (an#236, an#251).
The factory stamps every part it draws
cc0with the part’s digest, and the descriptor with itssource_svg’s, so the asset library can tell its shared parts from carved ones. It isan’s own work, not third-party: a credits report lists what is OWED, and listing fifty generated parts per character would bury the one carved head.- Return type:
- an.credits.is_generated_source(raw)[source]#
Whether a descriptor’s source was written by a generator rather than a person.
- Return type:
>>> is_generated_source({"provider": "dicebear", "license": "cc0-1.0"}) True >>> is_generated_source({"provider": "a-film", "license": "all-rights-reserved"}) False
- an.credits.speech_credits(mall, scene)[source]#
One entry per voice whose lines a render synthesized with a named provider (an#271).
Read from what the audio pipeline already keeps — no record of its own: the scene’s lines that carry an
audio_ref(stamped when synthesized), each line’s voice as the pipeline resolves it (an.audio.voices.line_voice_id()), and that voice’s document inmall["voices"](itsprovider,voice_idandmodel_id). A voice document may declare its ownsource(the provider’s terms, the licence the user holds); otherwise the speech is listed UNVERIFIED — the provider’s terms decide what is owed, and nobody recorded them. The licence that counts for synthesized speech is a provider-terms code (an.ir.assets.PROVIDER_TERMS:elevenlabs-paid-planisfree;elevenlabs-free-planisnoncommercial: it owes a credit and is flagged for commercial use, an#373), or any licenceanrecognises; it is read as the voice’s provider’s, so another provider’s terms count for nothing (an#307). A voice whose document names no provider (the offline default) is not listed: which provider spoke it is not recorded anywhere.- Return type:
list[CreditEntry]
>>> from types import SimpleNamespace as NS >>> line = NS(voice_ref="bob", speaker="bob", audio_ref="k1") >>> scene = NS(timeline=[NS(dialogue=[line], entities=[])]) >>> mall = {"voices": {"bob": {"provider": "elevenlabs", "voice_id": "TX3", ... "model_id": "eleven_v3"}}} >>> [(e.asset, e.license_class, e.source.extra["model"]) for e in speech_credits(mall, scene)] [('speech/bob', 'unknown', 'eleven_v3')] >>> mall["voices"]["bob"]["source"] = {"provider": "elevenlabs", "license": "elevenlabs-paid-plan"} >>> [e.license_class for e in speech_credits(mall, scene)] ['free']