Datenmodell: episode.md mit TOML-Frontmatter + episode.cache.json für Lifecycle-Daten #5

Closed
opened 2026-05-31 21:49:06 +02:00 by holm · 0 comments
Owner
Dimension Bewertung Einschätzung
Aufwand █████░░░░░ Mittel — Parser in Bash, Migration der 26 Episoden, Konvention dokumentieren
Nutzen ██████████ Maximal — Fundament für Templates, Audio-Tools, Validierung
Bruchhäufigkeit █░░░░░░░░░ Sehr niedrig — wenn etabliert, stabil
Nachhaltigkeit ██████████ Maximal — bestimmt Datenformat für Jahre
Dringlichkeit ████████░░ Hoch — blockiert #4 (saubere Integration nur einmal)

Ziel

Das aktuelle Hybrid aus episode.json + shownotes.md durch eine einzige episode.md ersetzen. Lifecycle-Daten in separater episode.cache.json. Speaker zentral aus speaker/<id>/speaker.toml.

Format-Design (final nach Datenanalyse)

episode.md (Single Source of Truth, human-only)

+++
episode = "001"
slug = "001"
title = "Health and Wellness"
subtitle = "Die Hörgerätefolge"
date = "2021-06-08T22:00:00+02:00"
duration = "03:01:13"
speakers = ["silke", "christoph", "holm"]
subformat = "healthandwellness"
explicit = false

[audio]
basename = "001"
formats = ["mp3"]
+++

# Health and Wellness — Die Hörgerätefolge

Freier Markdown-Text. Kapitelmarker als h5 (`#####`) frei im Text verteilt:

##### 00:00:00 Intro, Begrüßung

##### 00:02:30.190 Was ist dies für 1 Podcast?

Optionale Beschreibung pro Kapitel, beliebiger Markdown:

- Aufzählungen
- ![Bilder](gimmicks/foo.png)

##### 00:15:30 Olivenhandcreme {image="gimmicks/cream.png"}

##### 00:22:20 Schlappensommer

Konvention Kapitelmarker:

  • Regex: ^##### (\d{2}:\d{2}:\d{2}(\.\d{1,3})?) +(.+?)(\s+\{(.+)\})?$
  • Optionale Pandoc-Attribute: {image="..." url="..."} (Standard-MD-Erweiterung)
  • Alles zwischen zwei #####-Markern = Beschreibung des laufenden Kapitels
  • Text vor dem ersten ##### = Episode-Shownotes (Lead)

episode.cache.json (auto-generiert, gitignored)

{
  "files": {
    "mp3": { "size": 174219785, "sha256": "...", "duration_sec": 10873 }
  },
  "mp3_chapters_written": true,
  "rendered_at": "2026-05-31T22:00:00Z"
}

speaker/<id>/speaker.toml

id = "holm"
name = "holm"
role = "host"
bio = "Initiator von zentonic"
links = [
  { type = "web", url = "https://mueller.network" }
]

[avatar]
file = "avatar.jpg"

Rendering-Convenience (Bonus für Webuser)

Jedes Chapter-Heading wird gerendert zu:

<h5 class="chapter" id="t-00-15-30">
  <a href="#t=00:15:30" class="play-from" data-seconds="930">▶ 00:15:30</a>
  Olivenhandcreme
</h5>

Drei Funktionen in einem:

  • Click → Podlove-Player springt zur Stelle (Media Fragments URI)
  • Anker → externe Direktlinks teilbar (/001.html#t-00-15-30)
  • Single Source für <podcast:chapters>-JSON, MP3-Chaptermarks, Player-Konfig

Arbeitsschritte

  • Migration-Script: _private/podcast-source/episodes/* → neues Format in _private/podcast-source-new/
  • Validierung: 26 Episoden roundtrip-konvertieren
  • Speaker zentral konvertieren: speaker/<id>/speaker.toml aus Episode-Referenzen
  • Parser in Bash: episode.md + episode.cache.json + Speaker-Dir → vollständiges JSON-Objekt für Template-Engine
  • Frontmatter-Parser (alles zwischen +++)
  • Body-Parser: Lead-Text + Chapter-Sections (Regex ^##### )
  • Pandoc-Attribute pro Chapter parsen ({image="..." url="..."})
  • .gitignore: episode.cache.json ergänzen
  • Dokumentation in Pemmikan oder docs/episode-format.md

Abhängigkeit

Blockiert #4 (minijinja-Integration). Sinnvolle Reihenfolge: #5#4 → #26/#27.

Reale Daten zur Validierung in _private/podcast-source/ (gitignored, 26 echte Episoden).

| Dimension | Bewertung | Einschätzung | |---|---|---| | Aufwand | `█████░░░░░` | Mittel — Parser in Bash, Migration der 26 Episoden, Konvention dokumentieren | | Nutzen | `██████████` | Maximal — Fundament für Templates, Audio-Tools, Validierung | | Bruchhäufigkeit | `█░░░░░░░░░` | Sehr niedrig — wenn etabliert, stabil | | Nachhaltigkeit | `██████████` | Maximal — bestimmt Datenformat für Jahre | | Dringlichkeit | `████████░░` | Hoch — blockiert #4 (saubere Integration nur einmal) | ## Ziel Das aktuelle Hybrid aus `episode.json` + `shownotes.md` durch **eine einzige `episode.md`** ersetzen. Lifecycle-Daten in separater `episode.cache.json`. Speaker zentral aus `speaker/<id>/speaker.toml`. ## Format-Design (final nach Datenanalyse) ### `episode.md` (Single Source of Truth, human-only) ```markdown +++ episode = "001" slug = "001" title = "Health and Wellness" subtitle = "Die Hörgerätefolge" date = "2021-06-08T22:00:00+02:00" duration = "03:01:13" speakers = ["silke", "christoph", "holm"] subformat = "healthandwellness" explicit = false [audio] basename = "001" formats = ["mp3"] +++ # Health and Wellness — Die Hörgerätefolge Freier Markdown-Text. Kapitelmarker als h5 (`#####`) frei im Text verteilt: ##### 00:00:00 Intro, Begrüßung ##### 00:02:30.190 Was ist dies für 1 Podcast? Optionale Beschreibung pro Kapitel, beliebiger Markdown: - Aufzählungen - ![Bilder](gimmicks/foo.png) ##### 00:15:30 Olivenhandcreme {image="gimmicks/cream.png"} ##### 00:22:20 Schlappensommer ``` **Konvention Kapitelmarker:** - Regex: `^##### (\d{2}:\d{2}:\d{2}(\.\d{1,3})?) +(.+?)(\s+\{(.+)\})?$` - Optionale Pandoc-Attribute: `{image="..." url="..."}` (Standard-MD-Erweiterung) - Alles zwischen zwei `#####`-Markern = Beschreibung des laufenden Kapitels - Text vor dem ersten `#####` = Episode-Shownotes (Lead) ### `episode.cache.json` (auto-generiert, gitignored) ```json { "files": { "mp3": { "size": 174219785, "sha256": "...", "duration_sec": 10873 } }, "mp3_chapters_written": true, "rendered_at": "2026-05-31T22:00:00Z" } ``` ### `speaker/<id>/speaker.toml` ```toml id = "holm" name = "holm" role = "host" bio = "Initiator von zentonic" links = [ { type = "web", url = "https://mueller.network" } ] [avatar] file = "avatar.jpg" ``` ## Rendering-Convenience (Bonus für Webuser) Jedes Chapter-Heading wird gerendert zu: ```html <h5 class="chapter" id="t-00-15-30"> <a href="#t=00:15:30" class="play-from" data-seconds="930">▶ 00:15:30</a> Olivenhandcreme </h5> ``` Drei Funktionen in einem: - Click `▶` → Podlove-Player springt zur Stelle (Media Fragments URI) - Anker → externe Direktlinks teilbar (`/001.html#t-00-15-30`) - Single Source für `<podcast:chapters>`-JSON, MP3-Chaptermarks, Player-Konfig ## Arbeitsschritte - [ ] Migration-Script: `_private/podcast-source/episodes/*` → neues Format in `_private/podcast-source-new/` - [ ] Validierung: 26 Episoden roundtrip-konvertieren - [ ] Speaker zentral konvertieren: `speaker/<id>/speaker.toml` aus Episode-Referenzen - [ ] Parser in Bash: `episode.md` + `episode.cache.json` + Speaker-Dir → vollständiges JSON-Objekt für Template-Engine - [ ] Frontmatter-Parser (alles zwischen `+++`) - [ ] Body-Parser: Lead-Text + Chapter-Sections (Regex `^##### `) - [ ] Pandoc-Attribute pro Chapter parsen (`{image="..." url="..."}`) - [ ] `.gitignore`: `episode.cache.json` ergänzen - [ ] Dokumentation in Pemmikan oder `docs/episode-format.md` ## Abhängigkeit Blockiert #4 (minijinja-Integration). Sinnvolle Reihenfolge: #5 → #4 → #26/#27. Reale Daten zur Validierung in `_private/podcast-source/` (gitignored, 26 echte Episoden).
holm closed this issue 2026-05-31 23:02:34 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Zentonic/zentonic-publisher#5
No description provided.