summaryrefslogtreecommitdiff
path: root/internal/processor
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 17:46:07 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 17:46:07 +0300
commitf3d057fec20aeef584cb6340c6a002280a019f15 (patch)
tree018be28f954243414969e8b8970fb3f3be8da112 /internal/processor
parent1fc2ade33b72dd299fc987943ddd09dee7c609ad (diff)
task 002: restore Gemini warning output
Diffstat (limited to 'internal/processor')
-rw-r--r--internal/processor/processor.go12
-rw-r--r--internal/processor/processor_test.go50
2 files changed, 58 insertions, 4 deletions
diff --git a/internal/processor/processor.go b/internal/processor/processor.go
index f6eb706..2343120 100644
--- a/internal/processor/processor.go
+++ b/internal/processor/processor.go
@@ -28,6 +28,7 @@ type Processor struct {
translator *translation.Translator
translationCache *translation.TranslationCache
phoneticFetcher *phonetic.Fetcher
+ randomIntn func(n int) int
}
var newOpenAIImageClient = func(config *image.OpenAIConfig) image.ImageSearcher {
@@ -51,6 +52,7 @@ func NewProcessor(flags *cli.Flags) *Processor {
translator: translation.NewTranslator(&translation.Config{Provider: translationProvider, OpenAIKey: openAIKey, GoogleAPIKey: googleAPIKey}),
translationCache: translation.NewTranslationCache(),
phoneticFetcher: phonetic.NewFetcher(&phonetic.Config{Provider: phoneticProvider, OpenAIKey: openAIKey, GoogleAPIKey: googleAPIKey}),
+ randomIntn: rand.Intn,
}
}
@@ -317,12 +319,18 @@ func (p *Processor) audioVoiceForProvider() string {
return voice
}
voices := p.audioVoicesForProvider()
+ if p.randomIntn != nil {
+ return voices[p.randomIntn(len(voices))]
+ }
return voices[rand.Intn(len(voices))]
default:
if voice := p.openAIVoice(); voice != "" {
return voice
}
voices := p.audioVoicesForProvider()
+ if p.randomIntn != nil {
+ return voices[p.randomIntn(len(voices))]
+ }
return voices[rand.Intn(len(voices))]
}
}
@@ -361,6 +369,8 @@ func (p *Processor) generateAudio(word string) error {
fmt.Printf(" Retrying Gemini audio with voice: %s\n", candidate)
}
return p.generateAudioWithVoice(word, candidate)
+ }, func(candidate string) {
+ fmt.Printf(" Warning: Gemini returned no audio for voice %s\n", candidate)
})
return err
}
@@ -411,6 +421,8 @@ func (p *Processor) generateAudioBgBg(front, back string) error {
fmt.Printf(" Retrying Gemini audio with voice: %s\n", candidate)
}
return generatePair(candidate)
+ }, func(candidate string) {
+ fmt.Printf(" Warning: Gemini returned no audio for voice %s\n", candidate)
})
return err
}
diff --git a/internal/processor/processor_test.go b/internal/processor/processor_test.go
index 9f59bac..dcb8e06 100644
--- a/internal/processor/processor_test.go
+++ b/internal/processor/processor_test.go
@@ -1,6 +1,7 @@
package processor
import (
+ "bytes"
"context"
"errors"
"fmt"
@@ -100,6 +101,39 @@ func (f *fakeAudioProvider) IsAvailable() error {
return nil
}
+func captureStdout(t *testing.T, fn func()) (output string) {
+ t.Helper()
+
+ originalStdout := os.Stdout
+ reader, writer, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("failed to create stdout pipe: %v", err)
+ }
+
+ os.Stdout = writer
+ outputCh := make(chan string, 1)
+ defer func() {
+ os.Stdout = originalStdout
+ if err := writer.Close(); err != nil {
+ t.Fatalf("failed to close stdout pipe: %v", err)
+ }
+ output = <-outputCh
+ if err := reader.Close(); err != nil {
+ t.Fatalf("failed to close stdout reader: %v", err)
+ }
+ }()
+
+ go func() {
+ var buf bytes.Buffer
+ _, _ = io.Copy(&buf, reader)
+ outputCh <- buf.String()
+ }()
+
+ fn()
+
+ return output
+}
+
func TestNewProcessor(t *testing.T) {
t.Setenv("OPENAI_API_KEY", "test-openai-key")
t.Setenv("GOOGLE_API_KEY", "test-google-key")
@@ -712,10 +746,18 @@ func TestGenerateGeminiAudioWithFallbacksRetriesAlternateVoice(t *testing.T) {
flags.AudioProvider = "gemini"
p := NewProcessor(flags)
- if _, err := audio.RunWithVoiceFallbacks("Charon", func(voice string) error {
- return p.generateAudioWithVoice("ябълка", voice)
- }); err != nil {
- t.Fatalf("RunWithVoiceFallbacks() unexpected error: %v", err)
+ p.randomIntn = func(int) int { return 0 }
+ output := captureStdout(t, func() {
+ if err := p.generateAudio("ябълка"); err != nil {
+ t.Fatalf("generateAudio() unexpected error: %v", err)
+ }
+ })
+
+ if !strings.Contains(output, " Warning: Gemini returned no audio for voice Charon") {
+ t.Fatalf("stdout missing indented Gemini warning: %q", output)
+ }
+ if !strings.Contains(output, " Retrying Gemini audio with voice: Kore") {
+ t.Fatalf("stdout missing retry message: %q", output)
}
if got, want := strings.Join(attemptedVoices, ","), "Charon,Kore"; got != want {