audio_helper.gui module

Audio Helper — single-page GUI (“Recipe Canvas”).

This module holds nothing but the self-contained HTML document served by the FastAPI app at GET /gui (see audio_helper.api). It is deliberately build-step-free: one string of HTML + Tailwind (via CDN) + vanilla ES-module JavaScript. There is no bundler, no framework, no npm — the whole page is a static asset the API returns verbatim.

Where the words live

In the markup, in English. Each one is wrapped as {{_("…")}} in the HTML, or listed in _JS_NAME_TO_SOURCE for the script, and os_helper.Catalog translates it through the compiled gettext catalogues under locales/ (CODING.md 21.3).

English is the msgid, so it needs no catalogue and cannot fall out of sync with one; a string the French catalogue has not caught up with renders as readable English instead of as a key. The cost is the mirror image: rewording the English here orphans its French entry, and gettext would quietly serve the English. tests/test_gui_i18n.py exists to catch that — it hands every source string to os_helper.Catalog.problems(), so an orphaned translation is a red build rather than a half-reverted page.

Two families of string stay out of the catalogue on purpose, and the locale file says why: the per-verb parameter labels in OPS, which name the form fields the request actually carries, and the comment header written into an exported recipe.yaml, which is a committable artifact rather than UI.

render_gui() resolves a language and returns the finished page.

From bench to canvas

The first shipped GUI was a minimal “audition bench”: one file, one operation, one A/B comparison. This module upgrades it to the Recipe Canvas described in GUI.md — a sequential pipeline where the user chains the eight verbs (convert, chunk, silence, concat, roomtone, split, separate, resemblance) into a recipe and hears every intermediate step.

The whole thing is still client-only: running a recipe calls the very same /convert / /chunk / … endpoints the CLI uses, in order, feeding each step’s output file straight into the next step’s input. No new server logic is required to run a recipe — the browser is the orchestrator.

What the page does

  • Drop / pick a local audio file (kept entirely client-side).

  • Build a recipe: add steps (one per verb), reorder them, set per-step params.

  • Run the recipe top-to-bottom; each step POSTs multipart/form-data to the existing API and the returned file becomes the next step’s input.

  • Per step: a WaveSurfer.js waveform + an <audio> player of that step’s output, plus a Bypass toggle (routes input straight to output for an instant A/B).

  • Ear-first comparator: pick any two produced clips, scrub them together, and toggle before / after at the same playhead with the space bar; an optional difference view highlights what changed.

  • Export / import the recipe as recipe.yaml so a pipeline is a committable artifact (both the YAML emit and parse happen client-side).

CDN libraries (no build step)

  • Tailwind CSS — utility styling.

  • WaveSurfer.js — waveform rendering + scrubbing.

  • Vega-Lite / Vega-Embed — spectrogram of a step’s output (roadmap-adjacent, rendered on demand rather than on every keystroke).

  • fflate — tiny in-browser unzip so split / separate (which return a .zip) can still feed a chosen member into a downstream step.

Why a separate module

Keeping the (long) HTML out of audio_helper.api keeps the route definitions readable and lets other repos in the AI Helpers suite copy this file almost verbatim as their GUI template: swap the operation list and the per-operation form fields, keep the plumbing.

Author

Warith Harchaoui, Ph.D. — https://linkedin.com/in/warith-harchaoui/

audio_helper.gui.default_language()[source]

The language an unknown or absent ?lang= falls back to.

Return type:

str

audio_helper.gui.render_gui(lang='')[source]

Render the single-page GUI in the requested language.

Parameters:

lang (str) – Two-letter language code. Anything outside the locale file’s a compiled catalogue — including the empty string — falls back to _DEFAULT_LANGUAGE, so an unknown ?lang= never 500s.

Returns:

The complete HTML document for that language.

Return type:

str

Examples

>>> "<!doctype html>" in render_gui("en")
True
>>> render_gui("tlh") == render_gui(default_language())
True
audio_helper.gui.supported_languages()[source]

Language codes the GUI can render: English plus every compiled catalogue.

Return type:

tuple[str, …]