feat: 支持 MiniMax 音色克隆和 2.8 语音模型
This commit is contained in:
@@ -182,6 +182,88 @@ func TestMinimaxClientSpeechUsesT2AV2AndNormalizesAudio(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinimaxVoiceCloneTextValidationPayload(t *testing.T) {
|
||||
var capturedClone map[string]any
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if got := r.Header.Get("Authorization"); got != "Bearer test-key" {
|
||||
t.Fatalf("unexpected auth header: %q", got)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch r.URL.Path {
|
||||
case "/files/upload":
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"file": map[string]any{"file_id": "123456"},
|
||||
"base_resp": map[string]any{"status_code": 0},
|
||||
})
|
||||
case "/voice_clone":
|
||||
if err := json.NewDecoder(r.Body).Decode(&capturedClone); err != nil {
|
||||
t.Fatalf("decode voice clone request: %v", err)
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"demo_audio": "",
|
||||
"base_resp": map[string]any{"status_code": 0},
|
||||
})
|
||||
default:
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.String())
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
_, err := (MinimaxClient{HTTPClient: server.Client()}).Run(context.Background(), Request{
|
||||
Kind: "voice.clone",
|
||||
Model: "MiniMax-Voice-Clone",
|
||||
Body: map[string]any{
|
||||
"voice_id": "voice_test_123",
|
||||
"audio_url": "data:audio/wav;base64," + base64.StdEncoding.EncodeToString([]byte("wave")),
|
||||
"text_validation": false,
|
||||
"need_noise_reduction": true,
|
||||
"need_volume_normalization": true,
|
||||
"aigc_watermark": false,
|
||||
},
|
||||
Candidate: store.RuntimeModelCandidate{
|
||||
Provider: "minimax",
|
||||
BaseURL: server.URL,
|
||||
ProviderModelName: "voice_clone",
|
||||
Credentials: map[string]any{"apiKey": "test-key"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("run minimax voice clone client: %v", err)
|
||||
}
|
||||
if _, ok := capturedClone["text_validation"]; ok {
|
||||
t.Fatalf("legacy boolean text_validation should be omitted: %+v", capturedClone)
|
||||
}
|
||||
if capturedClone["file_id"] != float64(123456) {
|
||||
t.Fatalf("file_id should be submitted as number: %+v", capturedClone)
|
||||
}
|
||||
|
||||
capturedClone = nil
|
||||
_, err = (MinimaxClient{HTTPClient: server.Client()}).Run(context.Background(), Request{
|
||||
Kind: "voice.clone",
|
||||
Model: "MiniMax-Voice-Clone",
|
||||
Body: map[string]any{
|
||||
"voice_id": "voice_test_456",
|
||||
"audio_url": "data:audio/wav;base64," + base64.StdEncoding.EncodeToString([]byte("wave")),
|
||||
"text_validation": " 这是一段用于校验的源音频文本 ",
|
||||
},
|
||||
Candidate: store.RuntimeModelCandidate{
|
||||
Provider: "minimax",
|
||||
BaseURL: server.URL,
|
||||
ProviderModelName: "voice_clone",
|
||||
Credentials: map[string]any{"apiKey": "test-key"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("run minimax voice clone client with transcript: %v", err)
|
||||
}
|
||||
if capturedClone["text_validation"] != "这是一段用于校验的源音频文本" {
|
||||
t.Fatalf("unexpected text_validation payload: %+v", capturedClone)
|
||||
}
|
||||
if capturedClone["file_id"] != float64(123456) {
|
||||
t.Fatalf("file_id should be submitted as number with transcript: %+v", capturedClone)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimulationDurationCanBeControlledByParams(t *testing.T) {
|
||||
fixedDuration := simulationDuration(Request{Body: map[string]any{"simulationDurationSeconds": 7}})
|
||||
if fixedDuration != 7*time.Second {
|
||||
|
||||
Reference in New Issue
Block a user