Normative text · Working draft
Tórculo: a standard for films written as pliegos, version 1.0
The English text prevails if the two versions differ. BCP 14 keywords (MUST, MAY…) are marked.
- Status: Working Draft, 2026-10-15. Stable enough to implement; changes go through the
RFC process (
spec/rfcs/). The conformance suite inconformance/is part of this specification. - Editor: José Luis Saorín Ferrer.
- This version:
spec/SPEC.mdin https://github.com/joseluissaorin/torculo (private until the specification, the conformance suite and the reference implementations pass). - Spanish translation:
SPEC.es.md(faithful; in case of conflict the English text prevails). - License: this specification is published under CC BY 4.0. Code in the repository is MIT OR Apache-2.0. Contributors commit not to assert patents against implementations.
Abstract
Tórculo is an open standard for making films, explainers, animated shorts and moving
illustrations from a text that reads like the film. That text is a pliego, a .mesa
file written in the language of Tórculo: a line-oriented, Spanish-language script with
closed vocabularies, in which the author says what happens and how ("the stone rolls to
the edge, heavy") and the engine derives every number (positions, curves, durations,
colours, loudness). The standard has seven parts: the pliego language, the portable
project (.mesapack) with its voice sidecar, pieces (drawings, puppets, characters and
collage), the house canon (palette and deterministic randomness, with test vectors in
three languages), láminas (hand drawings revealed by a time atlas), materias (the
WGSL pass convention for paper, watercolour, risograph and transitions) and takes (the
recorded output of the engine, a fork of ManimGX, with its public API). Every part is
deterministic: the same inputs give the same film.
Status of this document
This is the first public version of the standard. Its language part absorbs and
reorganizes SPEC-MESA-2.md of manim-saorín (the working document of the reference
implementation, epoch 2 of the language); the other parts formalize documents that already
existed (pluma/LAMINA.md, materias/README.md, FORK.md, SPEC-PIEZAS.md). Where this
text and a conformance case disagree, the disagreement is a bug to be resolved through the
RFC process; until it is, implementations follow the conformance case. Known deviations of
the reference implementation from this text are listed in Appendix D and marked as pending
cases in the suite.
Contents
- Preface
- 1. Conventions and terminology
- 2. Architecture and conformance
- Part 1. The pliego language
- Part 2. 14. The portable project
- Part 3. 15. Pieces
- Part 4. 16. The canon
- Part 5. 17. Láminas
- Part 6. 18. Materias: the pass convention
- Part 7. 19. Takes and the public API
- 20. Security considerations
- 21. Privacy considerations
- 22. Versioning and compatibility
- 23. Media types and file identification
- 24. Internationalization
- Appendix A. Closed vocabularies
- Appendix B. Grammar
- Appendix C. Diagnostic codes
- Appendix D. Known deviations of the reference implementation
- Appendix E. References
- Appendix F. Profiles in development (informative)
Preface
A tórculo is the engraver's press. The plate is worked once and printed as many times as
needed. In this standard the plate is a pliego, a drawing or a materia, and the prints are
a video, a web page, an app or a game. The mesa is the work table where the pliego (the
sheet that goes through the press) is laid out: that is why pliegos keep the extension
.mesa.
The language was born inside manim-saorín, a collage-in-motion library on top of Manim,
for video essays with the look of a notebook: paper, ink that boils, cut-outs with tape,
risograph drums. Its first epoch (SPEC-MESA.md) grew as a changelog; the second
(SPEC-MESA-2.md, 2026-08) made it formal; the short film Radiointermisión (2026-10)
taught it posters, cameras, sound and a picture that listens. In parallel, Scholaris gave
the house its hand-drawing pen and its cream paper, and a fork of ManimGX (a Rust and wgpu
engine with the Python API of Manim) became the common engine: a film written in a pliego
that took about three and three quarter hours to render with Cairo renders in under eight
minutes on it. Tórculo is the name of that whole: the language, the formats around it, and
the engine they print with.
The language is Spanish by design. Its keywords are Spanish words read as Spanish
(la piedra rueda hasta el borde · pesado), diacritics distinguish words where Spanish
needs them (él is a character, el an article), and the engine's derivations encode a
craft (Lasseter's principles of animation, continuity editing, the print shop) rather
than parameters. This specification is written in English so that anyone can implement
it; every keyword is quoted as written in a pliego.
1. Conventions and terminology
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY and OPTIONAL are to be interpreted as described in BCP 14 (RFC 2119 and RFC 8174) when, and only when, they appear in capitals.
1.1 Terms
| Term | Meaning |
|---|---|
| pliego | A .mesa file: a script in the language of Tórculo. |
| servilleta | A pliego without any chapter head (==): plain prose (§5.12). |
| chapter (capítulo) | A unit of page and of rendering, opened by ==. Chapters MAY be rendered in parallel. |
| scene (escena) | A unit of world inside a chapter, opened by --; the world persists between its shots. |
| clip or beat | A unit of time (a shot), opened by *. |
| line | A unit of action inside a clip. |
| piece (pieza) | Anything placed on the table: a card, a label, a drawing, a puppet, a photograph, a sign. |
| bestiary (bestiario) | The project's catalogue of named pieces (PYTHON, PIEZAS). |
| compiler | A program that parses a pliego, checks it (§12) and produces its IR (§10). |
| interpreter | A program that turns an IR into frames and sound. The reference has two: ce (Manim Community Edition, Cairo) and gx (Tórculo's engine). |
| IR | The intermediate representation (guion rico), JSON (§10). |
| sidecar | <pliego>.tiempos.json: the voice's durations and word timings, and where its recordings are (§14.3). |
| take (toma) | A recording of an engine run as a stream of messages (.take, §19). |
| lámina | A hand drawing with a time atlas, ready to be revealed by any engine (§17). |
| materia | A compute pass over a plane (paper, watercolour, risograph…), in the convention of §18. |
| canon | The house's single source of truth: palette, randomness, craft numbers, foley weights (§16). |
| epoch (época) | The version of the language a pliego is written in (§22). |
1.2 Notation
Grammar productions use the EBNF of Appendix B (spec/gramatica/mesa.ebnf): names in
capitals are nonterminals, "literal" is literal text, [ ] optional, { } zero or more,
| alternative, TEXT the rest of the line, NL a line end, QUOTE a text between Latin
quotation marks. A nonterminal in capitals that the grammar does not define is a closed
vocabulary (§6, Appendix A); that correspondence is exhaustive.
In this document keywords are written with their accents, as they are read; comparison is by normalized form (§4.5).
1.3 Canonical JSON
Wherever this specification hashes or compares JSON, it uses the JSON Canonicalization
Scheme of RFC 8785 (JCS): object keys sorted by UTF-16 code units, no whitespace, numbers in
the shortest form that round-trips in ECMAScript notation (1.0 is 1, 1e-7 is
1e-7), strings in raw UTF-8 escaping only ", \ and U+0000 to U+001F. The reference
implementation is conformance/tools/jcs.py.
2. Architecture and conformance
2.1 The seven parts
| Part | Normative object | Version in Tórculo 1.0 |
|---|---|---|
| 1. Pliego language | the .mesa file, its compilation and its interpretation | epoch 2 |
| 2. Portable project | the .mesapack package and the voice sidecar | mesapack 1 |
| 3. Pieces | the piece contract (levels, card, parts, puppets, characters) | 1 |
| 4. Canon | palette, randomness, craft and foley numbers | canon 1 |
| 5. Láminas | the .lamina format | 1 |
| 6. Materias | the WGSL pass convention | 1 |
| 7. Takes and API | the .take stream of the fork and the engine's public interfaces | 0x8000_0002 |
Each part can be implemented on its own. A product claims conformance to a part and, where the part defines classes or profiles, to those classes and profiles.
2.2 Product classes
| Class | Part | Passes the suite's kinds |
|---|---|---|
| Compiler | 1 | vocabulario, lee, ir (normative projection, §10.6), cierre, espejo |
| Interpreter, per profile | 1 | huella and banda for the pliegos of its profiles (§8) |
| Packager | 2 | mesapack_referencia; its packages pass mesapack |
| Package reader | 2 | mesapack |
| Piece provider | 3 | the piece checks of §15.6 |
| Canon implementation | 4 | canon_azar and canon_paleta for its language |
| Lámina producer | 5 | lamina (byte-identical output) |
| Lámina reader | 5 | reveals every lámina of the suite as §17.5 says |
| Pass host | 6 | runs every conforming materia; materia for the checker |
| Take writer / reader | 7 | toma |
2.3 Conformance in general
A conforming product:
- MUST accept everything this specification declares valid for its class, and reject what it declares invalid, with the diagnostic codes of Appendix C where a code is defined;
- MUST NOT extend a closed vocabulary silently (§6.1);
- MUST be deterministic in the sense of §7.4 and §16.3;
- MUST pass every non-pending case of its class in the conformance suite of the same
version (
conformance/manifest.json); - SHOULD report its results in the report format of
conformance/README.md.
A compiler is not required to render: checking a pliego and producing its IR are conforming without any graphics engine.
Part 1. The pliego language
3. Principles
These principles are normative: they decide every question this text does not settle, and an RFC that breaks one of them MUST say so and why.
- The anti-parameter constitution. The pliego says human counts and manners; the engine sets the numbers. A pliego has no easing, keyframes, Bézier handles, rate functions, hexadecimal colours, per-piece shadows or loose durations in the plain dialect (§3.1). No new capability enters the language if it forces pliegos to say numbers that were previously derived.
- Closed vocabularies. The constitution only holds because every vocabulary is closed, and closed vocabularies are only bearable because the engine derives. A word outside its list is an error, never a silent extension.
- Closure. Writing out what the engine decided does not change the film (§11.1).
- Identity is the seed. Everything random is seeded from the identity of what it affects, computed from content, never from position, process, clock or file system (§7.4).
- What does not fit on the sheet is not read. Text that cannot be read in the time it is on screen is a defect (§12, the Lasseter review).
- Distance rules. The speed, colour and depth of every layer derive from its distance (lejanía) and from nothing else, with one declared exception (§7.7).
- The three seats. A capability that is not in the grammar, the compiler and the interpreter does not exist. A directive known to the vocabulary but not to the parser would be printed on screen as narration, which is the worst failure of the system; hence every nonterminal has its table (§6) and every event declares whether it is alive or reserved (§6.3).
- The law of authority. Documentation is enumerated from the parser, not from memory.
The vocabularies of Appendix A are extracted from the reference parser
(
spec/vocabularios/extrae.py) and the suite checks that they match (vocabulario).
3.1 The two dialects
| Dialect | Who writes it | Numbers |
|---|---|---|
| plain (pobre) | a person | none |
| revealed (revelado) | mesa escribe, transpilers, replica mode | yes, each decision marked (máquina) |
The plain share of a pliego is the fraction of its dramaturgy lines without figures. An
author's pliego SHOULD keep it at 85 % or more; a compiler MUST compute it and SHOULD warn
below 85 % (W112). Exempt from the count, each for its reason: section blocks (they
calibrate a craft, where numbers are legitimate), the body of a ver: (the data a
visualization draws), chapter titles, comments and the format line. Names of sound cues
and effects (for example 1M1) are names, not figures, and SHOULD NOT count (see
Appendix D).
4. Lexical structure
4.1 Encoding and lines
A pliego is UTF-8 without a byte order mark. Compilers MUST normalize it to NFC before
analysis. Lines end in LF or CRLF. Analysis is line oriented: each line is classified by
its prefix, and the prefix always wins. Only section blocks (§5.3) and dentro:
(§5.10) span several lines. Blank lines separate clips. Leading indentation is not
significant except inside section blocks and dentro:.
4.2 Comments, digressions and commissions
| Form | Meaning | In the IR |
|---|---|---|
// text | technical comment | no |
( text ) on its own line | author's digression | yes, digresiones |
~ deriva: text | a commission to the engine | yes, derivas |
4.3 The field separator
The middle dot · (U+00B7), with optional spaces around it, is the only field separator
inside a line.
4.4 Quotation
Text that goes on screen, and names that refer to text, are written between Latin
quotation marks «…» (U+00AB, U+00BB). Straight quotation marks are not equivalent and
MUST NOT be accepted in their place. A line that consists only of a quotation is a
shout (grito); a clip has at most one (E030).
4.5 Identifiers and normalization
An identifier is a sequence of letters (including accented letters and ñ), digits and
_. Section keys MAY contain spaces.
Keywords and vocabulary words are compared after this normalization:
- lower case;
- runs of spaces collapsed to one;
_is equivalent to a space (toca_la_trucaistoca la truca);- combining diacritics removed (NFD, drop U+0300 to U+036F): the canonical form has no
accents, and both forms are accepted (
ilustraciónisilustracion).
Exception: reserved words (§6.4) are compared as written, without normalization,
because in Spanish the diacritic distinguishes words: el is a reserved article and él
is a valid character name; likewise tu/tú, si/sí, mas/más.
Piece and drawing identifiers (id, bestiary names) SHOULD be ASCII: they are seeds
(§16.3), and an accent changes the seed.
4.6 Numbers
NUMBER is an integer or a decimal with a point, with an optional sign. Where the
language accepts a decimal comma it says so (2,39:1).
4.7 The (máquina) mark
A trailing (máquina) declares that the engine, not a person, took that decision. It
affects provenance fields of the IR (autor_cabecera, origen) and nothing else; in
particular it does not affect the master hash (§7.4).
4.8 The dash
The em dash — (U+2014) separates a head from its body in MOTIVO, PERSONAJE, ver:
and juntos:. Compilers MUST accept it with or without spaces on either side. The
canonical style, the one used in this document and in the suite, attaches it to the body,
as Spanish punctuation does with an opening dash: MOTIVO «error» —empieza como enemigo,
ver: votos —sí: 7 · no: 4, juntos: a · b · c —en fila. In dialogue, the dash that opens
a speech is part of the text (él: —¿Falta mucho?).
5. Grammar
The complete grammar is Appendix B. This section states the structure and the rules that the productions alone do not express.
5.1 The document
PLIEGO = PREAMBLE { CHAPTER } [ END ] ;
CHAPTER = CHAPTER-HEAD { UNIT-LINE | SECTION | COMMENT } { SCENE | CLIP } ;
SCENE = SCENE-HEAD { UNIT-LINE | SECTION | COMMENT } { CLIP } ;
CLIP = CLIP-HEAD { CLIP-LINE } ;The same set of unit lines is valid in the preamble, a chapter and a scene; sections are valid at the three levels. Inside a clip, lines are classified by prefix, the prefix always wins, and their order is kept.
5.2 The preamble
MESA [v N] TITLE opens a pliego and MAY declare the epoch (MESA v2 «El puerto»). A
pliego that declares an epoch newer than the compiler's MUST be rejected (E001).
formato declares properties: an aspect ratio (16:9, 4:3, 2,39:1), sala crema or
sala pizarra, tirada borrador or tirada definitiva, página desnuda (no folio, no
stamp, only paper) and en dos (everything drawn animated on twos).
REPARTO NAME: drum[, voice][, voice colour][, side][, alias: A · B] declares a speaker.
The cast is normative for dialogue: a speaker that is not declared in REPARTO or
PERSONAJE is not a speaker (§5.5). The voice colour is con radio or seca (E016
otherwise); the side is a la izquierda, a la derecha or al centro.
The preamble also carries the project's resources: PYTHON (or PIEZAS, Part 3) for the
bestiary, EFECTOS and BANDA for sound folders, MEZCLA for the mix, PARTITURA,
SOPORTE, LETRA, ARCHIVO, FANTASMA, RELOJES and SONIDO. Paths are relative to
the pliego's folder; in a portable project they MUST be (§14).
In epoch 2 the preamble line MUSICA path (song mode: the song leads the edit) and the
unit line MÚSICA cue (a cue of BANDA) share a keyword. A compiler MUST treat MÚSICA
followed by a name that exists in BANDA as a cue and any other MÚSICA line of the
preamble as a song, regardless of accents (RFC 0004; Appendix D).
5.3 Sections and the mirror law
SECTION = "#" NOMBRE-SECCION [ IDENT ] NL { SECTION-LINE } "#FIN" | NOMBRE-SECCION PATH ;A section block written inside the pliego is identical in grammar to the file imported in its place. Invariant (§11.2):
effective(p) == effective(parte(p)) == effective(funde(parte(p)))Keys of several words take a colon (por defecto: tijera) so that they survive the round
trip. Precedence, single and without exceptions, by partial inheritance (one line
overrides one line):
imported < inline in the preamble < chapter block < scene blockTALLER and MANO are normative (Appendix A: FAMILIA_TALLER, CLAVE_MANO); the
section BESTIARIO is equivalent to the preamble line PYTHON, and the section REPARTO
to the preamble lines REPARTO;
MONTAJE and CASCADA are reserved (§6.3).
5.4 Chapters and scenes
== TITLE · attributes ==== opens a chapter. Attributes: tensión (a TENSION), nº,
tambor, gigante, plano fijo (a PLANTILLA, not a shot size), tramo a → b,
nocturno, diurno.
-- TITLE [· HORA] -- opens a scene. Core unit lines:
EJE de A a B: the 180-degree rule. From it derive each one's side, the direction of looks and where someone who left by one side enters again.LUZ direction · hardness [· rasante]: one per scene; it governs all shadows. No piece declares its own shadow.MUNDO movement [N] · direction: the world clock (§7.7).FONDO key · distanceandDELANTE key [· distance] [· cada N]: multi-plane background and the proscenium; speed, colour and depth derive from the distance.ESCENARIO,TABLAS(the paper theatre as a still set; the hour tints, it does not dim; whoever has feet stands on the floor),ARCHIVO,REPITE «scene»(the same clips with the same identities: the same video).
Unit lines in the preamble apply to the whole pliego; in a chapter or a scene, to it. The scene prevails over the chapter and the chapter over the preamble.
5.5 Clips
CLIP-HEAD = "*" [ BEAT-ID ] ( FUNCION | SHOT ) [ "·" AFECTO ] [ "(máquina)" ] ;
SHOT = { TALLA | ALTURA | FRENTE | MODO } [ "de" [ ARTICLE ] IDENT ] ;Two languages, both legitimate: a dramaturgical function (* prueba · seco), from
which the composition template derives (§6.5), or a shot (* corto contrapicado de tercero · nervioso), which declares a shot size. They are two axes (§6.5). The article of
the subject is dropped (general de la carretera has subject carretera). An optional
beat id (* r01_02 primer de LOCUTOR · …) gives the clip a stable identifier, the one the
sidecar uses.
Content lines: di: TEXT is the narration and the score of the beat: its delivery
gives the beat's duration. SPEAKER: TEXT is dialogue; the speaker MUST be declared and
MUST NOT be a reserved word (E021); directives are resolved first, so a speaker named
like a directive cannot capture it. SPEAKER / SPEAKER: … is a sentence split between two
voices. letrero (register): TEXT is a sign (REGISTRO_LETRERO; unknown: E014;
reserved: W111). terminal:, canta: and plain prose complete the content lines.
5.6 Pieces and placement
pon: TYPE «text» · attributes places a piece of a TIPO-PIEZA; foto:, recorte:,
prensada: place archive material; ver: KEY —body a visualization of the CLAVE_VIS
catalogue, whose body is data; pica:; python: NAME args a bestiary piece (Part 3);
arriba:, pie:, nota:; marca: GESTURE «text» (GESTO_MARCA).
The law of the body: almost nothing goes in coordinates. Placement is relational:
en los pies de primero:, bajo «X» a 0.42:, junto a, delante de, detrás de,
juntos: a · b · c —disposition, en el mundo:, en el documento:, and the prefixes of
the profiles (en MATERIA:, de «A» a «B»:, a la izquierda:, a distance, en silueta:). Prefixes chain, and chain with al decir «…»:. The size of a drawing follows a
· (grande, enorme, gigante, a sangre).
clip: path [de mm:ss a mm:ss] places real video, a live cut-out whose sound joins the mix
at its exact time. A clip lasts what it says it lasts: a beat MUST NOT close while one
of its clips is still running; the beat grows instead (W123 says by how much). > espera al clip gives the clip the whole turn: the narration sounds first, then a breath, then
the clip, and the subtitle band withdraws while it runs. Reality is not developed: a
real-video clip never goes through the darkroom (no halftone, duotone or scissor die).
5.7 Movement
MOVEMENT = [ PLACEMENT ] [ ARTICLE ] SUBJECT VERB [ DESTINATION ]
{ "·" ( [ "por" ] TRAYECTO | MANERA | GRANULADO | REGISTRO-MOV | RASTRO ) } [ WINDOW ] ;A movement is recognized by its verb (VERBO_MOV, VERBO_RELACIONAL), never by its
suffixes. Otherwise la piedra rueda hasta el borde, with no suffix, would fall to prose
and be printed as narration (§3, principle 7). After a · in a movement line only a path,
manner, grain, register, trail or window is valid; anything else is an error (E012).
Relational verbs create a live binding that dies with its target; a cycle of bindings,
a chain of more than three links, or nesting deeper than three levels is an error
(E032).
The law of movement: the curve is never declared; it is derived from the material, the hand, the affect and the manner (§7.6).
Life verbs. A character or a puppet also turns, sits and looks, in plain words:
X se gira, X se da la vuelta, X se vuelve hacia la cámara, X se pone de frente | de perfil, X se vuelve de espaldas; X se sienta | se levanta | se inclina | se yergue | se asoma a la barandilla | se apoya en la barandilla; X asiente | niega | se encoge de hombros | se rasca la cabeza; X se acerca (walks towards the camera and grows on its
feet), X se aleja; X mira a «Y» (head and eyes towards another piece until the next
beat); X se queda quieto (only breathes). All of them can be anchored (al decir «gol»: X se asoma a la barandilla). Without quotes, A mira a B is both the look acted by
the piece and the eyeline of cinema (§5.8, W103); a compiler MUST keep both meanings.
5.8 Camera, cinema and journey
la truca ORDER [IDENT] [en SIZE] moves the rostrum (ORDEN_TRUCA); A mira a B (also
to someone off frame); A sale|entra por la SIDE; sonido: adelanta|retiene|dentro|fuera
(J and L cuts); fuera de campo: TEXT; el foco en X, el foco pasa a X, todo en foco
(focus is ink density, edge sharpness and shadow, never blur); X está STATE (a state for
continuity). The journey: X viaja, X se apea, el mundo MOVEMENT, por la ventanilla: … desfilan.
5.9 Events
EVENT = ">" EVENT-NAME [ ARG ] { "·" ">" EVENT-NAME [ ARG ] } ;Event names are a closed vocabulary with state (§6.3). An event written in a clip acts at
its place in the author's order and can be anchored to the voice (al decir «GOL»: > temblor). A transition written in a clip says how the clip enters; funde a negro
and funde a blanco say how it leaves. Four events are also copied to a field of the
clip because another pass reads them (EVENTO_A_CAMPO): salta and cruza el eje (the
escapes of the continuity warnings), congela and continúa.
5.10 Nesting and concurrency
dentro: opens sub-clips (at most three levels); mientras: opens a parallel track;
al decir «w»: LINE anchors a line to the moment the voice says w; LINE hasta decir «w» stretches it until then. Anchors are written as written, not as they sound; a
compiler with the sidecar matches figures with their reading (1154 and «mil ciento
cincuenta y cuatro») and approximate transcriptions by edit distance, and warns of anchors
that never match (W120) or that match the voice but not the text (W122).
5.11 The end
== FIN === closes the film; the lines after it are its colophon; > silencio N its final
silence (without it the compiler applies 3 seconds and warns, W113).
5.12 The servilleta
A pliego without any == is prose: every sentence is a clip and the dramaturge (fixed
rules, no machine learning) decides the rest. It is the entry point and MUST always work:
every compiler and every interpreter of the core profile MUST accept a servilleta,
including one with a preamble that declares its sound (BANDA, MÚSICA, AMBIENTE).
6. Closed vocabularies
6.1 The law
If a word is not in its list, it is an error, not a silent extension. Every
nonterminal of the grammar that the grammar does not define is a closed vocabulary listed
in Appendix A, with the structure of the reference parser it is extracted from and the
profile it belongs to. Appendix A is generated (spec/vocabularios/vocabularios.json); a
compiler MUST accept exactly those words for the epoch it implements, compared after
normalization (§4.5), and MUST reject any other word in a closed position with the code
of that position (Appendix C).
The vocabularies of an epoch are frozen: a later version of a compiler MUST NOT reject a word the epoch declared, including reserved words (§6.3). New words enter only through an RFC and are available to pliegos that declare the epoch that introduced them.
A compiler accepts the whole language. Profiles (§8) say what an interpreter realizes; they never restrict what a compiler accepts. A compiler MUST NOT reject a word of any profile because a particular interpreter does not realize it.
6.2 Overview
Appendix A lists 98 vocabularies (1015 words in total in this version). The most used:
| Vocabulary | Words | Notes |
|---|---|---|
AFECTO | 8 | contenido, eufórico, exhausto, juguetón, nervioso, seco, sereno, solemne |
FUNCION | 11 | apertura, cartel, contrapunto, digresión, eco, giro, ilustración, prueba, remate, respiro, tesis |
TENSION | 4 | sube, mantiene, cae, rompe |
ARCO | 6 | espiral, letanía, pregunta→respuesta, ruina, tesis→antítesis→síntesis, viaje y vuelta |
TALLA | 7, ordered | general, conjunto, medio, americano, corto, primer, detalle |
ALTURA, FRENTE, MODO | 5, 5, 3 | the other axes of a shot |
PLANTILLA | 8 | documento, primerísimo, general, mapa, contraplano, orla, nocturno, cartel |
VERBO_MOV | 24 | baja, cae, camina, corre, cruza, entra, esquiva, flota, gira… |
VERBO_RELACIONAL | 11 | agarra, alcanza, arrastra, cuelga, empuja, esquiva, huye, orbita, se apoya, sigue, suelta |
TRAYECTO, MANERA, GRANULADO | 16, 15, 4 | paths, manners and grains of a movement |
EVENTO | 163 | events of every profile, each with its state (§6.3) |
LEJANIA | 8, ordered | al pie, al paso, cerca, a media distancia, lejos, al fondo, en el horizonte, en el cielo |
CLAVE_VIS | 68 | the catalogue of ver: |
TAMBOR | 7 | ámbar, bermellón, naranja, rosa, ultramar, verde, violeta |
PALABRA_RESERVADA | 76 | §6.4 |
Ordered vocabularies (TALLA, LEJANIA, DISTANCIA, CADENCIA, INTENSIDAD,
SOPORTE) carry meaning in their order: the distance between two shot sizes is their
number of steps, an intensity is a level from 0 to 10.
6.3 State: alive and reserved
Every event, and every section name, declares a state:
- alive (vivo): the compiler or the interpreter consumes it;
- reserved (reservado): the language accepts it and the interpreter does nothing yet.
It is frozen vocabulary: writing it today does not break tomorrow. A compiler MUST accept
it and SHOULD warn (
W110).
In this version every event is alive. The sections MONTAJE and CASCADA and the sign
registers máquina, dymo and tira (REGISTRO_LETRERO_RESERVADO) are reserved.
6.4 Reserved words
PALABRA_RESERVADA lists the words that open a line in the parser plus articles and
prepositions. They MUST NOT be the name of a speaker or an identifier (E021), and they
are compared without normalization (§4.5): él is not el.
6.5 Templates and shot sizes are two axes
A shot size (TALLA) says how much of the frame the subject occupies. A template
(PLANTILLA) says where the pieces fall on the sheet. They share one word, general, and
primerísimo is not primer. Consequences:
PLANO_DEmaps functions to templates, not to sizes:Function Template apertura orla remate, giro primerísimo respiro general ilustración, contrapunto contraplano digresión mapa tesis, prueba, eco documento cartel cartel The size-jump warning (
W102) is only evaluated between two consecutive shots that both declare a size.plano fijotakes a template.
6.6 Piece types and substrates
TIPO-PIEZA (what pon: accepts: cartulina, dymo, mano, python, rescate, sello, texto,
tira, and apunte) is a dramaturgical role; SUSTRATO (14: papel, tira, cartulina,
postit, vegetal, acetato, foto, periódico, pijama, milimetrado, kraft, dymo, ficha,
polaroid) is a physical property (base colour, opacity, shadow, foley when it lands).
Every type resolves to a substrate (rescate, texto and mano to papel, sello to
cartulina, and the homonyms to themselves); the substrates that are not types are
reached from the workshop (materia NAME) or from the bestiary, not from pon:.
7. Semantics
7.1 Units and strata
PLIEGO
└─ CHAPTER unit of page and of rendering (rendered in parallel)
└─ SCENE unit of world (the world persists between shots)
└─ CLIP unit of time: a beat, a shot
└─ LINE unit of actionBecause chapters MAY be rendered in separate processes, continuity between them is
serialized data (estado_entrada, §10.4), never live objects.
| Stratum | Lives | Space | z band | Composed by the resolver |
|---|---|---|---|---|
FONDO | per sequence | table space | −60 to −30 | no |
MUNDO | until exit or curtain | floor, marks, bindings | −20 to 0 | no (relational) |
DOCUMENTO | per sentence | zones and slots, with reservation | 1 to 100 | yes |
PROSCENIO | while it crosses | table space | 101 to 200 | no |
ANOTACIÓN | with its target | the target | 9000 and above | no |
The proscenium (what is between the camera and the scene) goes above the document,
otherwise any card would be drawn over it and occlusion would not occlude, and below the
annotation, because a subtitle is not in the room: it is on the film. Membership is
inferred from the kind of piece and corrected with a word (en el mundo:, en el documento:).
7.2 The five laws
- The anti-parameter constitution (§3).
- Closure (§11.1).
- Identity is the seed (§7.4).
- What does not fit on the sheet is not read.
- Distance rules over speed, colour and depth of every stratum (§7.7).
7.3 Precedence
Every decision of the engine has a dimension and an ordered list of authorities; the first
authority that has a value wins. Every decider returns a value and its reason, or
nothing; the reason is mandatory by signature. Authorities are a closed vocabulary
(AUTORIDAD, 34 words).
| Dimension | Order of authority (left wins) |
|---|---|
| place | hand, binding, body, slot, composer, seed |
| z | stratum, proscenium, arrival |
| size | declared, hand, identity, paper, legibility |
| time | score, window, cap, gesture |
| background | order of the hand, scene, chapter, character |
| stratum speed | distance, order of the world |
| stratum colour | distance, archive, palette |
| curve | manner, material, hand, affect |
| shadow | light (the scene says it, never the piece) |
| name | exact, alias, exact text, fuzzy text |
Two candidates that tie at the same level of the name dimension are an ambiguity and an
error (E020). The presence of a field in the IR is the signal of authority (§10.5):
an explanation tool (mesa por-que) reads exactly that, so its explanation cannot diverge
from the render.
7.4 Identity, seed and determinism
Identity is the declared path (id portada/fabula) or the derived path
(chapter/scene/text). It is computed from content, never from position; an index
#n only breaks ties between literally identical pieces, locally.
Seed:
seed(piece) = H(identity) ⊕ H(take)where H is the canon's seed function (FNV-1a 32 over UTF-8, §16.3) and take is the
interpretation number (--toma N). Identity governs what must always look the same; the
take governs the material: --toma 3 gives another interpretation of the same film (same
shots, same duration, different material).
Forbidden seeds: no seed may depend on rendering or creation order, object addresses, the process, the clock or the file system.
The master hash is computed over the stripped, canonicalized pliego: spaces
normalized, comments and digressions removed, sections resolved, (máquina) marks
removed. Writing a pliego back (escribe) does not change its seed.
The determinism contract. Two runs produce the same film when these five inputs
coincide: (1) the canonicalized pliego, (2) the take number, (3) the engine version,
(4) the bestiary and the imported sections, (5) the voice sidecar. The sidecar is part of
the contract, not metadata: its hash and metodo per beat are inputs. A golden
fingerprint (§13.4) is valid for one set of the five inputs on one machine and GPU; across GPUs the fingerprint is compared with tolerance. A pliego used as a golden
reference MUST declare tirada definitiva and fix its take.
7.5 Time
One beat, one clock. Every beat has a duration before rendering: from the voice
(di: and dialogue, through the sidecar, §14.3), from > dura N, from its clips
(a beat does not close while a clip runs, §5.6) or synthetic (reading time of its text,
§16.4). There is no free regime.
The score (al decir «w»:) is the first authority of time. Every action has a window;
mientras: opens a parallel track; hasta decir stretches; the cap prevents an action
from eating the turn of the next. Two actions on the same subject in the same window are
an error (E031). Movement persists across a cut unless > congela.
7.6 Movement and the craft
The curve of every movement is derived; the pliego never declares it. The principles of
Lasseter (1987) are the default behaviour of every movement verb, with the numbers of the
canon (oficio, §16.4):
| Principle | What the interpreter does | Modulated by |
|---|---|---|
| slow in, slow out | the derived curve is eased at both ends; it is never linear | the manner (de golpe keeps the abruptness) |
| anticipation | moves back along its path before leaving, in proportion to speed | con anticipación forces it; de golpe removes it |
| arcs | without a path the verb decides (salta in an arc, vuela in a curve, cae falling); otherwise a gentle upward arc; nothing leaves the sheet on the way | a written path prevails; recto is straight |
| squash and stretch | stretches along the motion keeping its area; squashes on landing | speed and material (rigid gives half) |
| follow-through | overshoots and settles; leans against the motion | mass, bounce and sway |
| overlapping action | the parts of a group leave staggered, as damped springs; never more than simultaneos_maximos moving at once | |
| timing | duration from distance and manner, never under fotogramas_minimos | the manner |
| moving hold | what has moved breathes (a seeded minimal drift): never a frozen frame | > deja posar lengthens it |
| exaggeration | every factor × exageracion | the canon |
On twos: en dos animates drawn things at half the frame rate with held poses; it is
a suffix of a movement or a property of the whole pliego. Real video, boil and updaters
stay on ones.
Secondary motion (drag, bounce, sway) is a property of the material and is never
declared in the pliego. Support: a released piece falls to its support; it floats only
if its material allows it (E033 otherwise).
7.7 Distance rules, and its one exception
From the distance (LEJANIA), and from nothing else, derive the speed, colour and z of
a layer. The exception, declared: MUNDO acelera a N and MUNDO frena a N are an
explicit order of the hand to the world clock; the dimension stratum speed has a second
authority, order of the world, below distance. The law still holds between layers (a
layer cannot be slow and in front); the order changes the common clock, which multiplies
all of them alike. MUNDO para sets the clock to zero.
7.8 Material
Nothing is a flat fill. Every piece belongs to a register (REGISTRO_MATERIA):
recorte (scissor outline, grain, hard shadow, edge), pintado (gouache or marker: passes
with ductus and an overflowing edge), fotográfico (developed and die-cut), tinta (a
hand-drawn line, which boils). The boil: three poses of the same path, same geometry,
different tremor, periods seeded by identity; the poses MUST be isomorphic. The boil
changes the shape, never the place.
7.9 Camera, continuity, light and focus
From the axis derive each one's side, view and entry side. Flipping applies only to
pieces declared mirrorable. The three laws of camera: displacement is data, not a bounding
box; the cut does not travel; a scene with a world of its own is a new place. When the
hand declares toca la truca: sí, the rostrum inherits its pulse (anticipation, a tremor
of prime period, overshoot, and it loses the subject for half a second).
One light per scene, and every shadow obeys it; the hour tints it. Adjusting the shadow of a single piece is forbidden. Focus is not blur: what is out of focus is paler, with a softer edge and slightly larger. Text is never defocused, unless a rule is broken with permission (§8.5).
7.10 Continuity warnings
None is fatal: breaking them is legitimate, but it must be said. AVISO_CONTINUIDAD:
| Warning | When | Silenced by |
|---|---|---|
W101 axis jump | crossing the line without a neutral shot | > cruza el eje, > rompe el eje porque «…» |
W102 size jump | the same size and angle on the same subject, or more than two steps, between shots that both declare a size | > salta |
W103 eyeline | in a reverse shot both look to the same side | |
W104 direction | leaves by one side and enters by the same | |
W105 state | a piece changes without an action that explains it |
8. Profiles
A profile is a set of capabilities an interpreter realizes. Every interpreter MUST
accept every valid IR; for a capability outside its profiles it MUST behave as if the
line were absent, MUST NOT fail, and SHOULD tell the author once per capability. An
interpreter declares the profiles it realizes; the suite's huella and banda cases are
grouped by profile.
| Profile | Scope (grammar in Appendix B) | Reference |
|---|---|---|
| núcleo (core) | §5 and §7: the table, collage, pieces, movement with the craft, cinema and continuity, the journey, the paper theatre, the map, and the aspect lines of §8.1 | ce (partially: not the aspect) and gx |
| sonido (sound) | §8.2: voice, effects, the score of sound, music cues, ambiences, rooms, panning and master | gx |
| cartel (poster) | §8.3: every shot is a poster | gx |
| oído (hearing) | §8.4: the picture that listens, light, support, intensity | gx |
| cámara (camera) | §8.5: the camera as an object, depth, layered time, the frame as an object, breaking with permission | gx |
RFC 0002 proposes separating the aspect lines into a profile of their own.
8.1 Aspect (part of the core profile)
Unit lines (preamble, chapter or scene; the scene prevails) and events, all closed vocabulary and without numbers; the numbers belong to the interpreter:
MATERIA papel PAPEL | acuarela | risografía A y B [y C] · registration · screen | pincel | tejido [drum] | tinta | ninguna [sobre papel PAPEL]: what the frame is made of, a pass over the finished frame in the convention of Part 6. The same words as a prefix give the material of one piece (en acuarela: python: gamba). A photograph has no layers: its material is baked once on the original image, not on its halftone. Events:> se moja,> se seca,> se lava,> florece [drum] [en «X»],> se teje,> la tinta lo cubre todo [drum].BOBINA truca | sin grano | noticiario: the film stock (the newsreel at 18 frames per second, sepia, scratches, flicker and weave).FORMATO 4:3 | 16:9 | 2,39:1 [· de televisión] [· bandas de papel]and> formato X: bands of ink with torn edges; the change is animated. In a pliego that changes format, every format is a viewer with round corners and paper around it, and the viewer pass goes last.ESPEJO [side],PANTALLA PARTIDA [· con un espejo en medio] [· que se miran] [· desigual] [· inclinada],SIMULTÁNEO en rejilla | en abanico | en abanico que gira, with their events (> se rompe el espejo,> se parte la pantalla,> un solo plano…).- Transitions (
TRANSICION): two-plane transitions where the incoming plane is alive and the outgoing one is a still lámina of its last frame;corta,corta en la acción,sintoniza,a la vez,se sostiene,retención larga. RÍO TIPOGRÁFICO [· en fila | en libertad | a pantalla completa | no]: the voice written word by word at the instant it is said; capitals and> revienta «…»grow, stamp and overflow. The split sentence (A / B: —…) and the flying sign (de «A» a «B»: pon: …).MONTAJE se acelera · al ritmo de las palabras · al pulso · cada vez más cerca · la cámara no para · mezcla «A» · «B»: cuts inside the beat.- Movement trails (
con estela,con líneas de fuerza,en cronofotografía), metamorphosis (X se funde en Y,X hierve con Y,el pelo pasa de X a Y),> se rasga el papel y asoma «SCENE»,> asoma «SCENE» en el hueco,REPITE «SCENE», characters with a card (Part 3) andHERVOR dibujado | suave | no.
The chain of every instant is: material, what peeks through, mirror and split screen, simultaneity, camera, format, newsreel, transition, tuning, and the bath (paper and film). A pass changes only when something changes; its animations are functions of scene time.
8.2 Sound
The sound profile covers the voice and the whole soundtrack. Every example, gallery item and conformance pliego of this standard carries music and sound design.
Preamble: EFECTOS folder (effects and ambiences, by file name), BANDA folder (music
cues), MEZCLA para la web | para cine · con stems | sin stems, and in REPARTO the voice,
its colour (con radio: the loudspeaker band, a touch of saturation and the station's
hiss; or seca) and its side. Unit lines: MÚSICA cue | ninguna, AMBIENTE a · b
(layers), ESPACIO estadio | patio | estudio | radio | seco (the room of the effects),
CAMA, JINGLE. Clip lines: sonido: effect [side] (anchorable: al decir «X»: sonido: pitido). Events: > entra la música «cue», > la música se corta, > la música se apaga, > silencio de verdad, > las voces se juntan en el centro, > cada voz a su lado, > la voz se vuelve radio.
An interpreter of the sound profile MUST:
- resolve names case-insensitively and with the normalization of §4.5:
sonido:andAMBIENTEinEFECTOSand then inBANDA;MÚSICAinBANDA. (A name that is found in neither is an error the compiler reports:E040,E041,E042; an interpreter MUST NOT render such a pliego as if the sound were silence.) - mix in stereo through four buses: voices, music, effects and ambiences;
- keep a music cue running while consecutive scenes name the same cue (it does not restart), crossfade on a change of cue, end a cue shorter than its stretch on its own and fade one longer at the end of its stretch;
- loop ambiences with a crossfade at each turn, for as long as they last;
- duck music under the voice more than ambiences: the voice is always intelligible;
- on
> silencio de verdad, cut music, ambiences and what was sounding until the next beat, without room tone; an effect that starts at that very instant sounds whole; - place each voice at its side, move them on the panning events, and apply the room of
ESPACIOto the effects (the voice already carries its colour in the take); - master to −14 LUFS integrated for the web and −24 LUFS for cinema, with true peaks below −1 dBTP (a limiter oversampled at least four times), and, with stems, write the four buses with the master's gain and without the limiter;
- never call a paid service while rendering: voices come recorded in the sidecar (§14.3).
The reference writes the master as 24-bit WAV beside the video (<out>.master.wav), the
stems in <out>.stems/ and a report in <out>.banda.json with the measured loudness,
true peak, cues and counts; the suite's banda cases read that report.
8.3 Cartel: every shot is a poster
PALETA A, B y C (field, figure, accent, plus the paper; COLOR_CARTEL) and CARTEL composition · … (COMPOSICION) compose the page as a poster; inside a clip they apply to
that shot. Signs are pieces: LETRA «WORD» · en TYPE · arrangement · place · size · de COLOUR, «X» es un PAPEL-SIGNO [a «SCENE»], a letter that is a figure or becomes one,
[las letras de] «X» VERB (each letter with its rig and the craft), la raya corta «X»,
«X» forma FORM, ESCALA A como B, BOSQUE de …, en silueta:. Pieces can be cut by the
edge (CORTE) and grow gigante. The safeguard: a cut never takes away what is
essential in a piece (face and mouth of who speaks, the acting hand, the object that
matters: the essential parts of Part 3); text that must be read is read; · sin leer gives
permission. Text is woven: TEJE, SINTONIZA, se interrumpe en, sigue, FRASES,
and the stateful events of the cloth. PARTITURA path lets the typography of the source
text propose what a clip does not say (italics, dashes, capitals); what the clip declares
prevails.
8.4 Oído: the picture that listens
The interpreter hears the real audio (the voice of each beat, ambiences, music,
effects) as curves at 100 samples per second: intensity (absolute and relative), pitch (in
octaves), attack, spectral centroid and 32 log bands. Tracks (PISTA): la voz, la música, la cama, los efectos, la radio, or a named sound. Lines: la cámara respira con PISTA, el río mide la voz, la luz sube con PISTA, el dial es la línea de tiempo,
X es el espectrograma de PISTA. Light: LUZ de «piece» · desde abajo · drum (one hard
source, attached to its piece), LUZ de los focos · en contraluz, LUZ plana, COLOR monocromo [drum] | pleno, > estalla el color. Support (degradation as dramaturgy):
SOPORTE limpio | usado | gastado | sucio | roto, > el soporte empeora | se deshace | se limpia; the support lasts the whole film. Intensity as a direction parameter:
INTENSIDAD WORD | de WORD a WORD [· extraña] [· con PISTA], with eleven words from nula
(0) to rota (10), governing at once tremor, tilt, misregistration, grain and the pace of
MONTAJE al pulso.
8.5 Cámara: the camera as an object
Unit lines: CÁMARA lens · weight · hand · depth, HORIZONTE recto | se inclina | gira,
CADENCIA target cadence · … (each layer draws at its own rate), GOLPES con impacto | con borrón, PISTA ÓPTICA [side]; distance prefixes (lejos: python: fachada) put a
piece at that distance from a real perspective camera, and parallax is never declared:
it comes from the perspective when the camera moves. The sky is at infinity. Events
(EVENTO_CAMARA) include pans with mass, dolly, crane, lenses with focal length and
distance separated, the vertigo shot, a continuous tension curve for the handheld camera,
the tilting horizon, snorricam, orbit, bullet time, going through pieces, the long take,
axial cuts, the frame as an object (paper bands, perforations, a derailed frame), and
X mira a cámara.
Breaking with permission. A shot may break a rule knowingly, with its reason:
> rompe el eje porque «…», > se sale del cuadro porque «…», > sin leer porque «…»,
> demasiado rápido porque «…», > todo a la vez porque «…», > sin respiro porque «…», and the named awkward framings (ENCUADRE_INCOMODO). A rule broken without its
reason is an error (E060); a compiler explains it and the Lasseter review lists it apart.
9. Extension by layers
The language is never extended in silence. It grows by layers, from the inside out:
- The language: closed vocabulary, changed only by RFC and in a new epoch (§22).
- The sections
#TALLERand#MANO: they calibrate the craft of a project or a scene (paper, ink, edges, anchors, shadow, materials with mass and drag, the bath, the grid; the hand's pulse, precision, grain, entry and exit, fatigue, and whether it touches the rostrum). Numbers are legitimate here; the mirror law (§5.3) holds. - The bestiary (
PYTHON,PIEZAS): named pieces with their parameters, parts, poses, actions and cycles (Part 3), called from the pliego by name (python: radio,LOCUTOR señala). A bestiary adds pieces, never grammar; its actions are the closed vocabulary of that piece. - The interpreter: passes in the convention of Part 6, materials, foley. An interpreter MAY add passes and looks under existing words; it MUST NOT add words.
The house layer. A pliego that only says (a REPARTO and di: lines) is already a
film: in a unit where no beat places anything of its own, an interpreter SHOULD put the
sentence of each beat on the paper with the piece the function and the affect call for (a
question by hand, a shout as a ransom note, a quotation as a newspaper cutting, the rest
typed). The layer switches itself off, unit by unit, as soon as a beat teaches something
of its own; página vacía in the property line switches it off for the whole pliego. It
is what lets a person or a small model write a first pliego with no drawings at all.
~ deriva: text records a commission to the engine in the IR without changing the film.
What a pliego cannot say: easing, keyframes, rate functions or loose durations in the
plain dialect; colours by hex or RGB; shadow, stratum speed or z per piece; unnamed pieces;
two places for the same decision.
10. The intermediate representation
10.1 What it is
compile(pliego) returns (script, report, extra): the IR (guion rico), a list of
readable sentences about the direction, and per-beat decisions (function, affect,
template, tension, author), motifs, cast and arc. The IR is JSON, is regenerated always
and never versioned inside projects; it is the contract an interpreter and a narrator
(mesa cuenta) eat. If the narrator cannot tell a new capability, the capability is
badly integrated.
Field names are Spanish identifiers without accents. Unknown fields MUST be ignored by interpreters (forward compatibility, §22).
10.2 Script level
Required (a conforming compiler always emits them):
| Field | Type | Meaning |
|---|---|---|
escena | string | name of the scene to render |
capitulo | integer | page index (0-based) |
sala | string | crema or pizarra |
beats | array | the compiled clips (§10.3) |
taller | object | the effective workshop, with all precedence applied |
mano | object | the effective hand |
unidades | array | the chapters (§10.4); REQUIRED when the pliego has chapters |
Optional (absent or null when the pliego does not declare them): registro (the
dominant affect), subtitulos, gigantes, personajes, reparto, claves_cap,
tambor_cap, tramos_cap, archivo, archivo_cap, archivo_tintas, fantasma,
python_ruta, python_rutas, replica, efectos, banda, mezcla, bano, en_dos,
pagina, aspectos, and colofon ({lineas, tirada, semilla, toma, pobre}: counted,
not declared).
The script level also carries marionetas (the photo puppets declared
with MARIONETA: nombre, foto, mira, canto), and the aspect of every unit and
beat carries partitura_modo (whether the voice is set as a typographic score, §8.3; null
when the pliego says nothing). Both are part of the reference IR; neither enters the
normative projection.
10.3 Beat level
Required: id (the clip's ordinal, b07, or its declared beat id), cap (chapter
index), plano (the resolved template), afecto (the resolved affect), acciones
(§10.5), and identidad (the stable path of §7.4, source of the seeds; see Appendix D).
Optional, and what distinguishes the pairs: di (the beat's delivery), dura
(declared duration when there is no voice), sec, corte (there is a cut before this beat,
whoever decided it) and corte_mano (the hand asked for it), plano_mano (the template
was declared, not derived), limpia, queda, canta, nocturno, congela, luz (the
effective light, already resolved with the hour), escena, escena_titulo,
abre_escena, lugar_nuevo, linea (the source line), aspecto (the effective aspect of
§8.1 to §8.5, one object per beat), transicion, montaje, rio, voces,
frase_partida, revienta, rotos (rules broken with permission) and the rest of the
fields of the profiles. The pattern X / X_mano is systematic: X is the value and
X_mano says whether a person set it.
10.4 Unit level
Each element of unidades: n, titulo, beats (ids), escenas (titles) and
estado_entrada (REQUIRED): {velocidad_mundo, sentido, hora}, the state the chapter
opens with. It exists because movement persists across cuts and chapters are rendered in
different processes: the only way for chapter 3 to know how fast the world was going is
that the compiler writes it, walking everything before, deterministically.
10.5 Action level
verbo is REQUIRED. The presence of a field is the signal of authority: en (place
declared by the hand: authority hand), liga (binding), cuerpo (body), al_decir
(score), run (gesture), and the movement's trayecto, manera, granulado; spec
and sobre carry the body of a ver: and the target of a mark. The verbs the reference
compiler emits are listed in its IR; an interpreter MUST ignore a verb it does not know
and SHOULD tell the author.
10.6 Canonical form and normative projection
The canonical form of an IR is its JCS serialization (§1.3); its digest is the SHA-256 of that serialization, in lowercase hex (not to be confused with the fingerprint of a film, §13.4).
The normative projection of an IR keeps only the required fields of §10.2 to §10.5
(script, beat, unit and action levels). Two conforming compilers MUST produce IRs with
equal normative projections for every pliego of the suite. The reference implementation is
additionally held to its full IR, frozen in conformance/expected/ir/: any change is
either a regression or the subject of an RFC.
11. Invariants
11.1 Closure
canon(compile(p)) == canon(compile(escribe(p)))where escribe materializes every decision of the engine into the pliego (revealed
dialect, §3.1) and canon(ir) removes provenance and position, and nothing else: the
fields origen, autor_cabecera, _importado, linea and colofon. Everything that
decides a frame MUST coincide; who decided it, and on which line, need not.
11.2 The mirror
For the sections of §5.3, effective(p) == effective(parte(p)) == effective(funde(parte(p))), where parte moves every block to its own file and imports
it, funde inlines every import, and effective is the workshop and the hand after
precedence, compared line by line after normalization.
11.3 Compatibility
A pliego that compiled once compiles always (§22).
12. Diagnostics
A compiler checks a pliego (mesa lee in the reference) and reports errors and
warnings, each with a stable code (Appendix C, spec/diagnosticos.json) and a free
message, which SHOULD teach: say what was expected and offer the closest valid words. A
pliego with any error is invalid; a compiler's checking command MUST exit with a non-zero
status for an invalid pliego and SHOULD exit with zero otherwise. The suite compares
sets of codes, never messages or order.
Errors cover words outside a closed vocabulary (E010 to E019), names (E020 to
E022), structure (E030 to E033), sound resources (E040 to E042), the bestiary
(E050, E051), rules broken without reason (E060), and malformed lines (E090).
Warnings cover continuity (W101 to W105), reserved words in use (W110, W111), the
health of the pliego (W112 to W118), what needs the voice sidecar (W120 to W123)
and the Lasseter review (W130).
Warnings that need the sidecar are emitted only when <pliego>.tiempos.json exists:
the dead anchor, two voices (a sounding clip inside a narrated beat without > espera al clip), the illegible anchor, and the beat that grows.
The Lasseter review is measured on the real timeline of a render (or a dry render
that interpolates the same frames without rasterizing), never on the pliego: movement
shorter than fotogramas_minimos frames at 24 fps, more than simultaneos_maximos pieces
that stay on stage moving in the same frame, no pausa_fin_beat at the end of a beat, text
on screen for less than words / palabras_por_minuto · 60 + asiento_lectura seconds, twin
beats, linear movement, fast movement without anticipation. Each warning carries its beat,
its line, its instant, a suggestion and a severity.
Diagnostics that need the bestiary are computed by reading the bestiary without
executing it (in the reference, with Python's ast): a python: name that does not
exist (E050), a pose that was not declared (E051), a pose written without
normalization, a group that composes a piece not created in that beat.
12.1 Diagnostics that teach
The criterion of usability of the language is that a person, or a language model much smaller than the one that designed it, writes a clean pliego in a few attempts without reading any code. Diagnostics are the main tool for that, so a conforming compiler:
- MUST give the line of every diagnostic that has one;
- SHOULD give, after the message, why (the rule that applies), the fix (with «did
you mean …?» built from spelling distance, prefix and a table of synonyms:
lento→despacio,de frente→frontal) and an example of the correct line; - SHOULD offer an explanation of any word or line (in the reference,
mesa explica «X»: what it is, where it goes and an example; for a whole line, what the parser understands) and a one-page cheat sheet of the language (mesa chuleta); - SHOULD list the pieces a pliego can see, with their kind, description and the
actions each one declares, and the exact line to ask for them (
mesa bestiario pliego.mesa).
12.2 No silent failures
Whatever looks like an instruction and is not one is an error, never prose. A line the
interpreter would print on the paper by accident (dialogue by a speaker who is not in
REPARTO, a scene line written inside a clip, an instruction or verb that does not exist) is
E023; a line of prose that will be typed on purpose is the warning W125. A compiler
MUST also report, reading the pliego and the bestiary without executing anything:
| Code | What would otherwise fail in silence |
|---|---|
E018 | an unknown modifier after · in foto:, recorte: or clip:, or an unknown field of MARIONETA |
E024 | NAME action for a piece that is neither in REPARTO (with the piece as alias) nor a MARIONETA: the action would never reach it |
E025 | al decir «X» where the written voice of that beat never says X (without the sidecar; with it, W120) |
E052 | a drawing invoked wrongly: arguments after ·, parentheses as in a programming language, or arguments the signature of the piece does not accept |
E053 | the bestiary declared with PYTHON or PIEZAS does not exist next to the pliego |
E054 | an action the piece does not declare among its actions, poses or cycles (§15.2) |
W124 | an empty page: a beat opens a new frame (a declared shot size, a new chapter or scene) and places nothing while the voice sounds; not emitted for respiro, which empties the page on purpose |
The colour of a REPARTO entry is a closed vocabulary (the drums of the canon and the inks
of the poster palette); another word is an error (E019).
13. Tools and fingerprints
13.1 The command (informative)
The reference ships one command, mesa (python -m manim_saorin.formato.cli). Its
subcommands are not normative, but conformance adapters use them: lee (check), ir
(dump the IR), cuenta (tell the pliego in prose), escribe (reveal), indice (census
of names and ambiguities), por-que (each decision with its authority and line), mueve,
taller, parte, funde, graba (synthesize the voice and write the sidecar),
animatica, toca (render; --motor gx on Tórculo's engine), suena (the soundtrack
without rendering), lasseter, intensidad, dura, empaqueta, desempaqueta,
comprueba (Part 2), pieza and bestiario (Part 3), and the teaching tools of §12.1:
explica, chuleta and nuevo (mesa nuevo "Title" [--desde text.md] writes a project
with a commented template layer by layer, a minimal bestiary and its folders, or a first
pliego drafted from a text).
13.2 What a compiler MUST offer
A conforming compiler MUST offer, by any interface: checking a pliego with the codes of
Appendix C, dumping its IR as JSON, and revealing a pliego (escribe) and splitting and
merging its sections (parte, funde) so that §11 can be tested.
13.3 What an interpreter MUST offer
A conforming interpreter MUST render a pliego with its sidecar to a video with sound, and SHOULD offer a dry run that produces the timeline the Lasseter review reads.
13.4 The fingerprint of a film
The fingerprint (huella) of a video is a sequence of grey thumbnails of 96 × 54
pixels, one per second, scaled with area averaging (ffmpeg -vf fps=1,scale=96:54:flags=area -pix_fmt gray), stored base64 in JSON with the MD5 of each thumbnail quantized to 4 bits.
Two fingerprints match when they have the same number of samples (±1) and the mean
absolute difference per pixel of every pair of samples is at most 10 (on 0 to 255). On the
same machine and engine the reference matches with difference 0. Metrics lie: a
fingerprint says where things are, not whether they live; no golden fingerprint is changed
without looking at a strip of the film first.
Part 2. The portable project
14. The portable project
14.1 What a project is
A project is the pliego, its bestiary and its sound (the voice with its sidecar, the
effects, the music) plus everything the pliego reads (the PARTITURA, imported
sections, real-video clips, photographs, the lock of chosen láminas). A packager MUST
discover these files by reading the pliego and the bestiary, and MUST NOT execute
project code to do so (the reference reads the bestiary with Python's ast).
A project is portable when every path it uses is relative to the pliego's folder and stays inside it, and every file it needs is inside it or is declared as an installation dependency in the manifest.
14.2 The package
A .mesapack is a ZIP archive (PKWARE APPNOTE; ZIP64 allowed). Audio, video and images
SHOULD be stored without recompression (method 0). It contains the project tree, with the
pliego at the root, and a file MANIFIESTO.json at the root:
| Member | Type | Required | Meaning |
|---|---|---|---|
formato | string | yes | "mesapack 1"; a reader MUST reject another major (P003) |
pliego | string | yes | the pliego's path inside the package; MUST end in .mesa and exist (P008) |
titulo | string | no | the pliego's title |
creado | string | no | ISO 8601 |
por | string | no | the tool that packed it |
versiones | object | yes | lengua (the epoch, REQUIRED), motor (name, version, commit, branch), torculo (commits of the standard and of the engine), or null where unknown |
voces | object | no | the cast with voice, colour and side, and how many takes of each method (§14.3) |
fuentes | object | no | per font: where it is (motor, sistema, usuario) and, for user fonts, its path in the package (_fuentes/…) |
externos | array | no | what the bestiary reads from the installation and does not travel: {ruta, por, donde} |
no_portable | array | no | what could not be made portable: {donde, ruta, arreglo} |
archivo_fotos | array | no | archive photographs carried in _archivo/ |
archivos | object | yes | per path: {sha256, bytes, por}; por says why the file is in the package |
A reader:
- MUST reject entries with an absolute path, a
..segment, a backslash or a drive letter (P004), and MUST NOT write outside the destination folder; - MUST verify the SHA-256 and size of every declared file (
P005) and SHOULD reject undeclared files (P006); - MUST check that the sidecar's recordings are relative paths inside the package
(
P007); - SHOULD, after unpacking, check the project as a packager would and warn when the language, engine or standard versions differ from the manifest's.
The reference validator is conformance/tools/mesapack.py; the reference packager is
mesa empaqueta (with desempaqueta and comprueba).
14.3 The voice sidecar
<pliego without extension>.tiempos.json sits beside the pliego. It is the fifth input of
the determinism contract (§7.4).
{
"beats": {
"b01": {"dur": 2.57, "pause": 0.4, "hash": "cf79cc76fda2", "metodo": "silabas",
"palabras": [{"w": "Un", "t": 0.05, "d": 0.214}, {"w": "tórculo", "t": 0.264, "d": 0.482}]}
},
"wavs": {"b01": "audio/voz/b01.wav"}
}beatsmaps a beat id to its delivery:dur(seconds),pause(seconds after it),hash(of the text that was spoken, so a changed text invalidates the take),metodo(how the timings were obtained:whisper,silabas,elevenlabs,declarado,cancion,hueco, or another name), andpalabras, each wordwwith its starttand durationdin seconds from the start of the beat. A beat MAY carryt_abs(an absolute time, for songs).wavsmaps a beat id to its recording: a path, a list of paths (takes chained, as in a sentence split between two speakers), or a list of{ruta, desde}objects (takes that sound at once, each from its instant).- Paths SHOULD be relative to the sidecar's folder (the pliego's) and, in a package, MUST be. Readers MUST accept relative and absolute paths, resolving relative ones against the sidecar's folder. A sidecar whose absolute paths point to an old location of a moved project MAY be re-anchored when the same file (same path suffix and size) exists in the new location.
- A pliego whose voices were recorded outside the engine (for example by a casting service) carries them in the sidecar; rendering MUST NOT call a voice service.
14.4 Diagnostics
P001 not a ZIP, P002 no readable MANIFIESTO.json, P003 unknown format, P004
dangerous path, P005 missing file or wrong hash, P006 undeclared file, P007 a sidecar
recording outside the package or absolute, P008 the pliego is missing, P009 a required
member is missing.
Part 3. Pieces
15. Pieces
This part normalizes what enters a pliego through PYTHON/PIEZAS, python:,
MARIONETA, foto: and clip:. It follows SPEC-PIEZAS.md v1 of manim-saorín (branch
piezas, 2026-10-15); the binding to Python described there is the reference binding, and
another engine MAY offer the same contract in another language.
15.1 Levels
| Level | What it is | The pliego may also |
|---|---|---|
| 0, drawing | a pen drawing, a photograph, a cut-out | place it, move it, film it, cut it by the edge |
| 1, parts | plus named parts with a pivot | el pelo pasa de A a B; protect what is essential when cutting |
| 2, puppet | plus articulation (mothers and pivots), poses, actions and cycles | X saluda, X corre hasta…; the mouth follows the voice if there is a jaw |
| 3, character | plus five views, expressions, visemes, hands, walk and run cycles, colour worlds | X de espaldas; the view follows the shot; al decir «…»: X se asombra |
Each level is a superset of the one below.
15.2 The contract of a piece
A piece is a constructor (in the reference binding, a Python function returning a ManimGX mobject) with:
- its own arguments, by position or by name (what the pliego writes after
python: name), and the extras with defaults:alto(height in scene units; the screen is 8 high),hervor(0, 1 or 2 fixes a boil pose; none lets the table boil it),mundo(§15.5),espejo,id; - its card (§15.3);
- its boil: three poses with the same structure and another pulse;
- its support: the height where it rests (its feet), so it stands by its feet, not by its centre.
From level 1, a piece exposes partes (name to sub-object) and a pivot per part. From
level 2: the card signature vista, pose, expresion, boca, mano_i, mano_d,
hervor; POSES (names), ACCIONES (action to a list of poses, performed on twos) and
CICLOS (cycle to a repeating list of poses; corre and anda are started by the
movement verbs); a pivot and a mother for every articulated part; a part named mandibula
opens with the visemes. The actions of a puppet are its closed vocabulary: X saluda
is valid if saluda is among its actions or poses; otherwise the interpreter warns with
the list it has.
A level 3 character has views (frente, tres cuartos, perfil, tres cuartos de espalda, espalda), expressions, mouths (reposo, a, e, i, o, u, m, f,
l, gol), hands (open, fist, pointing, clapping, pinch, or an object held), common poses
and the cycles corre (8 drawings), anda (8) and habla (6), and nested parts with
pivots (trunk, neck, head with its features, hair, scarf, arms, forearms, hands, thighs,
legs, feet).
15.3 The card
| Key | What | Required |
|---|---|---|
nivel | dibujo, partes, marioneta or personaje | yes |
nombre | ASCII without spaces: it is the seed and what the pliego writes | yes |
titulo | with accents, for the sheets | no |
descripcion | what is seen, for whoever cannot see it; used by the meaning layer and the bestiary listing | yes, 20 characters or more |
alto | natural height in the scene | recommended |
mira | derecha, izquierda or frente: for mirroring and the axis | recommended |
tintas | the colours it uses | recommended |
registro | dibujo, foto, recorte, clip, tipografia, materia or escaneo | no |
partes | the parts it has | from level 1 |
esenciales | essential to part | from level 1 |
15.4 Essential parts
What the language protects when cutting by the edge (§8.3): cara, boca, cabeza,
mano (the acting one) and objeto (what matters). A character declares the first four;
a puppet at least cabeza or objeto; a drawing objeto. No essential part may leave
the outline of its piece. Without declarations, the centre of the piece is essential.
15.5 Colour worlds
mundo=: natural, tinta, sepia, noche, hielo, silueta or silueta:#RRGGBB,
riso:DRUM+DRUM (two drums of the canon), and the worlds a project registers. A world
recolours every ink of a drawing and maps the greys of a photograph to its two inks.
15.6 In the pliego, and the checks
PIEZAS path (a module, a declarative file of a character, puppet or cut-out, or a whole
folder) extends PYTHON. MARIONETA name · de la foto path [· mira a la izquierda | derecha] [· canto …] declares a photo puppet. python: name [args] places any piece;
named arguments fix the starting pose and view of a card. WHO action performs an action
the piece declares. Collage in motion: foto: path · sin fondo · canto de tijera | de troquel | rasgado | limpio · sombra pegada | levantada | sin sombra · con cinta | celo | chincheta, and clip: path de a a b · sin fondo (a cut-out film, on twos by default).
A piece provider MUST offer a check that calls each piece as the interpreter will and
verifies: it draws; it boils (three poses, same structure, different pulse); it has its
parts and essentials, none outside the outline; every articulated part has a pivot inside
the piece; every action and cycle uses poses that exist; for a character, the five views,
the visemes and the cycles. The reference is mesa pieza comprueba.
15.7 Photo puppets
A photo puppet is a level 2 piece made from a photograph without code: MARIONETA name · de la foto path … in the preamble or a name.marioneta.toml card. The provider finds the
joints and the face of the person, cuts the photograph once with the declared edge and
splits it at the joints (head, trunk, arms, forearms, thighs, legs; legs only when they
are seen whole), each part with a pivot and overlapping its mother; the part below the lip
becomes the mandibula, which opens with the voice. Without a person or a face the
photograph is one piece that trembles. Every photo puppet knows, besides what its card
declares: saluda, celebra, señala, baila, se inclina, duda, grita,
aplaude, en jarras, and the cycles anda and corre. An action whose parts the
photograph does not have (an arm that was not found) SHOULD be warned by the piece check.
A character card in words (name.personaje.toml) declares a level 3 character with
closed words instead of code: body (height, build, age), head (skull, nose, glasses,
eyes), hair (style, colour), clothes (top, bottom, shoes and their colours), the object it
holds, and its own poses ([poses.recuerda] brazo_i = "a la boca"). The words are a closed
vocabulary of the provider; an unknown word is an error of the piece check.
15.8 Collage in motion
Photographs, cut-outs, real video, type, pen and materials share one shot.
foto: path [· modifiers]pastes a photograph; with· sin fondothe figure is cut out (the provider removes the background), and the edge (canto de tijera | de troquel | rasgado | limpio), the shadow (sombra pegada | levantada | sin sombra) and the fastening (con cinta | con celo | con chincheta) are declared in words.recorte:is a photograph already without background. The material of a piece still applies (en risografía rosa: foto: …).clip: path [de a a b] · sin fondois a cut-out film: every frame is cut out and cut again with scissors, so the edge boils by itself; it plays on twos (12 drawings per second) unlessen uno/a 24oren cuatrois said, and it is an actor without frame or tape.clip de fondo: path [de a a b]fills the frame at the cadence of cinema. A background clip lasts its range: when it ends it leaves at the opening of the next beat, even if the shot continues; it never stays frozen over what comes next.CADENCIA(§8.5) sets each layer's cadence (las figuras en dos · el fondo en uno), so the mixture of cadences of collage (real video at 24, cut-outs on twos, the pen boiling at 8) comes out by itself.- The house sets.
FONDOandDELANTEmount pieces of the bestiary as a scene's set; an interpreter of the core profile MUST also offer, without any bestiary, the sets of the house:cielo,sierra,agua,arcada,celosia,ciudad,farola,lluvia,arboleda,cuarto,luna. A bestiary piece with the same name replaces it. A set that is neither is an error.
Who acts. An action is asked with a REPARTO name whose alias is the piece's name, even
for a piece that does not speak (REPARTO TIJERAS: minio, alias: tijeras, then al decir «corta»: TIJERAS corta); an alias equal to its own REPARTO name is not an ambiguity. The
piece must be on the table in that beat or before.
Part 4. The canon
16. The canon
16.1 Source and generated files
canon/canon.toml is the single source of truth. Every other form is generated by
canon/genera.py: Python (canon.py), TypeScript (canon.ts), Rust (canon.rs), WGSL
(canon.wgsl) and CSS (canon.css). Generated files MUST NOT be edited by hand;
genera.py --check fails if any is stale. The file declares version = 1.
16.2 Palette
Colours are sRGB, written #RRGGBB. In WGSL and Rust they are the same sRGB values as
floats, component / 255 rounded to six decimals (not converted to linear light); in CSS,
custom properties --group-name.
| Group | Colours |
|---|---|
papel (paper) | base #F5F0E8, hundido #EDE6D6, hoja #FAF7F0, filete #D4C4B0, filete_hondo #C4AE96, noche #1A0F0A |
tinta (ink) | base #2C1810, segunda #5C3D2E, apagada #7A5F4E, lapiz #9A8E80, negro #1A120D, sobre_noche #FAF7F0 |
escritorio (desk) | rojo #C1453B (minium), azul #2B4C7E (azurite), amarillo #E8A838, oro #D6A03A |
tambores (risograph drums) | ultramar #2B3BC7, bermellon #D93325, naranja #E8501A, ambar #F2C744, verde #00A95C, rosa #FF48B0, violeta #765BA7, humo #1A1A1A |
Drums are for content, never for chrome. The pliego's TAMBOR vocabulary names seven of
them (all but humo); the risograph materia (TAMBOR_RISO) accepts humo, tinta and
azurita too. New work MUST use this paper and ink; the older
creams #F2EEE4 and #F6F0E2 are legacy.
16.3 Randomness
All randomness in Tórculo is deterministic and derives from three functions, which every implementation MUST compute bit for bit:
semilla(text): FNV-1a, 32 bits, over the UTF-8 bytes of text
h = 0x811C9DC5; for each byte b: h = (h XOR b) * 0x01000193 mod 2^32
serie(s): Mulberry32 seeded with s; each call:
a = (a + 0x6D2B79F5) mod 2^32; t = a
t = (t XOR (t >> 15)) * (t OR 1) mod 2^32
t = t XOR ((t + ((t XOR (t >> 7)) * (t OR 61))) mod 2^32)
return (t XOR (t >> 14)) / 2^32 in [0, 1)
hash32(n): x = (n * 0x9E3779B9 mod 2^32) XOR 0x85EBCA6B
x = x XOR (x >> 13); x = x * 0xC2B2AE35 mod 2^32; x = x XOR (x >> 16)
return (x AND 0xFFFFFF) / 2^24 in [0, 1)serie returns doubles that are exact multiples of 2^−32; hash32 returns values that are
exact in a 32-bit float. Nothing may use the system clock, Math.random or an unseeded
generator. Seeds are computed over UTF-8; an older TypeScript helper of Scholaris
seeded over UTF-16 code units, which agrees only for ASCII: that is one reason identifiers
SHOULD be ASCII.
The test vectors are normative: conformance/canon/vectores.json gives, for a set of
texts (empty, ASCII, accented, ñ, CJK and a non-BMP character), the seed, the first eight
values of the series as integers before division, and hash32 of the seed and of five
fixed integers. A canon implementation in any language MUST reproduce them.
16.4 Craft and foley
oficio (the craft, Lasseter in numbers; no pliego writes them, the engine applies them):
palabras_por_minuto = 220 and asiento_lectura = 1.0 s (reading time of a text),
fotogramas_minimos = 8 (at 24 fps, nothing moves for less), simultaneos_maximos = 3,
pausa_fin_beat = 0.6 s, anticipacion = 0.2 (fraction of the action), exageracion = 1.25, hervor_fps = 8, hervor_poses = 3, dibujo_en = 2 (drawn things on twos). A
canon of a later version MAY add keys; implementations MUST ignore keys they do not know.
foley: the relative weight of each foley event (the ear does not hear a key like a
stamp): rotulador 0.55, tecla 0.75, hilo 0.8, papel-deslizar 1.0, papel-posar 1.0,
carton-posar 1.1, celo 1.15, despegar 1.15, tijera 1.3, chincheta 1.25, sello 1.35,
punzon 1.2, papel-rasgar 1.3, pagina 1.4, campanilla 1.1, pincel 0.6, lavado 0.7.
Part 5. Láminas
17. Láminas
A lámina is a hand drawing ready for any engine (web, app, game, video) to make it appear under the pen without computing the hand again: the image is rasterized once and, beside it, a time atlas says at what instant the pen reaches each pixel.
17.1 Two envelopes, the same content
Directory
name.lamina/with the files of §17.2.Packed, a single file
name.lamina:Bytes Content 0 to 7 the signature LAMINA\0\x01(4C 41 4D 49 4E 41 00 01)8 to 11 n, the length of the index, u32 little-endian12 to 12+n the index, UTF-8 JSON: {"archivos": [{"ruta", "inicio", "largo"}, …]}from 12+n the files one after another; iniciocounts from here
Index paths are the directory's paths. A reader tells the two cases apart by the signature.
17.2 Files
manifiesto.json what there is and how it is composed (always first)
geometria.json the vector geometry of every pose (optional)
vista.png the finished drawing on paper, pose 0 (preview)
capas/<layer>-<pose>.png colour atlas of a layer in a pose
capas/<layer>-<pose>-tiempo.png time atlas of that layer in that poseAll images of a lámina have the same size: tamano.ancho × tamano.alto pixels, the
drawing's box times its scale (2 by default).
Colour atlas: 8-bit RGBA PNG with premultiplied alpha (the PNG declares straight
alpha; a reader MUST load it without touching the values: in WebGL,
createImageBitmap(blob, {premultiplyAlpha: 'none', colorSpaceConversion: 'none'}) and
UNPACK_PREMULTIPLY_ALPHA_WEBGL = false). No paper: what has no ink is transparent.
Time atlas: 8-bit RGB PNG. Per pixel, R·256 + G is the instant normalized to 16 bits,
t = (R·256 + G) / 65535, 0 the start and 1 the lámina's duracion; B is 255 where the
layer has ink and 0 elsewhere (then R and G mean nothing). It MUST be sampled without
filtering (nearest or texelFetch). Where two pieces of the same layer cross, the
earliest instant wins.
| Piece | Instant of a pixel |
|---|---|
| ink and colour (pen) | that of the nearest point of its centre line; along the line, inicio + duracion · B⁻¹(arc/length), with B the cubic Bézier (0.55, 0.1, 0.45, 0.95) |
| pencil | the same, linear: inicio + duracion · arc/length |
| plane | a diagonal brush: inicio + 0.7 s · f, f the position along the diagonal of its box |
| note | written left to right, line after line, in 0.9 s |
17.3 Layers
In this order, only those that have something: lapiz (normal), planos (multiply),
tinta (normal), color (multiply, with the misregistration offset), encima (multiply,
with the offset), notas (normal; does not boil: all its poses point to the same image).
17.4 Boil
hervor.variantes poses (3 by default). Pose 0 is the drawing as always; the others have
the same geometry and rhythm and only change the tremor. In playback,
pose = floor(seconds_at_rest · fps + offset) mod variantes, with fps = 8 and the offset
written in the manifest (hash32(semilla(id)) · variantes). While the pen draws, pose 0 is
shown; the boil starts when the drawing is whole (al_reposar: true).
17.5 Revealing
For each layer, bottom to top, with progress from 0 to 1:
float t = (R * 255.0 * 256.0 + G * 255.0) / 65535.0;
float reveal = B > 0.5 ? clamp((progress * 1.03 - t) * 60.0, 0.0, 1.0) : 1.0;
vec4 c = color * reveal; // premultiplied
dst = blend == "multiplicar" ? dst * (1.0 - c.a) + dst * c.rgb
: c.rgb + dst * (1.0 - c.a);dst starts as the paper. The lead of 1.03 guarantees that at progress = 1 everything is
drawn; the slope 60 gives an ink front of 1/60 of the duration. Both numbers are in the
manifest (revelado).
17.6 The manifest
manifiesto.json has: formato ("lamina"), version (1), id (the drawing's id and
seed, ASCII), titulo and descripcion (for screen readers, in the lámina's language),
lengua, tamano (ancho, alto, escala, caja), duracion, papel, alfa
("premultiplicada"), revelado (formula, adelanto 1.03, pendiente 60), hervor
(variantes, fps, desfase, semilla, al_reposar), capas (per layer: nombre,
mezcla, desplazamiento, hierve, and the color and tiempo paths per pose), trazos
(the order of the hand: indice, capa, elemento, pasada, modo (lineal, pluma,
pincel, escritura), inicio, duracion, t0, t1), trayectoria (two tools,
lapiz and pluma, each a list of [ms, x, y, down] in drawing units, milliseconds never
decreasing), geometria (path or null), vista and canon (version, semilla,
serie).
geometria.json gives, per pose and per stroke in the order of the hand: tipo (cinta,
linea, relleno, nota), its layer and indices, how it is painted, inicio,
duracion, modo, the trembled centre line puntos, the accumulated arco, the width
ancho per point, the arrival llegada per point, the contorno, and for notes their
text, position, size, rotation and anchor. Numbers are rounded to thousandths.
17.7 Guarantees
- Determinism. The same lámina comes out byte for byte the same in native Rust, in
Python and in WebAssembly: randomness is the canon's and nothing reads the clock. The
suite gives the SHA-256 of three packed láminas (
laminacases); a producer MUST reproduce them. - Fidelity. Pose 0 is the same drawing as the SVG of the hand-drawing engine (mean difference under half a grey level, from antialiasing).
- Ids in ASCII (§4.5).
17.8 Memory
Each layer in each pose is two textures of width × height × 4 bytes. Readers SHOULD let
producers lower the scale or the variants for large drawings.
17.9 Diagnostics
L001 bad signature, L002 bad index, L003 a listed file is missing, L004 bad or
incomplete manifest, L005 an image of the wrong size, L006 a PNG of the wrong type,
L007 a time atlas whose blue channel is not 0 or 255, L008 layers out of order or with
the wrong blend or pose count, L009 strokes, L010 trajectory, L011 boil or reveal
parameters. The reference validator is conformance/tools/lamina.py.
Part 6. Materias
18. Materias: the pass convention
18.1 What a materia is
A materia turns a clean plane into paper, watercolour, paint, risograph, knitting or a
transition. It is one or more WGSL compute passes in a common convention, so that any
host (the engine's post chain, a library, a tool) runs it as it is. The reference library
is materias/ (Rust + WGSL) and the engine's m.Pass (§19.6).
18.2 Group 0: the convention
Every pass of a plane materia binds exactly:
| Binding | Name | Type |
|---|---|---|
@group(0) @binding(0) | entrada | texture_2d<f32>: the input, linear light, premultiplied, half floats |
@group(0) @binding(1) | muestreo | sampler: bilinear, clamped to the edges |
@group(0) @binding(2) | plano | var<uniform> Plano |
@group(0) @binding(3) | salida | texture_storage_2d<rgba16float, write>: the output, in the same form |
struct Plano {
resolucion: vec2f, // offset 0
fotograma: u32, // 8
tiempo: f32, // 12: scene time in seconds, never the system clock
semilla: u32, // 16
paso: u32, // 20: free for the materia (simulation step, pass number)
_hueco0: u32, // 24
_hueco1: u32, // 28
params: array<vec4f, 4>, // 32: sixteen parameters
} // 96 bytesA materia SHOULD obtain group 0 with #import plano rather than declaring it.
18.3 Groups 1 and 2
What is a materia's own goes in @group(1): textures it reads or writes, buffers. In the
engine, a pass's @group(1) holds only its pictures (a plate, the outgoing plane of a
transition), one sampled texture per binding from 0, in the order given. Persistent
state goes in @group(2): binding 0 the state as it is (a texture), binding 1 the next
(an rgba16float storage texture); before the pass, its step entry runs a fixed number of
times per frame, each from the state to the next and swapping them. A materia MUST NOT bind
other groups, and MUST NOT repeat a binding.
18.4 Determinism
The only time a pass sees is the scene's (plano.tiempo, plano.fotograma). Stateful
materias (watercolour) advance in fixed steps of 60 Hz: two runs give the same pixels.
A held frame steps too; going back in time starts the state again from zero. A materia
MUST NOT read the system clock.
18.5 Modules and chains
#import name pastes a module once (a preprocessor of the library). Shared modules:
canon (palette and hash32, generated from the canon), comun (sRGB and linear, PCG,
value noise, fbm, interleaved gradient noise, sobre), plano (the convention),
campos_papel (the eleven paper fields and color_papel), espectral (16-band
transmittance and spectral upsampling).
A chain of materias is written materia(key=value, …) > materia > …; values are numbers,
names the materia understands (tipo=khadi, tambor1=rosa) or #RRGGBB colours. Entry
points are compute entry points with @workgroup_size; a pass that writes salida
SHOULD take @builtin(global_invocation_id) and handle one pixel per invocation.
18.6 Diagnostics
M001 neither imports plano nor declares the convention's group 0, M002 group 0 is
not exactly the convention's, M003 Plano is not the convention's struct, M004 an
entry point that is not compute or lacks @workgroup_size, M005 own resources outside
groups 1 and 2, or a repeated binding, M006 reads a clock. The reference checker is
conformance/tools/materias.py; compilation and reference frames are tested by the
library's own tests (cargo test --release in materias/).
Part 7. Takes and the public API
19. Takes and the public API
19.1 The engine
The reference engine is a fork of ManimGX (Rust and wgpu, with the Python API of Manim
Community Edition), branch seams. Everything the fork adds is off by default: with
none of it in use, the engine draws exactly as upstream, pixel for pixel on the reference
corpus. The fork's own takes have versions of their own (§19.3), which upstream readers
refuse.
19.2 The take stream
A take records an engine run as the engine's calls: shapes, brushes and images uploaded under their keys, then frames (a view and its records, shown for some frames). It is one stream of messages, little-endian:
message = length:u32 opcode:u8 fields… (length counts the opcode and the fields)
bytes = length:u32 data…The first message MUST be START; a complete take ends with END. Readers MUST reject a take whose first message is not START, whose version they do not know, that contains an unknown opcode, a message longer than what remains, a second START or anything after END.
| Opcode | Message | Fields |
|---|---|---|
| 14 | START | version u32, width u32, height u32, frame rate f64 |
| 1 | PATH | key u64, centroid and area f32 × 6, array keys (points, subpaths) |
| 2 | POINTS | key u64, array key |
| 3 | MESH | key u64, outline u32, block u32, array keys |
| 4 | ROWS | key u64, array key (a brush's rows) |
| 5 | TEXTURE | key u64, width u32, height u32, array key (RGBA8) |
| 6 | GROW | key u64, closed u8, array key |
| 8 | FRAME | repeat u32, view (bytes), records key u64, camera count u32, and per camera: key u64, width u32, height u32, view (bytes), records key u64 |
| 9 | NOTE | bytes: UTF-8 JSON (the plays, sections and captions) |
| 10 | SOUND | bytes: an audio file the player plays beside the frames |
| 11 | ARRAY | key u64, base key u64 (0: none), kind u8, coding u8, bytes (zstd) |
| 12 | END | failed u8 |
| 13 | ENVIRONMENT | id u32, width u32, height u32, array key |
| 15 | POST | bytes: the post chain's description (only in 0x8000_0002, right after START) |
| 16 | MATERIAL | id u32, bytes: WGSL source (in 0x8000_0002; opcode 15 in 0x8000_0001) |
Uploads are held until a frame shows them; arrays are sent once under a key of their kind
and content (an opaque 64-bit digest: readers MUST treat keys as opaque) and coded against
the array they replace: ALONE (0), FIRST (difference from the base), SECOND
(difference from the linear prediction), TAIL (the base is its start), lane by lane and
compressed with zstd, with a keyframe every 32 versions. A FRAME's records are 424 bytes
each (eight keys of 8 bytes, flags, two 3 × 4 matrices, paints, parameters, dash, material,
the materia id u32, the blend u32, a user id u64 and sixteen user floats). The number of
frames of a take is the sum of the FRAME messages' repeats.
19.3 Versions
| Version | Records | Opcodes 15 and 16 | Readers |
|---|---|---|---|
0x8000_0001 | 424 B | 15 = MATERIAL | MUST be read |
0x8000_0002 | 424 B | 15 = POST, 16 = MATERIAL | written by the engine of Tórculo 1.0 |
The range 0x8000_0000 and above is the fork's; upstream's versions are below it. A take
writer of this standard MUST write 0x8000_0002. A new layout or opcode takes the next
version.
19.4 Diagnostics
T001 the first message is not START, T002 unknown version, T003 a message longer than
the take, T004 unknown opcode, T005 repeated START or data after END, T006 POST not
right after START, T007 a NOTE or MATERIAL that is not valid UTF-8 (JSON for NOTE). The
reference reader is conformance/tools/toma.py.
19.5 Determinism of the engine
Shaders see the scene's time (or the frame index), never the clock. The same scene,
rendered twice on the same machine and GPU with the same engine, gives the same bytes;
across GPUs this is not guaranteed, which is why fingerprints are compared with tolerance
(§13.4). Seeds of materials, misregistration and boil come from the canon's semilla of a
piece's name (set_material(…, pieza="c1_09/rosa")), never from a counter.
19.6 The public API
Stability. The interfaces in this section are public in Tórculo 1.0: they change only through an RFC. Everything else in the fork is internal.
Python (import manimgx as m; the API of Manim CE, see the engine's own guide):
| Interface | What |
|---|---|
m.config.post = [m.Papel(), m.Bobina("truca")] | the post chain: passes over every finished frame; the grain lives in the pauses |
m.Pass(shader, entry=None, reach=…, moves=…, params=(), paths=(), pictures=…, estado=None, pasos=…) | any pass in the convention of Part 6, with pictures in @group(1) and persistent state in @group(2) |
m.Papel(plate=None, …), m.Bobina(reel="truca", lut_in=None, lut=None, papel=canon paper, …) | the house's print bath and film |
m.config.compositing = "linear" | compose in linear light (half floats); default sRGB |
mobject.set_material(name, …, pieza=None), m.register_material(name, wgsl, params) | per-object materials (papel, acuarela, riso, and registered ones defining fn materia(m: Materia) -> vec4<f32>) |
| `mobject.set_blend("normal" | "multiplicar")` |
| `mobject.set_clip("mascara" | "dentro" |
m.Trazo(points, widths, tiempos=None, grano=None), m.Trazo.de_pluma(stroke) | the variable-width pen stroke, drawn by Create at the pace of the hand |
m.Hervor(drawing, poses=3, fps=8, desfase=True, gpu=False) | the line that lives at rest |
| `m.sidecar(pliego | tiempos.json |
Command line: manimgx render scene.py [--codec h264 | hevc | prores | prores4444] [--take] [-r WxH] [--fps N] [--sound-events]. HEVC Main10 and ProRes use VideoToolbox
(macOS); ProRes 4444 carries alpha, unpremultiplied. Binaries that include x264
(--codec h264) are GPL; builds with VideoToolbox only are not (DECISIONES.md).
Strict errors are the default: malformed LaTeX and Typst warnings fail at the line of the
scene; --no-strict turns them into warnings.
Rust: the crate manimgx-render (Replay::read(&bytes), replay.render(i) to RGBA,
Gpu::from_device(…) to draw on another application's device).
Web: <manimgx-film src="Scene.take" autoplay> plays a take with WebGPU, without Python;
it needs float32 blending and depth32float-stencil8 (Chrome and Edge 113 and later,
Safari 26).
20. Security considerations
- Compiling MUST NOT execute project code. A compiler checks and compiles a pliego and reads its bestiary without running it (§12). A packager discovers files the same way (§14.1).
- Rendering executes the bestiary. A pliego with
PYTHONorPIEZASruns that code when it is rendered: an interpreter MUST treat such a pliego as a program, and a viewer of untrusted projects MUST NOT render them outside a sandbox. A servilleta or a pliego without a bestiary executes nothing but the engine. - Packages can carry dangerous paths (§14.2): readers MUST reject them before writing anything, verify hashes, and bound the total uncompressed size.
- Takes carry shader source (MATERIAL, POST) that runs on the GPU. WebGPU and wgpu validate it, but a hostile take can still exhaust resources: players SHOULD bound the number of materials, the size of arrays and textures, and the decompressed size of each ARRAY, and MUST reject a take that breaks §19.2.
- Láminas are bounded by their manifest; a reader SHOULD refuse a lámina whose image sizes or layer counts would exceed its memory budget (§17.8).
- No network while rendering. Voices, music and effects come from the project; an interpreter MUST NOT call a paid or remote service while rendering.
21. Privacy considerations
- Voice recordings are personal data of whoever speaks. A package carries them; its manifest says how many takes of each method it has, never who recorded them unless the cast declares it.
- Absolute paths reveal user names and folder structures (
/Users/name/Library/Caches/…). Sidecars SHOULD use relative paths, and packages MUST (§14.3). - The manifest records commits and versions of the tools, not the machine.
22. Versioning and compatibility
- The constitution of compatibility: a pliego that compiled once compiles always. The
epoch is declared in the preamble (
MESA v2); a compiler MUST compile every pliego of every epoch it claims, and SHOULD read epoch 1 (SPEC-MESA.md) as legacy. The vocabulary of an epoch is frozen, reserved words included. - A new epoch MAY add words and lines; it MUST NOT change the meaning of a valid pliego of an earlier epoch. Removing a word is only possible by declaring it legacy in a new epoch, and compilers keep accepting it for pliegos that declare the old one.
- The IR is not versioned (§10.1): interpreters MUST ignore unknown fields and verbs.
mesapackmajors are incompatible (mesapack 2would be another format); minors (mesapack 1.1) only add members readers can ignore.- Lámina version 1 is written in the signature and the manifest; a new layout takes version 2.
- Take versions are listed in §19.3.
- The canon's
versionchanges when any value changes; generated files carry it. - The specification is numbered MAJOR.MINOR with editorial releases (
spec-v1.0.0); its number and the libraries' numbers are independent (governance/VERSIONING.md).
23. Media types and file identification
Proposed, not registered:
| Extension | Media type | Identification |
|---|---|---|
.mesa | text/vnd.torculo.mesa; charset=utf-8 | UTF-8 text whose first non-comment line starts with MESA (or prose: a servilleta) |
.mesapack | application/vnd.torculo.mesapack+zip | a ZIP with MANIFIESTO.json whose formato starts with mesapack |
.lamina | application/vnd.torculo.lamina | the signature LAMINA\0\x01 (a directory .lamina/ has manifiesto.json) |
.take | application/vnd.torculo.take | first message START (opcode 14) with a version from 0x8000_0001 |
.tiempos.json | application/json | beside a pliego with the same stem |
24. Internationalization
The language of Tórculo is Spanish: keywords, vocabularies and diagnostics are Spanish words, and diacritics are significant where Spanish makes them so (§4.5, reserved words). Text on screen is whatever the author writes, in any script, normalized to NFC. Compilers SHOULD write their messages in Spanish and MAY offer translations; codes are language-independent. A localized keyword set (for example, English keywords mapped to the same IR) would be a new dialect and needs an RFC; the IR, being the contract, would not change.
Appendix A. Closed vocabularies
Generated from spec/vocabularios/vocabularios.json, which is extracted from the reference
parser. Each vocabulary gives its profile, the structure it comes from and its words in
canonical form (without accents, §4.5); a compiler accepts them with or without accents.
Profile: core
ACCION_FICHA (15 words; Source: formato.aspecto.ACCIONES)
anda · aplaude · baila · cae · celebra · corre · gesticula · gira el dial · grita · habla · recoge · salta · se levanta · senala · señala
AFECTO (8 words; Source: formato.vocabulario.AFECTOS)
contenido · euforico · exhausto · jugueton · nervioso · seco · sereno · solemne
ALTURA (5 words; Source: formato.continuidad.ALTURAS)
cenital · contrapicado · nadir · normal · picado
ANCLA (5 words; Source: formato.vocabulario.ANCLAS)
bordado · celo · chincheta · esquineras · washi
ARCO (6 words; Source: formato.vocabulario.ARCOS)
espiral · letania · pregunta→respuesta · ruina · tesis→antitesis→sintesis · viaje y vuelta
AUTORIDAD (34 words; Source: formato.precedencia.AUTORIDADES)
afecto · alias · archivo · capitulo · caracter · compositor · cuerpo · declarado · escena · estrato · exacto · gesto · identidad · legibilidad · lejania · ligadura · llegada · luz · manera · mano · mano_taller · materia · orden_mano · orden_mundo · paleta · papel · partitura · proscenio · semilla · slot · texto_difuso · texto_exacto · tope · ventana
AVISO_CONTINUIDAD (5 words; Source: formato.continuidad.AVISOS)
RACCORD DE DIRECCIÓN · RACCORD DE ESTADO · RACCORD DE MIRADA · SALTO DE EJE · SALTO DE TALLA
BOBINA (3 words; Source: formato.aspecto.BOBINAS)
noticiario · sin grano · truca
CLAVE_MANO (7 words; Source: formato.taller.MANO_BASE)
cansa · entra · granulado · precision · pulso · sale · toca la truca
CLAVE_VIS (68 words; Source: visualizaciones.CATALOGO)
alfiler · ancla · arbol · balanza · barras · brujula · bucle · cadena · caja · cancelacion · ciclo · comparacion · constelacion · convergencia · cuadrante · cuenta · curva · dado · diana · dispersion · distribucion · domino · ecuacion · ejes · embudo · engranaje · escalera · espectro · espiral · flecha de proceso · fraccion · globo · grieta · huella · interruptor · isla · jerarquia · laberinto · linea temporal · lista tachada · lupa · mapa · medidor · moneda · monton · multitud · onda · orbita · papeleta · pendulo · pila · ping pong · porcentaje · proceso · puente · recorrido · red · reloj · resta · semaforo · suma · telarana · teorema · termometro · titere · venn · versus · votos
DESREGISTRO (2 words; Source: formato.aspecto.DESREGISTROS)
desregistrada · en registro
DIMENSION (10 words; Source: formato.precedencia.DIMENSIONES)
color_estrato · curva · fondo · nombre · sitio · sombra · tamaño · tiempo · velocidad_estrato · z
DIRECCION_LUZ (5 words; Source: formato.vocabulario.DIRECCIONES_LUZ)
cenital · de atras · de frente · de la derecha · de la izquierda
DISPOSICION (8 words; Source: formato.vocabulario.DISPOSICIONES)
amontonados · como flores · en abanico · en columna · en corro · en fila · en fila holgados · en rejilla
DUREZA (2 words; Source: formato.vocabulario.DUREZAS)
blanda · dura
ESPEJO_LADO (2 words; Source: formato.aspecto.ESPEJO_LADOS)
de la derecha · de la izquierda
EVENTO (163 words; Source: formato.vocabulario.EVENTOS)
a la vez · aire al reves · amanece · anochece · arranca de golpe · asoma · barre · barrido · barrido a la derecha · barrido a la izquierda · barrido hacia abajo · barrido hacia arriba · barrido temporal · cada voz a su lado · camara lenta · camara lenta a saltos · capitulo · chasquido · congela · congela la imagen · continua · corta · corta en la accion · cortado por la barbilla · cortado por la frente · cortinilla de tijera · cruza el eje · cuadro vacio · deja posar · demasiado cerca de · demasiado rapido · desenfoque de pasada · destellan los focos · dura · el clip se agranda y se va · el color se apaga · el cuadro gira · el cuadro se endereza · el fotograma se descarrila · el horizonte se endereza · el horizonte se inclina · el montaje se acelera · el que habla fuera de campo · el rio mide · el soporte empeora · el soporte se deshace · el soporte se limpia · empapela · encadena · entra de golpe · entra la musica · espectrograma de · espera al clip · estalla el color · florece · formato · fotograma de impacto · fotograma en blanco · funde a blanco · funde a negro · funde desde blanco · funde desde negro · gigante · gran angular · iris · la camara atraviesa · la camara baja · la camara deja de respirar · la camara entra en · la camara gira alrededor de · la camara mira desde dentro de · la camara no para · la camara respira con · la camara sale de · la camara se acerca a · la camara se aleja · la camara sube · la camara va a · la camara va montada en · la camara va pegada a · la camara vuelve · la costura se mueve hacia · la intensidad cae a · la intensidad salta a · la intensidad sube a · la linea se endereza · la linea se inclina · la linea se mueve · la linea se rompe · la luz sube con · la mancha deja · la mano tapa · la musica se apaga · la musica se corta · la pista se desborda · la pista vuelve · la tela se desenreda · la tela se enreda · la tension cae · la tension rompe · la tension se mantiene · la tension sube · la tinta lo cubre todo · la voz se vuelve radio · las bandas bajan · las bandas suben · las voces se juntan en el centro · lente normal · mezcla los registros · mirando fuera de campo · montaje al pulso · montaje al ritmo de las palabras · ojo de pez · pasa pagina · pasa por delante · plano holandes · plano secuencia por · queda · rampa de velocidad · respira · retencion larga · revienta · rio tipografico · rompe el eje · salta · salto axial a · se desteje · se junta la pantalla · se lava · se moja · se para en seco · se parte la pantalla · se quema · se rasga el papel · se rasga la banda · se rompe el espejo · se sale del cuadro · se seca · se sostiene · se teje · se van las perforaciones · se ven las perforaciones · seco · silencio · silencio de verdad · simultaneo en abanico · simultaneo en abanico que gira · simultaneo en rejilla · sin leer · sin respiro · sintoniza · teleobjetivo · temblor · tiempo bala sobre · todo a la vez · todo se para menos · triple salto axial a · un solo plano · velocidad normal · vertigo · vertigo al reves · vuelve el espejo · zoom de golpe
Reserved: none.
EVENTO_A_CAMPO (8 words; Source: formato.vocabulario.EVENTO_A_CAMPO)
Mapping: congela → congela_mano · continua → continua · cortado por la barbilla → salta · cortado por la frente → salta · cruza el eje → cruza_eje · demasiado cerca de → salta · rompe el eje → cruza_eje · salta → salta
EXPRESION (9 words; Source: formato.aspecto.EXPRESIONES)
duda · se asombra · se asusta · se calma · se enfada · se entristece · se pone serio · se rie · sonrie
FAMILIA_TALLER (10 words; Source: formato.taller.TALLER_BASE)
ancla · bano · canto · fantasma · materia · papel · reticula · sombra · tinta · vida
FORMATO (6 words; Source: formato.aspecto.FORMATOS)
16:9 · 1:1 · 2,39:1 · 4:3 · 4:5 · 9:16
FORMATO_MODO (2 words; Source: formato.aspecto.FORMATO_MODOS)
bandas de papel · de television
FRENTE (5 words; Source: formato.continuidad.FRENTES)
escorzo · espalda · frontal · perfil · tres cuartos
FUNCION (11 words; Source: formato.vocabulario.FUNCIONES)
apertura · cartel · contrapunto · digresion · eco · giro · ilustracion · prueba · remate · respiro · tesis
GESTO_MARCA (4 words; Source: formato.vocabulario.GESTO_MARCA)
rodea · senala · subraya · tacha
GRANULADO (4 words; Source: movimiento.GRANULADOS)
a doses · a pulso · a treses · a unos
HERVOR (3 words; Source: formato.aspecto.HERVORES)
dibujado · no · suave
HORA (5 words; Source: formato.vocabulario.HORAS)
amanece · atardece · diurna · mediodia · nocturna
LADO (4 words; Source: formato.vocabulario.LADOS)
abajo · arriba · derecha · izquierda
LEJANIA (8 words, ordered; Source: viaje.LEJANIAS)
al pie · al paso · cerca · a media distancia · lejos · al fondo · en el horizonte · en el cielo
LINEA_UNIDAD_ASPECTO (20 words; Source: formato.aspecto.UNIDAD)
AMBIENTE · BANDA · BOBINA · CAMA · EFECTOS · ESPACIO · ESPEJO · FORMATO · HERVOR · JINGLE · MATERIA · MEZCLA · MONTAJE · MÚSICA · PANTALLA PARTIDA · REPITE · RIO TIPOGRAFICO · RÍO TIPOGRÁFICO · SIMULTANEO · SIMULTÁNEO
MANERA (15 words; Source: movimiento.MANERAS)
a la deriva · a regañadientes · a tirones · con anticipación · con cuidado · de golpe · de un tirón · despacio · en volandas · ligero · pesado · resuelto · rozando · sin ganas · titubeante
MATERIA (7 words; Source: formato.aspecto.MATERIAS)
acuarela · ninguna · papel · pincel · risografia · tejido · tinta
MODO (3 words; Source: formato.continuidad.MODOS)
cartel · documento · mundo
MONTAJE (6 words; Source: formato.aspecto.MONTAJES)
al pulso · al ritmo de las palabras · cada vez mas cerca · la camara no para · mezcla · se acelera
MOVIMIENTO_MUNDO (4 words; Source: formato.vocabulario.MOVIMIENTO_MUNDO)
acelera · avanza · frena · para
NOMBRE_SECCION (6 words; Source: formato.taller.SECCIONES)
BESTIARIO · CASCADA · MANO · MONTAJE · REPARTO · TALLER
ORDEN_TRUCA (9 words; Source: formato.vocabulario.ORDEN_TRUCA)
baja · busca a · encuadra a · se acerca · se acerca a · se queda · sigue a · sube · viaja con
PALABRA_RESERVADA (76 words; Source: formato.vocabulario.PALABRAS_RESERVADAS)
a · al · alias · ancla · archivo · arco · arriba · bajo · bestiario · camino · canta · cascada · clip · con · contenido · de · del · delante · dentro · deriva · detras · di · eco · eje · el · en · escenario · fantasma · foco · fondo · formato · foto · fuera · hilo · junto · juntos · la · las · letra · letrero · los · luz · mano · marca · mesa · mientras · montaje · motivo · mundo · musica · nota · o · para · personaje · pica · pie · pon · por · prensada · python · que · recorte · relojes · reparto · revelado · se · sobre · sonido · su · sus · taller · terminal · un · una · ver · y
PAPEL (11 words; Source: formato.aspecto.PAPELES)
cuaderno · escolar · grano fino · khadi · kraft · lienzo · satinado · tintado · torchon · verjurado · washi
PARTE_CUERPO (7 words; Source: formato.vocabulario.PARTES_CUERPO)
el hombro · el pecho · el regazo · la cabeza · la espalda · las manos · los pies
PLANO_DE (11 words; Source: formato.vocabulario.PLANO_DE)
Mapping: apertura → orla · cartel → cartel · contrapunto → contraplano · digresion → mapa · eco → documento · giro → primerisimo · ilustracion → contraplano · prueba → documento · remate → primerisimo · respiro → general · tesis → documento
PLANTILLA (8 words; Source: formato.vocabulario.PLANTILLAS)
cartel · contraplano · documento · general · mapa · nocturno · orla · primerisimo
RASTRO (4 words; Source: formato.aspecto.RASTROS)
con borron · con estela · con lineas de fuerza · en cronofotografia
REGISTRO_LETRERO (6 words; Source: formato.vocabulario.REGISTROS_LETRERO)
cartulina · cita · cita maquina · cita moderna · mano · rescate
REGISTRO_LETRERO_RESERVADO (3 words; Source: formato.vocabulario.REGISTROS_LETRERO_RESERVADOS)
dymo · maquina · tira
REGISTRO_MATERIA (4 words; Source: materia.REGISTROS)
fotografico · pintado · recorte · tinta
REGISTRO_MOV (1 words; Source: movimiento.REGISTROS)
en dos
RIO_MODO (3 words; Source: formato.aspecto.RIO_MODOS)
a pantalla completa · en fila · en libertad
SENTIDO (2 words; Source: formato.vocabulario.SENTIDOS)
de espaldas · de frente
SIMULTANEO (3 words; Source: formato.aspecto.SIMULTANEOS)
en abanico · en abanico que gira · en rejilla
SUSTRATO (14 words; Source: pieza.SUSTRATOS)
acetato · cartulina · dymo · ficha · foto · kraft · milimetrado · papel · periodico · pijama · polaroid · postit · tira · vegetal
TALLA (7 words, ordered; Source: formato.continuidad.TALLAS)
general · conjunto · medio · americano · corto · primer · detalle
TAMBOR (7 words; Source: formato.vocabulario.TAMBORES_V)
ambar · bermellon · naranja · rosa · ultramar · verde · violeta
TAMBOR_RISO (10 words; Source: formato.aspecto.TAMBORES_RISO)
ambar · azurita · bermellon · humo · naranja · rosa · tinta · ultramar · verde · violeta
TENSION (4 words; Source: formato.vocabulario.TENSIONES)
cae · mantiene · rompe · sube
TRAMA (3 words; Source: formato.aspecto.TRAMAS)
de grano · de lineas · de puntos
TRANSICION (16 words; Source: formato.vocabulario.TRANSICIONES)
chasquido · corta · corta en la accion · cortinilla de tijera · desenfoque de pasada · encadena · entra de golpe · funde a blanco · funde a negro · funde desde blanco · funde desde negro · iris · la mano tapa · pasa pagina · se quema · sintoniza
TRAYECTO (16 words; Source: movimiento.TRAYECTOS)
a saltos · cayendo · en arco · en curva · en espiral · en zigzag · flotando · fuera de campo · girando · por el borde · por el camino · por el suelo · rebotando · recto · resbalando · rodando
VENTANA (2 words; Source: movimiento.VENTANAS)
hasta decir · mientras
VERBO_MOV (24 words; Source: movimiento.VERBOS)
baja · cae · camina · corre · cruza · entra · esquiva · flota · gira · rebota · resbala · rueda · sale · salta · se apea · se encaja · se levanta · se sienta · sube · tiembla · tropieza · va · viaja · vuela
VERBO_RELACIONAL (11 words; Source: movimiento.VERBOS_RELACIONALES)
agarra · alcanza · arrastra · cuelga · empuja · esquiva · huye · orbita · se apoya · sigue · suelta
VISTA (5 words; Source: formato.aspecto.VISTAS)
de espaldas · de frente · de perfil · de tres cuartos · de tres cuartos de espaldas
Profile: sound
ESPACIO (5 words; Source: formato.aspecto.ESPACIOS_SALA)
estadio · estudio · patio · radio · seco
MEZCLA (4 words; Source: formato.aspecto.MEZCLAS)
con stems · para cine · para la web · sin stems
VOZ (6 words; Source: formato.sonido.VOCES)
cita · cita_f · cita_f2 · cita_f3 · cita_m2 · narrador
Profile: cartel
BOSQUE (5 words; Source: formato.cartel.BOSQUES)
brazos · brazos y punos · manos · manos abiertas · punos
COLOR_CARTEL (16 words; Source: formato.cartel.COLORES)
amarillo · arena · azul · blanco · celeste · crema · lila · minio · morado · naranja · negro · rojo · rosa · tinta · ultramar · verde
COMPOSICION (15 words; Source: formato.cartel.COMPOSICIONES)
campo a sangre · campo en bandas · campo partido en diagonal · centro vacio · columna a sangre a la derecha · columna a sangre a la izquierda · diagonal de abajo a la izquierda arriba a la derecha · diagonal de arriba a la izquierda abajo a la derecha · disco detras · en silueta · enorme · figura delante de la letra · la letra corta a la figura · la letra delante de la figura · tercios
CORTE (12 words; Source: formato.cartel.CORTES)
cortada por abajo · cortada por arriba · cortada por el borde · cortada por la derecha · cortada por la frente · cortada por la izquierda · cortado por abajo · cortado por arriba · cortado por el borde · cortado por la derecha · cortado por la frente · cortado por la izquierda
DISPOSICION_SIGNO (6 words; Source: formato.cartel.DISPOSICIONES)
a sangre · en abanico · en columna · en escalera · girada · rota por el borde
EVENTO_CARTEL (5 words; Source: formato.cartel.EVENTOS)
la costura se mueve hacia · la mancha deja · la tela se desenreda · la tela se enreda · se desteje
FORMA_PALABRA (5 words; Source: formato.cartel.FORMAS)
el patio · un marco · un muro · una columna · una porteria
LINEA_UNIDAD_CARTEL (3 words; Source: formato.cartel.UNIDAD)
CARTEL · PALETA · PARTITURA
PAPEL_SIGNO (9 words; Source: formato.cartel.ROLES)
barandilla · cielo · cuchilla · mascara · muro · persiana · porteria · suelo · ventana
SITIO_SIGNO (5 words; Source: formato.cartel.SITIOS)
a la derecha · a la izquierda · abajo · arriba · en el centro
TIPO_LETRA (6 words; Source: formato.cartel.TIPOS)
anton · la serifa de pretexto · league gothic · letra de mano · maquina de escribir · serifa
VERBO_SIGNO (14 words; Source: formato.cartel.VERBOS_SIGNO)
cae · caen · se abre · se abren · se apila · se apilan · se estampa · se estampan · se rompe · se rompen · se separa · se separan · se va · se van
Profile: oído
DIRECCION_FUENTE (4 words; Source: formato.oye.DIRECCIONES_LUZ)
desde abajo · desde arriba · desde la derecha · desde la izquierda
EVENTO_OYE (14 words; Source: formato.oye.EVENTOS_OYE)
destellan los focos · el color se apaga · el rio mide · el soporte empeora · el soporte se deshace · el soporte se limpia · espectrograma de · estalla el color · la camara deja de respirar · la camara respira con · la intensidad cae a · la intensidad salta a · la intensidad sube a · la luz sube con
INTENSIDAD (11 words, ordered; Source: formato.oye.INTENSIDADES)
nula · quieta · serena · templada · viva · agitada · tensa · encendida · desatada · furiosa · rota
PISTA (5 words; Source: formato.oye.PISTAS)
la cama · la musica · la radio · la voz · los efectos
SOPORTE (5 words, ordered; Source: formato.oye.SOPORTES)
limpio · usado · gastado · sucio · roto
Profile: cámara
BANDA_CUADRO (4 words; Source: formato.camara.BANDAS)
de abajo · de arriba · de la derecha · de la izquierda
BLANCO_CADENCIA (6 words; Source: formato.camara.BLANCOS_CADENCIA)
el fondo · la camara · la letra · las figuras · lo de delante · todo
CADENCIA (4 words, ordered; Source: formato.camara.CADENCIAS)
en uno · en dos · en tres · en cuatro
DISTANCIA (9 words, ordered; Source: formato.camara.DISTANCIAS)
delante · al pie · cerca · al paso · a media distancia · lejos · al fondo · en el horizonte · en el cielo
ENCUADRE_INCOMODO (7 words; Source: formato.camara.INCOMODOS)
aire al reves · cortado por la barbilla · cortado por la frente · cuadro vacio · demasiado cerca de · el que habla fuera de campo · mirando fuera de campo
EVENTO_CAMARA (47 words; Source: formato.camara.EVENTOS_CAMARA)
barrido temporal · camara lenta a saltos · el cuadro gira · el cuadro se endereza · el fotograma se descarrila · el horizonte se endereza · el horizonte se inclina · fotograma de impacto · gran angular · la camara atraviesa · la camara baja · la camara entra en · la camara gira alrededor de · la camara mira desde dentro de · la camara sale de · la camara se acerca a · la camara se aleja · la camara sube · la camara va a · la camara va montada en · la linea se endereza · la linea se inclina · la linea se mueve · la linea se rompe · la pista se desborda · la pista vuelve · la tension cae · la tension rompe · la tension se mantiene · la tension sube · las bandas bajan · las bandas suben · lente normal · ojo de pez · pasa por delante · plano secuencia por · rampa de velocidad · salto axial a · se rasga la banda · se van las perforaciones · se ven las perforaciones · teleobjetivo · tiempo bala sobre · todo se para menos · triple salto axial a · vertigo · vertigo al reves
GOLPE (2 words; Source: formato.camara.GOLPES)
con borron · con impacto
HORIZONTE (3 words; Source: formato.camara.HORIZONTES)
gira · recto · se inclina
LENTE (4 words; Source: formato.camara.LENTES)
gran angular · normal · ojo de pez · teleobjetivo
LINEA_UNIDAD_CAMARA (7 words; Source: formato.camara.UNIDAD)
CADENCIA · CAMARA · CÁMARA · GOLPES · HORIZONTE · PISTA OPTICA · PISTA ÓPTICA
MANO_CAMARA (2 words; Source: formato.camara.MANOS)
al hombro · en tripode
PESO_CAMARA (3 words; Source: formato.camara.PESOS)
con masa · ligera · pesada
PISTA_LADO (2 words; Source: formato.camara.PISTA_LADOS)
a la derecha · a la izquierda
PROFUNDIDAD (2 words; Source: formato.camara.PROFUNDIDADES)
poca profundidad · profundidad total
ROTURA (6 words; Source: formato.camara.ROTURAS)
demasiado rapido · rompe el eje · se sale del cuadro · sin leer · sin respiro · todo a la vez
Appendix B. Grammar
The complete grammar is spec/gramatica/mesa.ebnf, normative, reproduced here.
(* Tórculo 1.0, part 1: the grammar of the pliego language (.mesa), epoch 2.
Normative. Notation (SPEC §1.4):
NAME nonterminal; every nonterminal in capitals that is not defined
here is a closed vocabulary of Appendix A (spec/vocabularios/
vocabularios.json), and that correspondence is exhaustive.
"literal" literal text, compared after normalization (SPEC §4.5),
except reserved words, which are compared as written.
A | B alternative [ A ] optional { A } zero or more
TEXT any characters up to the end of the line
NL end of line
IDENT identifier (SPEC §4.5)
NUMBER integer or decimal with a point, optional sign
QUOTE "«" TEXT-WITHOUT-» "»" (U+00AB … U+00BB; straight quotes are not equivalent)
· the field separator, U+00B7 MIDDLE DOT, with optional spaces around it
Analysis is line oriented: each line is classified by its prefix and the
prefix always wins (SPEC §5.1). Only section blocks and "dentro:" span lines.
Blank lines separate clips. *)
PLIEGO = PREAMBLE { CHAPTER } [ END ] ;
PREAMBLE = { PREAMBLE-LINE | UNIT-LINE | SECTION | COMMENT } ;
(* ---------- preamble ---------- *)
PREAMBLE-LINE = "MESA" [ "v" NUMBER ] TITLE
| "formato" PROPERTY { "·" PROPERTY }
| "ARCO" ARCO
| "MOTIVO" QUOTE [ "—" TEXT ]
| "ECO" IDENT ( "→" | "->" ) IDENT
| "REPARTO" SPEAKER ":" TAMBOR [ "," VOZ ] [ "," VOICE-COLOUR ] [ "," SIDE ] [ "," "alias:" ALIAS { "·" ALIAS } ]
| "PERSONAJE" IDENT "—" TEXT
| "LETRA" PATH
| "PYTHON" PATH
| "ARCHIVO" KEY { "·" KEY }
| "FANTASMA" ( "foto" | "texto" | "numeral" ) NUMBER
| "RELOJES" IDENT NUMBER { IDENT NUMBER }
| "SONIDO" TEXT
| "EFECTOS" PATH (* sound profile: folder of effects and ambiences *)
| "BANDA" PATH (* sound profile: folder of music cues *)
| "MEZCLA" MEZCLA { "·" MEZCLA } (* sound profile: "para la web" | "para cine"; "con stems" | "sin stems" *)
| "PARTITURA" PATH (* cartel profile *)
| "SOPORTE" SOPORTE (* oído profile *)
| "el dial es la línea de tiempo" (* oído profile *)
| "baño" BOBINA ;
PROPERTY = ASPECT-RATIO | "sala" ( "crema" | "pizarra" ) | "tirada" ( "borrador" | "definitiva" )
| "página desnuda" | "en dos" ;
ASPECT-RATIO = FORMATO ;
VOICE-COLOUR = "con radio" | "seca" ;
SIDE = "a la izquierda" | "a la derecha" | "al centro" ;
(* ---------- sections: the mirror law (SPEC §5.3) ---------- *)
SECTION = BLOCK | IMPORT ;
BLOCK = "#" NOMBRE-SECCION [ IDENT ] NL { SECTION-LINE } "#FIN" ;
IMPORT = NOMBRE-SECCION PATH ;
SECTION-LINE = FAMILY [ VALUE ] { "·" FIELD } ;
FIELD = KEY ( " " | ": " ) VALUE ; (* keys of several words take a colon *)
FAMILY = FAMILIA-TALLER | CLAVE-MANO ;
(* ---------- chapter and scene ---------- *)
CHAPTER = CHAPTER-HEAD { UNIT-LINE | SECTION | COMMENT } { SCENE | CLIP } ;
CHAPTER-HEAD = "==" TITLE { "·" CHAPTER-ATTR } { "=" } ;
CHAPTER-ATTR = "tensión" TENSION | "nº" NUMBER | "tambor" TAMBOR | "gigante" WORD
| "plano fijo" PLANTILLA | "tramo" NUMBER ( "→" | "->" | "a" ) NUMBER
| "nocturno" | "diurno" ;
SCENE = SCENE-HEAD { UNIT-LINE | SECTION | COMMENT } { CLIP } ;
SCENE-HEAD = "--" TITLE [ "·" HORA ] "--" ;
(* Unit lines are valid in the preamble (whole pliego), a chapter or a scene;
the scene prevails over the chapter, the chapter over the preamble. Several
are also valid inside a clip, for that shot only (SPEC §5.6). *)
UNIT-LINE = CORE-UNIT-LINE | ASPECT-UNIT-LINE | SOUND-UNIT-LINE
| CARTEL-UNIT-LINE | OIDO-UNIT-LINE | CAMERA-UNIT-LINE ;
CORE-UNIT-LINE = "EJE" "de" IDENT "a" IDENT
| "LUZ" DIRECCION-LUZ { "·" ( DUREZA | "rasante" ) }
| "MUNDO" MOVIMIENTO-MUNDO [ NUMBER ] [ "·" SENTIDO ]
| "FONDO" KEY { ARG } "·" LEJANIA [ "·" NUMBER ]
| "DELANTE" KEY { ARG } [ "·" LEJANIA ] [ "·" "cada" NUMBER ]
| "ESCENARIO" TEXT
| "TABLAS" { "·" ( HORA | "suelo" NUMBER | "a sangre" | "ancho" NUMBER | "alto" NUMBER ) }
| "ARCHIVO" KEY { "·" KEY }
| "REPITE" QUOTE ;
ASPECT-UNIT-LINE= "MATERIA" MATERIA-SPEC
| "BOBINA" BOBINA
| "FORMATO" FORMATO { "·" FORMATO-MODO }
| "ESPEJO" [ ESPEJO-LADO ]
| "PANTALLA PARTIDA" { "·" ( "con un espejo en medio" | "que se miran" | "desigual" | "inclinada" ) }
| "RÍO TIPOGRÁFICO" [ "·" ( RIO-MODO | "no" ) ]
| "SIMULTÁNEO" SIMULTANEO
| "MONTAJE" MONTAJE-SPEC { "·" MONTAJE-SPEC }
| "HERVOR" HERVOR ;
MATERIA-SPEC = "papel" PAPEL
| "acuarela" [ ON-PAPER ]
| "risografía" TAMBOR-RISO "y" TAMBOR-RISO [ "y" TAMBOR-RISO ]
{ "·" ( DESREGISTRO | "trama" TRAMA ) } [ ON-PAPER ]
| "pincel" [ ON-PAPER ] | "tejido" [ TAMBOR-RISO ] | "tinta" [ ON-PAPER ] | "ninguna" ;
ON-PAPER = "sobre papel" PAPEL ;
MONTAJE-SPEC = MONTAJE | "mezcla" QUOTE { "·" QUOTE } ;
SOUND-UNIT-LINE = "MÚSICA" ( CUE | "ninguna" )
| "AMBIENTE" EFFECT-NAME { "·" EFFECT-NAME }
| "ESPACIO" ESPACIO
| "CAMA" EFFECT-NAME | "JINGLE" EFFECT-NAME ;
CARTEL-UNIT-LINE= "PALETA" COLOR-CARTEL "," COLOR-CARTEL "y" COLOR-CARTEL
| "CARTEL" COMPOSICION { "·" COMPOSICION } ;
OIDO-UNIT-LINE = "INTENSIDAD" ( INTENSIDAD | "de" INTENSIDAD "a" INTENSIDAD ) { "·" ( "extraña" | "con" PISTA ) }
| "SOPORTE" SOPORTE
| "COLOR" ( "monocromo" [ TAMBOR-RISO ] | "pleno" )
| "LUZ" ( "de" ( QUOTE | "los focos" ) { "·" ( DIRECCION-FUENTE | TAMBOR-RISO | "en contraluz" ) }
| "plana" [ "·" "de estudio" ] )
| "la cámara respira con" PISTA | "el río mide la voz" | "la luz sube con" PISTA ;
CAMERA-UNIT-LINE= ( "CÁMARA" | "CAMARA" ) CAMERA-SPEC { "·" CAMERA-SPEC }
| "HORIZONTE" HORIZONTE
| "CADENCIA" BLANCO-CADENCIA CADENCIA { "·" BLANCO-CADENCIA CADENCIA }
| "GOLPES" GOLPE { "·" GOLPE }
| "PISTA ÓPTICA" [ PISTA-LADO ] ;
CAMERA-SPEC = LENTE | PESO-CAMARA | MANO-CAMARA | PROFUNDIDAD ;
(* ---------- clip ---------- *)
CLIP = CLIP-HEAD { CLIP-LINE } ;
CLIP-HEAD = "*" [ BEAT-ID ] ( FUNCION | SHOT ) [ "·" AFECTO ] [ "(máquina)" ] ;
BEAT-ID = IDENT ; (* optional, stable id for the sidecar (e.g. r01_02) *)
SHOT = { TALLA | ALTURA | FRENTE | MODO } [ "de" [ ARTICLE ] IDENT ] ;
CLIP-LINE = CONTENT | PIECE | REAL-VIDEO | PLACEMENT | SCENE-VERB | MAP | MOVEMENT | CAMERA
| JOURNEY | SOUND | EVENT | NESTING | UNIT-LINE | SIGN | WEAVE | CHARACTER | COMMENT ;
CONTENT = "di" [ "(" VOZ ")" ] ":" TEXT
| SPEAKER-LIST ":" TEXT (* the speaker MUST be declared (REPARTO, PERSONAJE) *)
| "letrero" [ "(" REGISTRO-LETRERO ")" ] ":" TEXT { "/" TEXT }
| "terminal:" TEXT | "canta:" TEXT | "contenido (máquina):" TEXT
| QUOTE (* a shout: at most one per clip *)
| TEXT ; (* prose: the beat's content *)
SPEAKER-LIST = SPEAKER { "/" SPEAKER } ; (* "VECINO / LOCUTOR": the split sentence *)
PIECE = "pon:" TIPO-PIEZA QUOTE { "·" PIECE-ATTR }
| ( "foto" | "recorte" | "prensada" ) ":" KEY
| "ver:" CLAVE-VIS [ "—" BODY ]
| "pica:" KEY [ "en" NUMBER ]
| "python:" NAME { ARG | NAME "=" VALUE } { "·" PIECE-SIZE | "·" CORTE | "·" "sin leer" }
| ( "arriba" | "pie" | "nota" ) ":" TEXT
| "marca:" GESTO-MARCA QUOTE ;
PIECE-ATTR = NUMBER | "id" PATH | TAMBOR ;
PIECE-SIZE = "grande" | "enorme" | "gigante" | "a sangre" ;
REAL-VIDEO = "clip" [ " de fondo" | " mudo" ] ":" PATH [ "de" TIME "a" TIME ] ;
TIME = [ DIGITS ":" ] DIGITS [ "." DIGITS ] ;
PLACEMENT = "en" NUMBER NUMBER ":" CLIP-LINE
| "en" PARTE-CUERPO "de" IDENT [ NUMBER NUMBER ] ":" CLIP-LINE
| RELATION OBJECT [ "a" NUMBER ] ":" CLIP-LINE
| RELATION "cada uno:" IDENT TEXT
| "juntos:" LIST "—" DISPOSICION
| ( "en el mundo" | "en el documento" ) ":" CLIP-LINE
| "en" MATERIA-SPEC ":" CLIP-LINE (* the material of one piece *)
| "de" QUOTE "a" QUOTE ":" CLIP-LINE (* the sign that flies *)
| ( "a la izquierda" | "a la derecha" ) ":" CLIP-LINE
| DISTANCIA ":" CLIP-LINE (* camera profile: depth *)
| "en silueta:" CLIP-LINE ; (* cartel profile *)
RELATION = "bajo" | "sobre" | "junto a" | "delante de" | "detrás de" ;
SCENE-VERB = IDENT "con vista" VISTA
| IDENT "se encaja en" HOLE | "en sus huecos:" LIST
| "recoge" IDENT | "clava" IDENT "en" IDENT
| ( "recorta" | "dobla" | "tapa" | "traslada" ) QUOTE TEXT
| "retira:" ( "el escenario" | "las tablas" | "el teatro" )
| "la truca" ( "se acerca a" IDENT | "vuelve" | "se aleja" ) ;
MAP = "mapa:" MAP-ORDER ;
MAP-ORDER = "territorio" QUOTE { "·" ( "con" LIST | "grande" | "en" PLACE ) }
| "línea desde" QUOTE [ "hacia" QUOTE ]
| "la línea de" QUOTE ( "llega a otro igual" | "se hunde" | "vuelve" )
| "conecta" QUOTE { "·" QUOTE } | "el círculo se abre" | "mira a" QUOTE
| "en fila abajo" | "en columna izquierda" | "se va" ;
(* Movement is recognized BY THE VERB (VERBO-MOV, VERBO-RELACIONAL), never by its suffixes. *)
MOVEMENT = [ PLACEMENT-PREFIX ] [ ARTICLE ] SUBJECT ( VERBO-MOV | VERBO-RELACIONAL ) [ DESTINATION ]
{ "·" ( [ "por" ] TRAYECTO | MANERA | GRANULADO | REGISTRO-MOV | RASTRO ) } [ VENTANA-SPEC ]
| SUBJECT "se funde en" SUBJECT | SUBJECT "hierve con" SUBJECT
| "el pelo pasa de" SUBJECT "a" SUBJECT
| SUBJECT "se sale del cuadro" [ "por la" LADO ] ;
DESTINATION = ( "hasta" | "a" | "hacia" ) OBJECT | "fuera de campo" [ "por la" LADO ] ;
VENTANA-SPEC = "hasta decir" QUOTE | "mientras" ;
CAMERA = "la truca" ORDEN-TRUCA [ IDENT ] [ "en" TALLA ]
| IDENT "mira a" IDENT | IDENT "mira a cámara"
| [ ARTICLE ] IDENT ( "sale" | "entra" ) "por la" LADO
| "sonido:" CRUCE-SONIDO [ NUMBER ]
| "fuera de campo" [ "por la" LADO ] ":" TEXT
| [ "el" ] "foco" ( "en" | "pasa a" ) IDENT [ "y en" IDENT ] | "todo en foco"
| IDENT "está" TEXT ; (* a state, for continuity *)
JOURNEY = IDENT "viaja" | IDENT "se apea"
| "el mundo" MOVIMIENTO-MUNDO [ NUMBER ]
| "por la ventanilla:" LIST "desfilan"
| "por" WINDOW-OF "de" IDENT "se ve el mundo" ;
SOUND = "sonido:" EFFECT-NAME [ SIDE ] ; (* an effect, at its place; anchorable with "al decir" *)
CHARACTER = SUBJECT ( ACCION-FICHA | EXPRESION | "de espaldas" | "de perfil" | "de frente"
| "de tres cuartos" | "de tres cuartos de espaldas" ) ;
SIGN = "LETRA" QUOTE { "·" ( "en" TIPO-LETRA | DISPOSICION-SIGNO | SITIO-SIGNO | PIECE-SIZE
| "de" COLOR-CARTEL | "sin leer" ) }
| QUOTE "es" ( "un" | "una" ) PAPEL-SIGNO [ ( "a" | "de" ) QUOTE ]
| [ "la" | "el" ] LETTER "de" QUOTE ( "es" | "se convierte en" ) IDENT
| IDENT "se convierte en" [ "la" | "el" ] LETTER "de" QUOTE
| [ "las letras de" ] QUOTE VERBO-SIGNO
| "la raya corta" QUOTE
| QUOTE "forma" FORMA-PALABRA
| QUOTE "tapa a" IDENT | IDENT "tapa" QUOTE
| "el ojo completa" QUOTE
| "ESCALA" IDENT "como" IDENT
| "BOSQUE de" BOSQUE ;
WEAVE = ( "TEJE" | "SINTONIZA" ) QUOTE { "·" ( "en" TIPO-LETRA | "con la aguja del dial" | PIECE-SIZE | DISPOSICION-SIGNO ) }
| QUOTE "se interrumpe en" QUOTE | QUOTE "sigue"
| "los hilos de" IDENT "y" IDENT "se entretejen"
| "FRASES" QUOTE { "·" QUOTE } ;
(* Events: a closed vocabulary with state (alive | reserved). The union of
EVENTO, EVENTO-CARTEL, EVENTO-OYE and EVENTO-CAMARA, some with an argument. *)
EVENT = ">" EVENT-NAME [ ARG ] { "·" ">" EVENT-NAME [ ARG ] } ;
EVENT-NAME = EVENTO | EVENTO-CARTEL | EVENTO-OYE | EVENTO-CAMARA | ROTURA-WITH-REASON | ENCUADRE-INCOMODO ;
ROTURA-WITH-REASON = ROTURA "porque" QUOTE ; (* breaking a rule with permission: the reason is required *)
NESTING = "dentro:" NL { CLIP-LINE } (* sub-clips; at most three levels *)
| "mientras:" CLIP-LINE
| "al decir" QUOTE ":" CLIP-LINE
| CLIP-LINE "hasta decir" QUOTE ;
(* ---------- end ---------- *)
END = "==" "FIN" { "=" } { TEXT } [ NL ">" "silencio" NUMBER ] ;
(* ---------- comments ---------- *)
COMMENT = "//" TEXT (* technical comment: not in the IR *)
| "(" TEXT ")" (* author's digression: in the IR, `digresiones` *)
| "~" "deriva:" TEXT ; (* a commission to the engine: in the IR, `derivas` *)
(* ---------- terminals ---------- *)
ARTICLE = "el" | "la" | "los" | "las" ;
TITLE = QUOTE | TEXT ;
SPEAKER = IDENT ; (* not a reserved word; compared as written *)
CUE = WORD ; (* a file of BANDA, by name, case-insensitive *)
EFFECT-NAME = WORD { WORD } ; (* a file of EFECTOS (or BANDA), by name *)
PATH = TEXT ; (* relative to the pliego's folder in a portable project *)
LIST = IDENT { "·" IDENT } ;Appendix C. Diagnostic codes
Codes of the pliego language (spec/diagnosticos.json):
| Code | Severity | Meaning |
|---|---|---|
E001 | error | the pliego declares a newer epoch than the compiler supports |
E010 | error | affect outside the closed vocabulary |
E011 | error | unknown function or shot in a clip header |
E012 | error | stray word in a movement line (not a path, manner, grain, register or window) |
E013 | error | > event outside the closed vocabulary |
E014 | error | unknown sign register |
E015 | error | unknown ESPACIO (room) |
E016 | error | unknown voice colour in REPARTO |
E017 | error | unknown arc |
E018 | error | unknown collage modifier or MARIONETA field (after · in foto:, recorte:, clip: or MARIONETA) |
E019 | error | another word outside a closed vocabulary |
E020 | error | ambiguous name: two candidates tie at the same level of the name dimension |
E021 | error | reserved word used as a speaker name or identifier |
E022 | error | reference to something that does not exist (piece, clip, ECO id, character) |
E023 | error | a line that looks like an instruction and is not one: it would be printed on screen by accident (dialogue by someone not in REPARTO, a scene line inside a clip, an instruction or verb that does not exist) |
E024 | error | a piece acts (NAME action) without being in REPARTO or being a MARIONETA |
E025 | error | dead anchor in the text: al decir «X» and the written voice of that beat never says X |
E030 | error | two shouts in one clip |
E031 | error | two actions on the same subject in the same window, or a duration declared twice |
E032 | error | cycle of bindings, chain of more than three links, or nesting too deep |
E033 | error | unsupported piece whose material does not float |
E040 | error | MÚSICA cue not found in BANDA (or no BANDA declared) |
E041 | error | sonido: effect found in neither EFECTOS nor BANDA |
E042 | error | AMBIENTE not found in EFECTOS |
E050 | error | python: names something that is not in the bestiary |
E051 | error | pose not declared by the bestiary |
E052 | error | drawing invoked wrongly: arguments after ·, parentheses, or arguments the piece's signature does not accept |
E053 | error | the declared bestiary (PYTHON or PIEZAS) does not exist next to the pliego |
E054 | error | action the piece does not declare (neither among its ACCIONES, its POSES nor its CICLOS) |
E060 | error | a rule broken without its porque |
E090 | error | malformed line (the parser cannot continue) |
W101 | warning | axis jump (180-degree rule) |
W102 | warning | shot-size jump |
W103 | warning | eyeline mismatch |
W104 | warning | screen-direction mismatch |
W105 | warning | continuity-of-state mismatch |
W110 | warning | reserved event: accepted by the language, not yet realized |
W111 | warning | reserved sign register |
W112 | warning | plain-dialect share below 85 % |
W113 | warning | no final silence declared |
W114 | warning | too many clips without a breather |
W115 | warning | scene with two or more characters and no EJE |
W116 | warning | empty clip |
W117 | warning | clocks that are not coprime |
W118 | warning | dubious action on a piece (enters twice, acts on something absent) |
W120 | warning | dead anchor: al decir «X» and the voice never says X |
W121 | warning | two voices: a sounding clip inside a narrated beat without > espera al clip |
W122 | warning | illegible anchor: matches the voice but not its di: |
W123 | warning | the beat grows: the clip is longer than the voice |
W124 | warning | empty page: the beat opens a new frame and places nothing while the voice sounds |
W125 | warning | text on screen: a prose line that will be typed on the paper |
W130 | warning | Lasseter review (on the real timeline) |
W199 | warning | other warning |
Codes of the other parts: P001 to P009 (portable project, §14.4), L001 to L011
(láminas, §17.9), M001 to M006 (materias, §18.6), T001 to T007 (takes, §19.4).
Appendix D. Known deviations of the reference implementation
Found while building the conformance suite (2026-10-15) against manim-saorín 1.0.0b1. Each is a pending case in the suite; it stops being pending when the reference passes it.
| Case | What the reference does | What this specification says |
|---|---|---|
lee-errores-reservada | accepts REPARTO nota: … and then treats nota: as a directive (warns «clip vacío») | a speaker named with a reserved word is E021 (§5.5, §6.4) |
lee-estampas | warns «clip vacío» (W116) for a clip whose only content is a sign (LETRA) | a sign is a piece (§8.3); the clip is not empty |
lee-errores-letra-preambulo | accepts a LETRA line (a clip line) in the preamble without error and drops it silently: the sign never reaches the IR | the three seats (§3): a line out of its place is an error (E090), never a line that disappears |
cierre-servilleta | mesa escribe rewrites a servilleta's preamble and drops BANDA, EFECTOS, MEZCLA, MÚSICA and AMBIENTE | closure (§11.1): the revealed pliego sounds the same |
espejo-taller | an imported .mano reads toca la truca: sí as no; an inline precisión alta stays as an unnormalized key beside precision alta; parte drops the section name | the mirror law (§11.2) |
(all ir cases) | does not emit identidad in each beat | identidad is a required beat field (§10.3); the normative projection will include it when the reference emits it |
| (preamble) | MUSICA 1M1 without the accent in the preamble is taken as a song path and the cue is silently lost | MÚSICA and MUSICA are the same word (§4.5); a name in BANDA is a cue (§5.2, RFC 0004) |
| (plain share) | counts cue names such as 1M1 as figures | names are not figures (§3.1) |
| (checking) | mesa lee does not report name ambiguities; mesa indice does, with exit status 0 | a compiler's check reports E020 and fails (§12); the adapter merges both commands |
| (codes) | messages without codes | codes of Appendix C (RFC 0003); the adapter derives them from messages |
Appendix E. References
- BCP 14: RFC 2119 and RFC 8174, key words.
- RFC 8785, JSON Canonicalization Scheme (JCS).
- RFC 6838, media type specifications and registration procedures.
- ISO/IEC 14977, EBNF.
- PKWARE, .ZIP File Format Specification (APPNOTE).
- W3C, WebGPU and WGSL.
- EBU R 128 and ITU-R BS.1770, loudness and true peak.
- J. Lasseter, Principles of Traditional Animation Applied to 3D Computer Animation, SIGGRAPH 1987.
- Real Academia Española, Diccionario panhispánico de dudas, «raya».
SPEC-MESA-2.md,SPEC-PIEZAS.md(manim-saorín);pluma/LAMINA.md,materias/README.md,FORK.md(this repository); ManimGX (Academa, MIT).
Appendix F. Profiles in development (informative)
Three branches of the reference implementation are building new profiles at the time of this draft. What follows is informative: it records the lines they introduce so that other implementations do not take the same words for something else. Each becomes normative when its branch is merged and the suite has cases for it.
- metraje (real footage), merged into the reference implementation on 2026-10-15
(its working document is
SPEC-METRAJE.md); the newFORMATOwords are already in Appendix A, and the aspect of the IR carriesformato.reencuadre. Preamble:METRAJE,REVELADO,RECORTA,LIMPIA,ESTABILIZA. Clip:plano ≈ «…»andrecurso ≈ «…»(a shot found by meaning in an indexed library),toma: «…»,plano: file de A a B, and the tracking prefixessobre la mano de X:andsobre «objeto»:(the pen follows what was filmed). REPARTO accepts the voicefilmada.FORMATOgains9:16,1:1and4:5, with reframing after·:sigue a quien habla | sigue al sujeto | sigue a NAME | centrado. Tools:ingesta,busca,monta(editing by words),exporta,importa,planilla. Transcription is local and word by word. - géneros (genres and production). Preamble:
GÉNERO X [· field …], which only fills defaults where the pliego says nothing. Clip:ecuación:,fuente:,dato:,rótulo:,cita:, andver: curva | barras | puntos desde datos.csv. Native vertical and square canvases. Tools:nuevo --género,serie,variantes,traduce,subtitulos,audiodescribe,accesible,revisa,notas,trailer,canal,deriva. - 3D (volume). The set in volume from the words of the pliego, the same physical camera in the light 3D of the engine and in Blender orchestrated by layers, exchange through glTF and USD, and generated images and clips that are declared and frozen.