- upload: validate target folder with resolve_within, refuse to overwrite an existing voice unless overwrite=1, stage audio/transcripts and swap them in together so conversion or disk failures keep the previous voice, drop stale .txt/.orig.txt and other-format siblings, write .orig.txt for the native script - ffmpeg is resolved explicitly (PATH, then portable python dir) with a timeout - voice/gallery scans run in a worker thread; stems are unique across scan folders; audio URLs are percent-encoded and versioned by mtime - stream and delete only accept audio extensions; paging and template names are validated; errors are JSON - romanizer no longer reads Han-only (Chinese) text as Japanese and reports missing pykakasi / hangul-romanize instead of silently succeeding - extension static files use Cache-Control: no-cache (revalidate) instead of no-store; document the deliberate PATH exception in __init__.py Verified: new local tests/test_audio_catalog.py (14 tests) plus the existing Python suite (78 tests) pass in a Linux venv; not yet exercised in ComfyUI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W411Z69FC3em9CzpeqEub5
26 lines
1016 B
Python
26 lines
1016 B
Python
import os
|
|
import sys
|
|
|
|
# Deliberate process-wide exception (AGENTS.md section 5): the portable build ships
|
|
# ffmpeg/ffprobe beside python.exe, and audio nodes such as ComfyUI-F5-TTS look them
|
|
# up on PATH. Only missing directories are prepended. This plugin's own conversion
|
|
# resolves ffmpeg explicitly in api/audio_catalog.py and does not rely on this.
|
|
python_dir = os.path.dirname(sys.executable)
|
|
scripts_dir = os.path.join(python_dir, "Scripts")
|
|
for p in [python_dir, scripts_dir]:
|
|
if os.path.isdir(p) and p not in os.environ.get("PATH", ""):
|
|
os.environ["PATH"] = p + os.pathsep + os.environ.get("PATH", "")
|
|
|
|
from .api import setup_routes
|
|
from server import PromptServer
|
|
|
|
WEB_DIRECTORY = "./web"
|
|
|
|
# 注册 API 路由
|
|
if hasattr(PromptServer, "instance") and PromptServer.instance is not None:
|
|
setup_routes(PromptServer.instance.app)
|
|
|
|
NODE_CLASS_MAPPINGS = {}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY']
|