feat(audio): set audio content type (#8416)

* feat(audio): set audio content type

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* chore: add tests

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2026-02-05 19:14:12 +01:00
committed by GitHub
parent 218d0526cb
commit 697f6aa71c
8 changed files with 179 additions and 20 deletions

View File

@@ -120,7 +120,15 @@ func (m *MockBackend) GenerateVideo(ctx context.Context, in *pb.GenerateVideoReq
func (m *MockBackend) TTS(ctx context.Context, in *pb.TTSRequest) (*pb.Result, error) {
xlog.Debug("TTS called", "text", in.Text)
// Return success - actual audio would be in the Result message for real backends
dst := in.GetDst()
if dst != "" {
if err := os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
return &pb.Result{Message: err.Error(), Success: false}, nil
}
if err := writeMinimalWAV(dst); err != nil {
return &pb.Result{Message: err.Error(), Success: false}, nil
}
}
return &pb.Result{
Message: "TTS audio generated successfully (mocked)",
Success: true,

View File

@@ -75,23 +75,20 @@ var _ = Describe("Mock Backend E2E Tests", Label("MockBackend"), func() {
Describe("TTS APIs", func() {
Context("TTS", func() {
It("should generate mocked audio", func() {
req, err := http.NewRequest("POST", apiURL+"/audio/speech", nil)
body := `{"model":"mock-model","input":"Hello world","voice":"default"}`
req, err := http.NewRequest("POST", apiURL+"/audio/speech", io.NopCloser(strings.NewReader(body)))
Expect(err).ToNot(HaveOccurred())
req.Header.Set("Content-Type", "application/json")
body := `{"model":"mock-model","input":"Hello world","voice":"default"}`
req.Body = http.NoBody
req.GetBody = func() (io.ReadCloser, error) {
return io.NopCloser(strings.NewReader(body)), nil
}
// Use direct HTTP client for TTS endpoint
httpClient := &http.Client{Timeout: 30 * time.Second}
resp, err := httpClient.Do(req)
if err == nil {
defer resp.Body.Close()
Expect(resp.StatusCode).To(BeNumerically("<", 500))
}
Expect(err).ToNot(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get("Content-Type")).To(HavePrefix("audio/"), "TTS response should set an audio Content-Type")
data, err := io.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
Expect(len(data)).To(BeNumerically(">", 0), "TTS response body should be non-empty")
})
})
})
@@ -107,7 +104,11 @@ var _ = Describe("Mock Backend E2E Tests", Label("MockBackend"), func() {
resp, err := httpClient.Do(req)
Expect(err).ToNot(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(BeNumerically("<", 500))
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get("Content-Type")).To(HavePrefix("audio/"), "sound-generation response should set an audio Content-Type (pkg/audio normalization)")
data, err := io.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
Expect(len(data)).To(BeNumerically(">", 0), "sound-generation response body should be non-empty")
})
It("should generate mocked sound (advanced mode)", func() {
@@ -120,7 +121,11 @@ var _ = Describe("Mock Backend E2E Tests", Label("MockBackend"), func() {
resp, err := httpClient.Do(req)
Expect(err).ToNot(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(BeNumerically("<", 500))
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get("Content-Type")).To(HavePrefix("audio/"), "sound-generation response should set an audio Content-Type (pkg/audio normalization)")
data, err := io.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
Expect(len(data)).To(BeNumerically(">", 0), "sound-generation response body should be non-empty")
})
})