From 5dfb64bb0ca347012d4af2d5e2745534c89a780e Mon Sep 17 00:00:00 2001 From: Steve Calcott Date: Wed, 16 Sep 2026 07:51:04 +0000 Subject: [PATCH] Add a dedicated Timbre/voice-description field to the pipeline studio 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 Claude-Session: https://claude.ai/code/session_01Y1oQ4h4WE4R9KRvMQLr5Ey --- webui/app.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/webui/app.py b/webui/app.py index 5634ee3..cd4dd6b 100644 --- a/webui/app.py +++ b/webui/app.py @@ -252,6 +252,7 @@ def apply_edit( current_ref: str, history: list, enhance: str, + timbre_description: str, emotion: str, other_emotion: str, pitch: str, @@ -266,6 +267,14 @@ def apply_edit( # character/accent editing, not after (garbage in, garbage timbre-edited). if enhance and ENHANCE_INSTRUCTIONS.get(enhance): instructions.append(ENHANCE_INSTRUCTIONS[enhance]) + if timbre_description and timbre_description.strip(): + # This is AuK's Timbre task - the one actually used to build every + # character's base voice in this project (accent, age, register, + # personality all described in one free-form sentence). It has no + # fixed vocabulary, unlike Emotion below. + instructions.append( + f'Keep the spoken content unchanged and change the timbre to: "{timbre_description.strip()}".' + ) if emotion and emotion != "none": instructions.append(auk_emotion_instruction(emotion)) if other_emotion and other_emotion.strip(): @@ -577,13 +586,26 @@ with gr.Blocks(title="Audio-demo pipeline studio") as demo: list(ENHANCE_INSTRUCTIONS.keys()), value="none", label="Enhance (denoise/dereverb/restore) - runs first, before character edits", ) + timbre_tb = gr.Textbox( + label="Timbre / voice description (accent, age, register, personality)", + placeholder=( + 'e.g. "British male, mid-30s, dry and understated, slight Essex ' + 'accent, deadpan delivery" - this is what actually built every ' + "character's base voice in this project. Free-form, no fixed " + "vocabulary (unlike Emotion below)." + ), + lines=2, + ) emotion_dd = gr.Dropdown( ["none"] + EMOTIONS, value="none", label="Emotion (AuK's fixed vocabulary - anything else, use the field below)", ) other_emotion_tb = gr.Textbox( - label="Other emotion word (not in AuK's list)", - placeholder='e.g. "bemused" - automatically wrapped as a Timbre instruction instead', + label="Other emotion word (not in AuK's list above)", + placeholder='e.g. "bemused" - a single word for a momentary reaction, wrapped ' + "as a Timbre instruction automatically (different from the " + "voice-description field above, which is for the character's " + "lasting accent/age/personality)", ) pitch_dd = gr.Dropdown(["none"] + PITCH_OPTIONS, value="none", label="Pitch (semitones)") speed_dd = gr.Dropdown(["none"] + SPEED_OPTIONS, value="none", label="Speed") @@ -637,7 +659,7 @@ with gr.Blocks(title="Audio-demo pipeline studio") as demo: ) apply_btn.click( apply_edit, - inputs=[current_ref_audio, history_state, enhance_dd, emotion_dd, other_emotion_tb, + inputs=[current_ref_audio, history_state, enhance_dd, timbre_tb, emotion_dd, other_emotion_tb, pitch_dd, speed_dd, custom_instruction], outputs=[current_ref_audio, history_state, history_label, ref_transcript_box], )