Files
DemonGatanjieu-Anomalous_Mo…/web/modules/audio_voice_drag.js
T
DemonGatanjieuandClaude Opus 5.5 721a006b16 refactor(audio): drop F5-TTS, the audio page manages GPT-SoVITS only
The F5-TTS voice library (input/F5-TTS scanning, voice upload with ffmpeg
conversion, romanization, Load Audio clip drags) and the engine switch are
removed. The audio page now works with one engine, Anomalous_TTS
(GPT-SoVITS): characters, drags onto its node, the Script Director with
direct generation, pronunciation and settings. The audio gallery and its
stream route stay (output and temp folders only). The root PATH hack that
existed for F5-TTS's ffmpeg lookup is gone. Recorded as AD-016.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:53:07 +08:00

46 lines
1.8 KiB
JavaScript

import { app } from '../../../scripts/app.js';
import { t } from './interface_settings.js';
import { AUDIO_NODE_TARGETS, planVoiceDrop } from './audio_node_targets.js';
import { TTS_ENGINE } from './audio_engines.js';
import { bindMaterialDrag } from './material_drag.js';
/**
* Dragging a character onto a canvas node, shared by the studio cards and the
* audio sidebar. Which nodes take it is decided by audio_node_targets.js;
* unlisted nodes are refused, never guessed.
*/
/** Why a hovered node is refused; every refusal names what to do instead. */
function dropRejectHint(node, group) {
const plan = planVoiceDrop(node, group);
if (plan.ok) return '';
return t(`audioDropReject_${plan.reason}`, {
node: plan.target?.label || '',
supported: AUDIO_NODE_TARGETS.map(target => target.label).join(t('audioListSeparator')),
character: group.character,
file: plan.path || '',
});
}
export function bindVoiceDrag(element, group, owner) {
bindMaterialDrag(element, owner || {}, {
payload: () => ({
group,
dragHint: t('audioDragCharacterHint', { character: group.character, node: TTS_ENGINE.label }),
}),
accepts: node => planVoiceDrop(node, group).ok,
targetHint: node => {
const plan = planVoiceDrop(node, group);
return plan.ok ? t('audioDropCharacterTarget', { node: plan.target.label, character: group.character }) : '';
},
rejectHint: node => dropRejectHint(node, group),
drop: async node => {
const plan = planVoiceDrop(node, group);
if (!plan.ok) return;
plan.widget.value = plan.value;
plan.widget.callback?.(plan.value, app.canvas, node);
node.setDirtyCanvas?.(true, true);
},
});
}