Files
ttstd-infinite-canvas/backend/internal/protocol/autodl_indextts2_test.go

96 lines
4.5 KiB
Go

package protocol
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
)
// IndexTTS2 的音色完全来自 prompt_simple 参考音频,缺失时上游返回“缺少必填参数”,
// 因此插件必须把画布连线的参考音频映射过去,并在本地拦截未连接音频的请求。
func TestAutoDLIndexTTS2Workflow(t *testing.T) {
data, err := os.ReadFile(filepath.Join("..", "..", "..", "plugin-packages", "autodl-comfyui.yingce-plugin"))
if err != nil {
t.Fatal(err)
}
pkg, err := ParsePluginPackage(data)
if err != nil {
t.Fatal(err)
}
adapters, err := LoadInstalledProviders(pkg.ManifestRaw, nil)
if err != nil {
t.Fatal(err)
}
var adapter Adapter
for _, a := range adapters {
if a.Metadata().ID == "autodl-comfyui-audio" {
adapter = a
}
}
if adapter == nil {
t.Fatal("autodl-comfyui-audio provider adapter not found")
}
if !adapter.Metadata().RequiresPublicMediaURLs {
t.Fatal("IndexTTS2 reference audio must be sent as public URLs")
}
if _, err := adapter.BuildCreate(context.Background(), RequestContext{BaseURL: "https://autodl.art", Request: GenerationRequest{
Capability: CapabilityAudio, Model: "indextts2-v1", Prompt: "你好,这是一段测试文本",
}}); err == nil || !strings.Contains(err.Error(), "音色参考音频") {
t.Fatalf("missing prompt_simple must be rejected locally, err = %v", err)
}
create, err := adapter.BuildCreate(context.Background(), RequestContext{BaseURL: "https://autodl.art", Request: GenerationRequest{
Capability: CapabilityAudio, Model: "indextts2-v1", Prompt: "你好,这是一段测试文本",
Audios: []MediaReference{{URL: "https://cdn.example/voice.mp3", Order: 0}},
Extra: map[string]any{"audioVoice": "alloy"},
}})
if err != nil {
t.Fatal(err)
}
if create.Method != "POST" || create.Path != "/api/v1/comfyui/comfyui_workflow/indextts2-v1" {
t.Fatalf("create spec = %#v", create)
}
body := create.Body.(map[string]any)
if body["prompt_text"] != "你好,这是一段测试文本" || body["prompt_simple"] != "https://cdn.example/voice.mp3" || body["emo_control_method"] != "与音色参考音频相同" || body["emo_random"] != false {
t.Fatalf("single reference body = %#v", body)
}
for _, name := range []string{"emo_happy", "emo_angry", "emo_sad", "emo_afraid", "emo_disgusted", "emo_melancholic", "emo_surprised", "emo_calm"} {
if value, ok := body[name]; !ok || manifestFloat(value) != 0 {
t.Fatalf("%s = %#v, body = %#v", name, value, body)
}
}
for _, name := range []string{"emo_ref_audio", "voice", "prompt"} {
if _, exists := body[name]; exists {
t.Fatalf("single reference body must not send %s: %#v", name, body)
}
}
withEmotion, err := adapter.BuildCreate(context.Background(), RequestContext{BaseURL: "https://autodl.art", Request: GenerationRequest{
Capability: CapabilityAudio, Model: "indextts2-v1", Prompt: "测试",
Audios: []MediaReference{{URL: "https://cdn.example/emotion.mp3", Order: 2}, {URL: "https://cdn.example/voice.mp3", Order: 1}},
ProviderOptions: map[string]map[string]any{"autodl-comfyui-audio": {"emo_happy": 0.5, "emo_calm": 0.3}},
}})
if err != nil {
t.Fatal(err)
}
emotionBody := withEmotion.Body.(map[string]any)
if emotionBody["prompt_simple"] != "https://cdn.example/voice.mp3" || emotionBody["emo_ref_audio"] != "https://cdn.example/emotion.mp3" || emotionBody["emo_control_method"] != "使用情感参考音频" || manifestFloat(emotionBody["emo_happy"]) != 0.5 || manifestFloat(emotionBody["emo_calm"]) != 0.3 {
t.Fatalf("emotion reference body = %#v", emotionBody)
}
if _, err := adapter.BuildCreate(context.Background(), RequestContext{BaseURL: "https://autodl.art", Request: GenerationRequest{
Capability: CapabilityAudio, Model: "indextts2-v1", Prompt: "测试",
Audios: []MediaReference{{URL: "https://cdn.example/a.mp3"}, {URL: "https://cdn.example/b.mp3", Order: 1}, {URL: "https://cdn.example/c.mp3", Order: 2}},
}}); err == nil {
t.Fatal("more than two reference audios must be rejected")
}
completed, err := adapter.ParsePoll(context.Background(), PollContext{TaskID: "671ce5ca"}, []byte(`{"msg":"","code":"Success","data":{"status":"completed","results":[{"url":"https://cos.example/ComfyUI_00010_.wav","type":"audio","node_id":"9","file_type":"wav","output_type":"output"}],"task_id":"671ce5ca"}}`))
if err != nil || completed.Status != StatusSucceeded || completed.Result == nil || len(completed.Result.Audios) != 1 || completed.Result.Audios[0].URL != "https://cos.example/ComfyUI_00010_.wav" {
t.Fatalf("completed = %#v, err = %v", completed, err)
}
}