- upload: validate target folder with resolve_within, refuse to overwrite an
existing voice unless overwrite=1, stage audio/transcripts and swap them in
together so conversion or disk failures keep the previous voice, drop stale
.txt/.orig.txt and other-format siblings, write .orig.txt for the native script
- ffmpeg is resolved explicitly (PATH, then portable python dir) with a timeout
- voice/gallery scans run in a worker thread; stems are unique across scan
folders; audio URLs are percent-encoded and versioned by mtime
- stream and delete only accept audio extensions; paging and template names
are validated; errors are JSON
- romanizer no longer reads Han-only (Chinese) text as Japanese and reports
missing pykakasi / hangul-romanize instead of silently succeeding
- extension static files use Cache-Control: no-cache (revalidate) instead of
no-store; document the deliberate PATH exception in __init__.py
Verified: new local tests/test_audio_catalog.py (14 tests) plus the existing
Python suite (78 tests) pass in a Linux venv; not yet exercised in ComfyUI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeqEub5