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>
46 lines
1.8 KiB
JavaScript
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);
|
|
},
|
|
});
|
|
}
|