Skip to content

Episode format reference ​

Every key of episode.yaml, generated from the schema that validates it (episodeJsonSchema() in packages/core/src/jsonschema.ts). Objects are strict: an unknown key is error V-1 with a "did you mean" hint. reelforge schema writes the same schema as JSON for editor autocompletion.

Type time is a time expression: 12.5s, l7, l7.end, l7:'word', l7:'word'#2, l7.3, @scene, @scene.end, each with an optional offset such as +0.4. See Writing episodes for examples and the components reference for props.

Episode identity: meta ​

KeyTypeDefaultRequiredLimitsDescription
metaobjectyesEpisode identity and publishing texts
meta.idstringyespattern ^[a-z0-9][a-z0-9_-]*$Slug of the episode (folder name)
meta.seriesstring""Series name shown in the header
meta.titlestring""Episode title
meta.episodeinteger1≥ 1Episode number shown in the header
meta.presetstring"tiktok"Platform layout: tiktok, reels, shorts or your own preset
meta.themestring"default"Theme name in themes/, or a relative path
meta.langstring"ar-EG"Voice-over language, e.g. en-US (left to right) or ar-EG (right to left)
meta.publishobjectTexts written to out/publish.md
meta.publish.coverstringShort cover text
meta.publish.captionstringPost caption
meta.publish.hashtagsstring[][]Hashtags
meta.publish.pinnedstringPinned comment

Audio: audio ​

KeyTypeDefaultRequiredLimitsDescription
audioobject{}Voice, sound effects and mastering
audio.voicestring"voice.wav"Voice recording, relative to the episode folder
audio.sfxauto | none | manual"auto"auto: components play their default sounds; manual: only listed sounds
audio.sfx_gain_dbnumber-16≥ -60, ≤ 12Sound effect level in dB
audio.duckbooleantrueLower the effects under the voice
audio.denoisebooleanfalseRemove background noise from the voice (RNNoise)
audio.extraobject[][]Extra sounds at given times
audio.extra[].attimeyes
audio.extra[].soundwhoosh | hit | ding | err | glitch | tick | tap | typingyes
audio.extra[].gain_dbnumber

Script: script ​

KeyTypeDefaultRequiredLimitsDescription
scriptobject[]yesmin 1 itemsSpoken lines; ids default to l1, l2, …
script[].idstringpattern ^[A-Za-z_][A-Za-z0-9_]*$Line id used in time expressions
script[].textstringyesWhat you say, one sentence
script[].captionstring"auto"auto, none or a custom caption text
script[].breakstring[][]Force a caption break before these words

Chapters: chapters ​

KeyTypeDefaultRequiredLimitsDescription
chaptersobject[][]Chapter labels on the progress bar and in publish.md
chapters[].attimeyes
chapters[].labelstringyes

Scenes: scenes ​

KeyTypeDefaultRequiredLimitsDescription
scenesobject[]yesmin 1 itemsScenes in order; each starts at a time and ends where the next starts
scenes[].idstringyespattern ^[A-Za-z_][A-Za-z0-9_]*$
scenes[].attimeyesStart time (usually a line, e.g. l3)
scenes[].endtimeEnd time (default: next scene start)
scenes[].glowstring | object[]Background glow color, or a list of timed colors
scenes[].glow[].attimeyes
scenes[].glow[].colorstringyes
scenes[].transitioncrossfade | cut | slide-up | zoom | push | blur"crossfade"How the scene replaces the previous one
scenes[].camerastill | drift | push-in | pull-out"still"One slow camera move across the scene
scenes[].layoutstage | full"stage"stage (between header and captions) or full (whole canvas)
scenes[].rowobjectLay out elements side by side
scenes[].row.gapinteger≥ 0
scenes[].row.alignstart | center | end
scenes[].row.xinteger
scenes[].row.yinteger
scenes[].row.winteger> 0
scenes[].row.hinteger> 0
scenes[].columnobjectStack elements vertically
scenes[].column.gapinteger≥ 0
scenes[].column.alignstart | center | end
scenes[].column.xinteger
scenes[].column.yinteger
scenes[].column.winteger> 0
scenes[].column.hinteger> 0
scenes[].columnsinteger≥ 1, ≤ 6Split the stage into lanes (elements pick one with col)
scenes[].gutterinteger≥ 0

Elements: scenes[].elements ​

KeyTypeDefaultRequiredLimitsDescription
scenes[].elementsobject[][]Components shown in the scene
scenes[].elements[].usestringyesComponent name (see the components reference)
scenes[].elements[].idstringpattern ^[A-Za-z_][A-Za-z0-9_-]*$Element id (for arrows, states and the editor)
scenes[].elements[].propsmap{}Component props; strict per component
scenes[].elements[].placeobjectBox in stage coordinates (1080 × 1000)
scenes[].elements[].place.xinteger
scenes[].elements[].place.yinteger
scenes[].elements[].place.winteger> 0
scenes[].elements[].place.hinteger> 0
scenes[].elements[].place.centerboolean
scenes[].elements[].place.anchortop | bottom | center | left | right
scenes[].elements[].place.margininteger
scenes[].elements[].sizeobjectSize inside a row/column helper
scenes[].elements[].size.winteger> 0
scenes[].elements[].size.hinteger> 0
scenes[].elements[].colinteger≥ 0
scenes[].elements[].layerbase | overlayoverlay draws on top and skips the overlap rule (V-8)
scenes[].elements[].zinteger
scenes[].elements[].enterobjectWhen and how the element appears
scenes[].elements[].enter.attimeEnter time, best on a word: "l3:'bucket'"
scenes[].elements[].enter.animpop | rise | slide-l | slide-r | fade | draw | type | count | flip | glitch | stamp | zoom | blur | wipe | spring | drop | reveal | noneEnter animation
scenes[].elements[].enter.durnumber> 0
scenes[].elements[].enter.easesmooth | snappy | gentle | linearEasing curve
scenes[].elements[].enter.s0number
scenes[].elements[].enter.dynumber
scenes[].elements[].enter.distnumber
scenes[].elements[].enter.cpsnumber> 0
scenes[].elements[].enter.caretboolean
scenes[].elements[].enter.rotnumber
scenes[].elements[].enter.ampnumber
scenes[].elements[].exitobjectWhen and how the element leaves
scenes[].elements[].exit.attimeyes
scenes[].elements[].exit.animfade | pop | rise | sink | slide-l | slide-r | zoom | blur | wipe | none
scenes[].elements[].exit.durnumber> 0
scenes[].elements[].statesobject[][]Prop changes over time
scenes[].elements[].states[].attimeyes
scenes[].elements[].states[].setmapyes
scenes[].elements[].fxobject[][]Effects: shake, flash, glitch, pulse, bump
scenes[].elements[].fx[].attimeyes
scenes[].elements[].fx[].doshake | flash | glitch | pulse | bumpyes
scenes[].elements[].fx[].ampnumber
scenes[].elements[].fx[].durnumber> 0
scenes[].elements[].fx[].colorstring
scenes[].elements[].fx[].ratenumber> 0
scenes[].elements[].fx[].targetself | camera
scenes[].elements[].fx[].soundwhoosh | hit | ding | err | glitch | tick | tap | typing | none
scenes[].elements[].sfxauto | none | object[]"auto"none, or a list of sounds at times
scenes[].elements[].sfx[].attimeyes
scenes[].elements[].sfx[].soundwhoosh | hit | ding | err | glitch | tick | tap | typingyes
scenes[].elements[].sfx[].gain_dbnumber