The show file¶
One folder per show. Audio as ordinary files; everything else in a single SQLite database beside them. Copy the folder to a USB stick and the show travels complete — episodes, transcripts, chapters, edits, custom fields, and which step of the workflow you had reached.
Ondes Courtes/
├── ondes-courtes.podlibre one SQLite file: the whole model
├── artwork.jpg
└── episodes/
└── 14-le-son-du-silence/
├── camille.wav sources stay as files; the database points at them
├── invite.wav
├── musique.flac
└── export.mp3
Audio is not stored in the database. A show is tens of gigabytes of audio and a few megabytes of everything else, and the two want different treatment: files for the audio, so any other tool can read it and a backup can deduplicate it; a transaction log for the rest, so an interrupted edit never leaves half a change behind.
The fixed part of the model¶
| Table | Holds |
|---|---|
show |
One row. The podcast itself. |
episode |
One row per episode. |
track |
A lane in the editor: a microphone, the music bed. |
clip |
A piece of audio on a track, with its source file and position. |
chapter |
Title, start, optional image and link. |
speaker |
A voice, named once per episode by the user. |
segment |
A span of transcript: start, end, speaker, text. |
dictionary_rule |
The user's own corrections, applied to a transcript without a model. |
bookmark |
Somewhere to come back to: an episode, or a moment inside one. |
field_def, field_value |
Everything else — see below. |
workflow_state |
Which workflow this show uses. |
mark |
Steps the user ticked off by hand, for work that leaves no other trace. |
schema_version |
One integer, and the migrations that read it. |
Bookmarks are here, in the show, rather than in Podlibre's own settings. A note saying "pickup
to re-record" is about the work, not about the machine it was written on, so it travels when the
show is copied to another one. A bookmark whose at_ms is null means the episode; a bookmark
with one means a moment inside it.
The variable part¶
Almost nothing about podcast metadata is fixed. iTunes defines a set of tags, Podcasting 2.0 defines more each year, and a plugin may invent one tomorrow. So none of them are columns.
A field definition is a row describing a field: its key, what it attaches to, its type, its label, where it goes on the way out, and whether other plugins may read it.
field_def(key, on, type, label_key, rss_tag, id3_frame, owner, shared)
field_value(key, target_id, value)
Three layers, one mechanism:
| Layer | Examples | Comes from |
|---|---|---|
| Base | title, author, explicit, episodeType |
The iTunes podcast DTD, shipped |
| Extended | podcast:transcript, podcast:chapters, podcast:person, podcast:funding |
Podcasting 2.0, shipped, switchable off |
| Added | notes_html, episode_mood |
A plugin, at install time |
None of the three is special-cased in code. Adding a field is inserting a row, and the third layer needs no release of Podlibre.
Because a definition carries its own RSS tag and ID3 frame, an exporter written before a field
existed still emits it correctly. And a field marked shared is readable by every plugin: the
show-notes writer declares notes_html, the Castopod publisher reads it, and neither needs to
know the other exists.
Who may write¶
The supervisor's show store is the only writer. The UI reads directly, through a read-only connection, so drawing a list never waits for a lock; plugins read and write through the gate, which serialises changes and keeps a plugin from leaving a half-finished edit behind when it is killed.
Moving a show¶
Nothing in the database holds an absolute path. A clip points at episodes/14-…/camille.wav
relative to the show folder, so the folder can be moved, renamed, copied to another operating
system, or kept in a sync folder, and still open.