The doc folders now track only their Markdown; screenshots, logs and raw
test data belong under the ignored .agents/. AGENTS.md section 0 says so,
and forbids local paths and file:/// links in committed files. Fixes the
existing audit index link that pointed at a local path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A folder holding one character's GPT + SoVITS weights and its clips is that
character, named after the folder: two characters whose weights are both
"model" no longer merge, pinyin weights in a Chinese-named folder take the
folder's name, version folders read "派蒙 v2". Package weight folders keep
the name-by-stem rule.
- Skip rules match the node (interface v9): Python environments and base
models always; GPT_SoVITS / logs / output / TEMP / tools only inside a
package; the chosen or dropped folder never. The drop walker and the folder
dialog apply them where the listing is known (the old re-check on each
file's path skipped a chosen folder called "output"), local scans prefix
the chosen folder so every source sorts alike, and the window names the
skipped and too-deep folders instead of losing files quietly. Drops only
open importable files and stop at 5000.
- Same-name files inside a character are renamed with their folder
(难过_01.wav, sent as the file's "name") instead of dropped; an unclaimed
.list goes to every character.
- Big adds open 20 characters (about 800 files) at a time; "next batch" opens
the rest, and it opens by itself once a batch is imported, replacing the
imported cards. Unassigned files upload only once put into a character.
- Every clip can be previewed while importing, local paths included (through
the node's preview route): one at a time, ▶ turns into stop, another clip
switches.
- Upload queue and preview player move to their own modules, the "add more"
menu to the screens module (ui_tts_import.js 647 → 652 lines with batches and renames added).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RMuwbsWZHnx2eCWpxYqAB
- A folder per character: clips and line files follow the weights in their
nearest folder, so pinyin weights, Chinese folders and English clips still
land together (a real 34-character folder: 3065 unassigned files -> 0).
- Clips outside 3-10 s and their same-name line files are left out of the
import and folded under "left out" instead of one warning per clip.
- GPT-SoVITS program and training folders are skipped in drops (not even
walked) and picked folders; a very large upload (>1500 files or 2 GB)
first offers the local folder picker.
- Uploads run three at a time, status repaints are coalesced, a card shows
its first 60 clips, move menus are filled when opened, and the unassigned
card folds into one line per folder that can be assigned at once.
- New ui_tts_import_sources.js brings files in (dialogs, drops, local picker).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ui_shortcut_organizer.js and shortcut_layout.js only referenced each other;
the bottom bar is the fixed one built in ui_toolbox.js. Also drops their
eleven locale keys and marks the customizable-shortcuts plan as abandoned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The import window now asks what the user has first: one character, many
characters or a package, or files for an existing character (picked from
a list, or opened straight from a card's "Add files"). Dropped files skip
the question.
Each character card leads with a checklist (GPT model, SoVITS model,
clips, main voice, name) that lights up the next step and offers its
button in that line; the chosen weights sit in their lines, and the
card header says how many steps are left. A main voice (3-10 s) is now
required for a new character, as GPT-SoVITS needs one.
A spotlight tour explains the first question and the card the first time
each is shown; "?" in the header replays it. ui_spotlight_tour.js takes
its steps and an onClose from the caller now; the browser tour is
unchanged. The fixed screens and tour steps live in
ui_tts_import_screens.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two-column workbench was hard to read on first open. The window now
opens as one drop area that says what to bring (GPT model, SoVITS model,
3-10 s clips) with two buttons and a quiet "files on this PC" line, and
three steps at the top show where the user is.
With files, each character is a card: folded, one line with the name
(edited in place), a short status and what it holds; unfolded, two model
tiles, one line per clip (main-voice star, emotion, line) and the line
files and language at the bottom. One card is open at a time; files that
match no character get a card of their own at the top. "Add more" is a
single button with a menu, the owner picker on each clip only shows on
hover, and the footer says what still needs a look and where it saves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The import form becomes a two-column workbench for one or many
characters. Files and whole folders can be dropped, or a folder on this
PC scanned (Anomalous_TTS browse?recursive=1, interface 6). Weights pair
up by name with the latest epoch kept; clips and line files follow their
folder or file-name prefix; anything unclear waits in an unassigned
tray. The left column lists the characters with a status dot, the right
shows the selected one with one compact line per clip and a picker (or
drag handle) to move files between characters. Ready characters are
imported one after another, each on its own, so a failure leaves the
others alone.
Grouping rules live in tts_import_groups.js, the draft pane in
ui_tts_import_draft.js and OS drop reading in ui_tts_file_drop.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each section title gets a mark (green check with counts, amber
"required" for what a new character still needs, red on problems) and
each row a coloured bar: green ready or merged, blue uploading, grey
skipped, red failed or refused. Clips scroll in their own box and the
Import button stays in view.
When adding to a character, inspect now sends the target (Anomalous_TTS
interface 5): files it already has show as skipped, annotation files as
merged, and a different file under the same name blocks the import.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sidebar groups characters by language (GPT-SoVITS) or folder
(F5-TTS) in foldable groups; a character unfolds into its clips and a
click plays one through the studio row. Characters drag onto nodes from
the sidebar, a red dot marks characters that need a look, a search box
shows from six characters on, and files dropped on a GPT-SoVITS
character open "Add files" for it.
GPT-SoVITS settings move to a dialog opened from the sidebar footer,
which carries the reminder dot; "Import character" moves into the
studio toolbar. Canvas drag helpers move to audio_voice_drag.js so the
sidebar and the cards share them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The setup card is one folded line; missing pretrained files (fetched on
first use anyway) only get a small dismissable dot once the studio's
characters need them, and the import form notes what the chosen
language will download. An empty GPT-SoVITS studio is a drop area with
the import button.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uses Anomalous_TTS interface v4.
- Setup card: "where characters are kept" replaces the library list.
"Change..." picks a folder on the ComfyUI machine and asks whether the
current characters move along (move / don't move / cancel). A move shows
its progress (characters, and bytes when copying across disks) and the
studio redraws when it ends; an error says where it stopped.
- "Other places" lists earlier storage places that still hold characters
and yaml folders; x on an earlier place stops listing it (files kept).
- Import form: no location picker; new characters go to the storage place
and the form shows the exact path.
- The "add library" action is gone (no longer offered by the node).
Tested: node tests/tts_setup_api.mjs (storage calls, moving summary).
Isolated ComfyUI in the browser: change storage with move (both
characters moved, a non-character folder left, config updated), change
back without moving (old place listed under other places, stale move
message not shown), remove the earlier place (characters unlisted, files
kept), import form shows the storage path; a .list dropped on a clip's
text box fills it without being added as a file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Each clip shows where its line came from (same-name .txt / .lab,
annotation file, or the file name, marked as a guess to check).
- Dropping a .txt / .lab / .list on a clip's line box fills it: a plain
file is the line, an annotation file is searched for that clip (same
rule as the node, including the name without the emotion part).
- .lab is an importable line file.
Tested: node tests/tts_setup_api.mjs (textFromFile added).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Fixed sections for GPT weight, SoVITS weight, reference clips and line
files; files dropped anywhere on the form go to their section. One GPT
and one SoVITS: a new one replaces the old, and from a batch the latest
epoch is kept (the others are named in a note).
- The save location is one line ("Saved to …/gpt_sovits/<name>") with
"Change location"; the library list only shows when asked for.
- Name clashes are shown while typing; an exact match offers "add to that
character instead", which switches the form to add mode in place.
- Unsupported SoVITS versions (v3/v4) are marked and block the import;
clips outside 3-10 s cannot be the main voice.
- After an import the studio scrolls to the new card and highlights it.
Tested: node tests/tts_setup_api.mjs (epoch pick, name clash, version
block, clip range added). Isolated ComfyUI in the browser: name clash and
switch to add mode, three GPT epochs -> e15 kept, SoVITS replaced by a v4
file -> blocked, short clips not selectable as main, add-mode import of a
clip as {平静} with the card highlighted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uses Anomalous_TTS interface v3 so a new user can get going without
editing extra_model_paths.yaml or sorting model folders by hand.
- Setup card on the GPT-SoVITS studio: character libraries (add/remove),
pretrained files (per-item or all download with progress, or use an
existing GPT-SoVITS package) and missing Python packages with the
install command. Collapses to one line when ready.
- Import form: drop files, pick them in the browser, or pick them on the
ComfyUI machine (server-side path picker, no upload). Name, SoVITS
version, clip length, lines, main voice and language are filled in from
the node's inspect; emotions per clip. Uploads go in 8 MB chunks.
- "Add files" on a card, or a drop onto it, adds clips and emotions to
that character without replacing its main voice.
- Hidden for nodes without v3; disabled when the page is not opened on
the ComfyUI machine.
- New modules: tts_setup_api.js (calls + pure form rules),
ui_tts_setup.js, ui_tts_import.js, ui_tts_path_picker.js and
styles/12-tts-setup.css. ui_audio_studio.js only wires them in.
Tested: node tests/tts_setup_api.mjs (new, local) plus the audio engine,
node target and script rule tests. Isolated ComfyUI with both plugins in
the browser: setup card for a fresh user, package as pretrained source,
library add, import from local paths (lines found in all.txt), file drop
onto a card (chunked upload, add mode), cancel discards the upload.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cache engine presence and voice groups (60 s) so domain switches, sidebar
clicks and the studio + sidebar pair cost no requests; saves and added
voices invalidate, Refresh also asks Anomalous_TTS to rescan (?refresh=1).
- Follow Anomalous_TTS interface v2: the list is a summary; the emotion
editor opens at once and loads the character's audio list in the
background (save waits for it, keeps unknown settings fields).
- Cards: show "角色/版本" as name + quiet suffix, one-line drag hint,
header wraps instead of squeezing.
- Docs: ARCHITECTURE audio_engines paragraph, audio-studio guide.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6FStZ5hiKELvNH3WKgBnx
- audio_engines.js: F5-TTS and GPT-SoVITS (the separate Anomalous_TTS node
pack), detected through /object_info/<node class>. Both engines' voices are
normalised into one voice-group shape so cards, sidebar and Script Director
share one implementation.
- The audio page shows an engine switch; a missing engine stays listed as
"not installed" with install steps (no popups). The F5-TTS library still
works without the F5-TTS node; GPT-SoVITS is never scanned when missing.
- GPT-SoVITS cards come only from the node's HTTP contract: preview reference
clips, drag a character onto AnomalousTTS_CharacterSpeech, and edit the
emotion references ("Edit emotions"), saved through /anomalous_tts/settings
with unknown fields preserved and the node's validation messages shown.
- Drop targets and the Script Director are per engine: voices of one engine
are refused on the other engine's node with the reason.
- Audio gallery reads the character of GPT-SoVITS generations.
- Usage guide (in-app and docs/guides/audio-studio.md) covers both engines.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeQEub5
- audio_node_targets.js is the only list of nodes the audio studio writes
into: F5-TTS (Audio / Advanced / FromModel) takes a whole character, so the
card header sets its main voice; ComfyUI's Load Audio takes one exact clip,
so a row sets that file. Unlisted nodes are refused instead of matched by
widget name, and a single emotion clip is never written into F5-TTS's
sample (it would break {emotion} tags).
- While dragging, the hint says what releasing will do, or why a hovered node
is refused and what to do instead (shared bindMaterialDrag targetHint /
rejectHint).
- Script Director uses the same table and refuses nodes whose sample_audio is
linked.
- In the audio domain the header "!" opens a five-step usage guide;
docs/guides/audio-studio.md is the full guide (docs/guides is now tracked).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeQEub5
Conflicts:
- api/__init__.py, web/styles.css: keep audio routes/styles and add the
version manager.
- README.md, CHANGELOG.md: take main's released text; this branch's
0922b27 was an earlier alignment of the same v1.57 notes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeQEub5
- api/version_manager.py: installed version (local only), published
releases on request (GitHub API, git tag fallback), switch to a
published tag, return to the default branch (fast-forward only), undo
the last switch; refuses to overwrite modified tracked files
- header version chip and "Version & updates" panel; nothing goes online
until "Check for updates" is clicked; restart via ComfyUI Manager
- zh/en strings, styles, architecture notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeQEub5
Conflicts resolved:
- entry trigger files, web/main.js, api/__init__.py: main carries the squashed
entry fix (09b06d1), identical to this branch before its later cleanup, so
this branch's versions are kept
- ARCHITECTURE.md, docs/architecture/backend.md, web/modules/ui_sidebar.js:
both sides' additions kept
Verified on the merged tree: 107 Python tests, all JS tests except the orphaned
material_parameter_cross_node.mjs, jsdom walkthroughs of the audio studio,
domain switching and the gallery search blocks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeqEub5
- api/image_search.py reads only the PNG text chunks before IDAT (ComfyUI
prompt/workflow, A1111 parameters), builds one small record per image and
caches it by mtime; all space-separated terms must match
- hex terms of 8+ characters also match SHA256 values recorded in the
workflow (extra.anomalous_hashes) and local model files with that hash, so
renamed models are still found; A1111 "Model hash" text matches as text
- gallery_images accepts q; the search box above the gallery debounces input,
shows the match count, keeps paging/infinite scroll and the detail viewer on
the filtered list, and lets a newer query supersede one still loading
On the local output (774 PNG) the first search reads ~10 MB of text chunks;
later searches use the cache.
Verified: tests/test_image_search.py (prompt, seed, AND terms, A1111, file
names, recorded and local-index hashes, cache, chunk reader), full Python suite
(106), jsdom walkthrough of the gallery search box.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeqEub5
- entry: one explicit legacy-coordinate cleanup instead of three module-load
side effects, no ?v= import, shared size estimate and DEFAULT_MIN_SAFE_X
instead of literals, drop unused exports; drag behavior unchanged
- explain the !important topbar-entry rules as AGENTS.md requires
- docs: restore the model_identity.py entry, describe the F5-TTS voice layout,
ingestion guarantees, the no-cache/no-?v= module rule, the shared all-in-one
adapter table and the no-cross-role prompt rule; remove pixel values and
promotional wording, fix the contradictory trigger position text
Verified: tests/floating_trigger_position.mjs (9 pass), jsdom setup of the real
browser entry plus an audio-domain navigation walkthrough (outside the repo).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeqEub5