teaching/sermons/col-1-15-20/anki/README.md

Anki — Col 1:15-20 deck

Operational context for the deck and its TTS audio output. The deck powers a "corkboard with red yarn" study workflow (per Art of Teaching) — browse cards on phone, listen to the audio walkthrough hands-free.

What's here

Outside the repo

The pipeline lives at ~/Library/Application Support/AnkiProgramFiles/. Run scripts with that dir's venv: ~/Library/Application Support/AnkiProgramFiles/.venv/bin/python.

Script Purpose
sync.py Push deck to AnkiWeb. Reads hkey from ~/Library/Application Support/Anki2/prefs21.db. Desktop app must be closed.
export_cards_for_voice.py Write ../cards_for_voice.md — a TTS-friendly walkthrough (Card N. front … back). Sorts by NID, not due. See "Stable order" below.
export_anki_to_project.py Write cards.md here. Section-grouped, scannable.
add_cards_batch2.py Template for adding cards in bulk (idempotent on Front text).
fix_duplicates.py Template for editing existing cards in place.
render_cards_audio.py TTS render all cards → chunks in ../.tts_chunks/, then concat to ../cards_for_voice.mp3. Resumable.
stitch_append.py Render only missing chunks and append to the existing mp3 via ffmpeg.
tts_speakable.py Pronunciation substitution layer (Col→Colossians, v.17→verse 17, BP→Bible Project, LXX→Septuagint, …). Only substitutes book abbreviations when followed by a chapter digit, so common words pass through.

Collection path: ~/Library/Application Support/Anki2/User 1/collection.anki2 Deck name: Col 1:15-20

Stable order — DO NOT change

export_cards_for_voice.py sorts cards by NID (creation order). It was previously sorting by cards()[0].due, but Anki's due-value assignment is unstable when new cards are added — the export order shifted, the position-keyed chunk cache misaligned, and four cards ended up duplicated in the audio file. NID-sort is load-bearing. Adding new cards always appends to the end of the audio; existing chunks stay valid.

If you ever change the sort key, you must nuke ../.tts_chunks/ and full-re-render. Quota cost is ~40k chars (full deck).

ElevenLabs

Common operations

Add cards — copy add_cards_batch2.py, edit the CARDS list, run. Then sync.py, then export_anki_to_project.py to refresh cards.md.

Edit cards — copy fix_duplicates.py, key by Front text, run. Then sync + export.

Re-render audio after content changes:

  1. Identify affected card numbers (look at NID-ordered cards.md / cards_for_voice.md).
  2. Delete just those chunks from ../.tts_chunks/NNN.mp3.
  3. Run render_cards_audio.py — it'll synthesize the deletes and concat fresh.

Listen on phone — pull deck on AnkiMobile (browse view works best, not study), OR open cards_for_voice.mp3 via the viewer at http://100.83.250.41:8889/sermons/col-1-15-20/cards_for_voice.mp3 (Tailscale-only, has HTTP Range so iOS audio scrub works).

Card schema

Anki note type: Basic (Front, Back). Tags carry the structure:

Back text uses HTML (<b>, <i>, <br>) — Anki renders it; the exporters strip/convert it. Footer convention: Source: <path> (the exporters strip this line before TTS so it isn't read aloud).

Current state (2026-05-13)