Real bug, not user error: Gradio refuses to serve a file back to the
browser unless it lives under the app's own directory, the system
temp dir, or an explicit allowlist. Every character's reference audio
lives in the-service-station repo, a completely different path, so
selecting *any* character in the Characters tab threw
gradio.exceptions.InvalidPathError server-side (visible in the server
log, not surfaced usefully in the browser's generic error toast).
Fixed with launch(allowed_paths=[SERVICE_STATION_DIR]), the documented
fix for this exact error.
Also: the character dropdowns choices were fixed at server-start time,
so a character created earlier in the same running session did not
show up without manually clicking Refresh. Added a demo.load() hook to
refresh both dropdowns automatically on page load, in addition to
keeping the manual Refresh button for mid-session use without a full
reload.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Real workflow gap: the transcript boxes were read-only, so correcting a
mis-hearing meant manually retyping into the separate Text to speak
field. Reported case: uploading a clip with casual speech ("its
gonna") transcribed as "it is going to be" - if that formalized text
then gets used for generation (by copying it over by hand, the only
option available), the cloned voice ends up speaking noticeably more
formally than intended.
Both transcript boxes are now editable, and thereas a direct "Use this
transcript as Text to speak" button on the reference transcript so a
corrected transcript can be sent straight into generation without
retyping. Also bumped the Whisper model from small to medium for
somewhat better fidelity on casual speech - a real but modest
improvement on the one comparison run, not a guaranteed fix, which is
why the editable box is the actual fix and the model bump is a bonus.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Four more AuK tasks exposed in the Pipeline Studio (vendor/AuK/docs/
COOKBOOK.md sections 3.3, 4.3-4.5), grouped in a collapsed accordion so
they do not crowd the main flow:
- De-accent: remove a regional accent, keep the voice.
- Volume: simple +/-5/10/15 dB.
- Whisper conversion: speech <-> a soft whisper, same content/speaker.
- Nonverbal editing: add/remove breaths, laughs, coughs - directly
relevant to this project's original brief (make a character sound
surprised or laugh). Needs an explicit --gen_seconds like Speed does,
but unlike Speed there is no way to auto-derive the target (add/remove
both change duration unpredictably per AuK's own cookbook) - defaults
to the current reference's own duration if left blank.
Also added a Flash/Base model toggle (ckpts/AuK-Flash, downloaded - same
architecture distilled to 4 fixed steps with CFG=0, ~4.6GB since it
shares the Qwen text encoder with Base rather than needing its own
copy). Verified end-to-end: 37s wall-clock including model load vs the
60-90s+ typical for Base on similar edits. Intended workflow: draft and
iterate fast with Flash, confirm the take you are actually keeping with
Base before promoting a voice or emotion - surfaced as an explicit
reminder in the emotion-candidate flow, which defaults to Flash since
that one is inherently exploratory.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Timbre is actually the most-used AuK task in this whole project - every
character base voice was built from a full free-form description
(accent, age, register, personality in one sentence), but the UI never
had a labeled control for it. It only existed as implicit plumbing
behind the emotion-word wrapping, or something a user could hand-type
into the generic custom-instruction box. Added a clearly labeled
Timbre / voice description field that builds the correct AuK template
directly.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Speed editing was a silent no-op - AuK needs --gen_seconds or it just
preserves the input duration (vendor/AuK/docs/COOKBOOK.md 3.2). Fixed
by computing the target from the current reference duration / speed
factor, with a UI warning that longer references risk a memory-swap
stall on this box (reproduced building a character voice: a 27s target
hung 20+ minutes swapping with 0%% GPU use, a 12s source completed in
seconds).
Added Whisper content verification (faster-whisper, small/CPU/int8)
after every AuK edit and MOSS generation. Motivated by a real incident
building the-service-station cast: a chained AuK edit leaked fragments
of its own instruction text into a character reference, undetected
through a full listen-and-approve round because nothing had
transcribed the reference itself, only generated lines.
History is now per-instruction rather than per-click, so Undo is
granular and a save action can derive a sensibly-scoped
generation_recipe.
New Characters tab: browses the-service-station repo's CHARACTER.md
cards (name/role/status/reference audio/emotion_library), lets you
create a new character (writes a fresh CHARACTER.md, always
status: draft) or generate an emotion candidate for an existing one
(writes to voices/<name>/emotion-cache/<emotion>.wav, same path the
automated pipeline's own fallback uses). Approving anything stays a
manual step - this tab creates candidates for a human to listen to and
promote, it never self-approves.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Real reference clips are often cheap-mic/phone-call quality. Adds
AuK's dedicated Speech Enhancement task (denoise+dereverb, or a
telephone-effect-specific variant) as a new dropdown, applied first
in the edit chain - before emotion/pitch/speed/custom - since character
edits on noisy source audio just carry the noise through.
Found useful while iterating on real character voices for a sibling
project (the-service-station) using this exact tool.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
AuK's loader (librosa/soundfile) can't read compressed containers like
m4a/mp3 at all - only demucs's loader handles those. Gradio keeps
uploads in their original format, so any edit attempted directly on an
uploaded m4a failed with "Format not recognised."
Normalize to wav via ffmpeg at the single point a reference is set
(use_as_reference), so both AuK and MOSS-TTS downstream always see wav
regardless of what was uploaded.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey
Gradio app that orchestrates the three existing isolated venvs via
subprocess (their dependencies conflict too much to merge into one
environment - MOSS-TTS needs transformers 5.0.0, AuK needs 4.57.6).
Lets you strip a voice, iteratively edit it (emotion/pitch/speed/custom
instruction) with preview and undo/reset after each step, then generate
new speech in the resulting voice - addressing the trial-and-error
workflow the pitch-overshoot investigation needed.
Also extracts tts/generate.py as a reusable, general-purpose MOSS-TTS
cloning CLI (text/reference/language/output args) rather than one-off
personal scripts.
Verified all three stages end to end via direct function calls before
wiring up the UI.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey