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
cards.md— gitignored, regenerable. 86-card source-of-truth export from the Anki deck, organized into sections (vocab, cross-refs, voices, voice memos, etc.). Read top-to-bottom to surface duplicates. Regenerate withexport_anki_to_project.pyafter deck edits.README.md— this file.
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
- Key:
ELEVENLABS_API_KEYin~/.zshrc - Voice:
iUqOXhMfiOIbBejNtfLR— Oxley - Rich and Deep (American grandpa, warm baritone, narrative/storytime). Hardcoded inrender_cards_audio.py. - Model:
eleven_multilingual_v2(handles Greek transliteration well: πλήρωμα reads correctly) - Format:
mp3_44100_128 - Tier: starter, 90,000 chars/month
- Quota check:
curl -s -H "xi-api-key: $ELEVENLABS_API_KEY" https://api.elevenlabs.io/v1/user/subscription
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:
- Identify affected card numbers (look at NID-ordered
cards.md/cards_for_voice.md). - Delete just those chunks from
../.tts_chunks/NNN.mp3. - 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:
col-1-15-20— present on every card- Verse:
v15,v16,v17,v18,v19,v20 - Chunk type:
vocab,greek,cross-ref,quote,concept,structure - Source:
bp,piper,bell,willard,staton,peppiatt,comer,tyler,ligertwood,voice-memo,bkc,hntc,nicnt,tntc, … - Theme:
cross-as-throne,firstborn,firstborn-from-dead,peace-blood,fullness,image-of-god,reconciliation,head-body,series-slogan, …
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)
- 86 cards, deck synced to AnkiWeb
cards_for_voice.mp3— 51:11, Oxley, pronunciation throughout- Quota used this month: ~74k / 90k (after full re-render)
- Last full render did the audio + pronunciation cleanup; chunks 001-086 = NID order