Files
Memoh/internal/tts/adapter/edge/ws_integration_test.go
T
2026-03-13 02:49:52 +08:00

131 lines
3.8 KiB
Go

//go:build integration
package edge
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/memohai/memoh/internal/tts"
)
// Real Edge TTS integration tests. Not compiled by default (requires -tags=integration).
// Requires network access to speech.platform.bing.com.
//
// Run:
//
// go test -tags=integration ./internal/tts/adapter/edge/... -run TestRealEdgeTTS -v
func TestRealEdgeTTS_Synthesize(t *testing.T) {
client := NewEdgeWsClient()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
config := tts.AudioConfig{Voice: tts.VoiceConfig{ID: "en-US-JennyNeural", Lang: "en-US"}, Speed: 1.0}
audio, err := client.Synthesize(ctx, "Hello, this is a real Edge TTS test.", config)
if err != nil {
t.Fatalf("Synthesize: %v", err)
}
if len(audio) == 0 {
t.Fatal("expected non-empty audio from real Edge TTS")
}
t.Logf("got %d bytes of audio", len(audio))
}
func TestRealEdgeTTS_Stream(t *testing.T) {
client := NewEdgeWsClient()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
config := tts.AudioConfig{Voice: tts.VoiceConfig{ID: "zh-CN-XiaoxiaoNeural", Lang: "zh-CN"}}
ch, errCh := client.Stream(ctx, "你好,这是流式测试。", config)
var total int
for b := range ch {
total += len(b)
}
if err := <-errCh; err != nil {
t.Fatalf("Stream: %v", err)
}
if total == 0 {
t.Fatal("expected non-empty audio stream")
}
t.Logf("streamed %d bytes total", total)
}
// TestRealEdgeTTS_Formats tries every candidate format and reports which ones are supported.
//
// go test -tags=integration ./internal/tts/adapter/edge/... -run TestRealEdgeTTS_Formats -v
func TestRealEdgeTTS_Formats(t *testing.T) {
formats := []string{
"audio-24khz-48kbitrate-mono-mp3",
"audio-24khz-96kbitrate-mono-mp3",
"webm-24khz-16bit-mono-opus",
}
for _, fmt := range formats {
t.Run(fmt, func(t *testing.T) {
client := NewEdgeWsClient()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
config := tts.AudioConfig{
Voice: tts.VoiceConfig{ID: "en-US-JennyNeural", Lang: "en-US"},
Format: fmt,
Speed: 1.0,
}
audio, err := client.Synthesize(ctx, "Hello, format test.", config)
if err != nil {
t.Errorf("UNSUPPORTED format %q: %v", fmt, err)
return
}
t.Logf("OK format %q -> %d bytes", fmt, len(audio))
})
}
}
// TestRealEdgeTTS_SaveAudio synthesizes speech and writes the result to a file for manual inspection.
//
// go test -tags=integration ./internal/tts/adapter/edge/... -run TestRealEdgeTTS_SaveAudio -v
func TestRealEdgeTTS_SaveAudio(t *testing.T) {
client := NewEdgeWsClient()
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
cases := []struct {
name string
text string
voice tts.VoiceConfig
file string
}{
{"en", "Hello, this is an Edge TTS audio save test.", tts.VoiceConfig{ID: "en-US-JennyNeural", Lang: "en-US"}, "test_en.mp3"},
{"zh", "你好,这是一段中文语音合成测试。", tts.VoiceConfig{ID: "zh-CN-XiaoxiaoNeural", Lang: "zh-CN"}, "test_zh.mp3"},
}
outDir := filepath.Join(os.TempDir(), "edge_tts_test")
if err := os.MkdirAll(outDir, 0o755); err != nil {
t.Fatalf("mkdir %s: %v", outDir, err)
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
config := tts.AudioConfig{Voice: tc.voice, Speed: 1.0, Pitch: -10.0}
audio, err := client.Synthesize(ctx, tc.text, config)
if err != nil {
t.Fatalf("Synthesize: %v", err)
}
if len(audio) == 0 {
t.Fatal("expected non-empty audio")
}
outPath := filepath.Join(outDir, tc.file)
if err := os.WriteFile(outPath, audio, 0o644); err != nil {
t.Fatalf("write file: %v", err)
}
t.Logf("saved %d bytes -> %s", len(audio), outPath)
})
}
}