From fe773e70eff53efe32270862f5be0d900e50eea3 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 8 Apr 2026 10:10:33 +0300 Subject: config: centralize NanoBanana and audio defaults in defaults.go Add internal/config/defaults.go with shared model IDs, output format, OpenAI/Gemini audio literals, and speed defaults. Wire audio.DefaultProviderConfig, CLI flags, GUI defaulting paths, and image package re-exports to these constants. Update command_test to use the public config identifiers. Made-with: Cursor --- internal/audio/provider.go | 23 ++++++++++++----------- internal/cli/command_test.go | 5 +++-- internal/cli/flags.go | 12 +++++------- internal/config/defaults.go | 36 ++++++++++++++++++++++++++++++++++++ internal/gui/app.go | 8 ++++---- internal/image/nanobanana.go | 5 +++-- 6 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 internal/config/defaults.go (limited to 'internal') diff --git a/internal/audio/provider.go b/internal/audio/provider.go index 0a9a4b8..424b946 100644 --- a/internal/audio/provider.go +++ b/internal/audio/provider.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "codeberg.org/snonux/totalrecall/internal/config" "codeberg.org/snonux/totalrecall/internal/registry" ) @@ -117,19 +118,19 @@ func geminiAudioConfigFrom(c *Config) GeminiAudioConfig { } } -// DefaultConfig returns default configuration +// DefaultProviderConfig returns default configuration (shared literals live in +// internal/config/defaults.go). func DefaultProviderConfig() *Config { return &Config{ - Provider: "gemini", - OutputDir: "./", - OutputFormat: "mp3", - OpenAIModel: "gpt-4o-mini-tts", // New model with voice instructions support - OpenAIVoice: "alloy", - OpenAISpeed: 1.0, - // OpenAISpeed: 0.98, // Default speed for clarity - OpenAIInstruction: "You are speaking Bulgarian language (български език). Pronounce the Bulgarian text with authentic Bulgarian phonetics, not Russian. Speak slowly and clearly for language learners.", - GeminiTTSModel: "gemini-2.5-flash-preview-tts", - GeminiSpeed: 1.0, + Provider: config.ProviderGemini, + OutputDir: "./", + OutputFormat: config.DefaultAudioOutputFormat, + OpenAIModel: config.DefaultOpenAIAudioModel, + OpenAIVoice: config.DefaultOpenAIVoice, + OpenAISpeed: config.DefaultOpenAIAudioSpeed, + OpenAIInstruction: config.DefaultOpenAIAudioInstruction, + GeminiTTSModel: config.DefaultGeminiTTSModel, + GeminiSpeed: config.DefaultGeminiAudioSpeed, } } diff --git a/internal/cli/command_test.go b/internal/cli/command_test.go index afc1e18..80626eb 100644 --- a/internal/cli/command_test.go +++ b/internal/cli/command_test.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/viper" "codeberg.org/snonux/totalrecall/internal/audio" + "codeberg.org/snonux/totalrecall/internal/config" ) func TestCreateRootCommand(t *testing.T) { @@ -506,10 +507,10 @@ func TestMarkExplicitFlagValues(t *testing.T) { if err := cmd.Flags().Set("format", "mp3"); err != nil { t.Fatalf("Failed to set format flag: %v", err) } - if err := cmd.Flags().Set("nanobanana-model", defaultNanoBananaModel); err != nil { + if err := cmd.Flags().Set("nanobanana-model", config.DefaultNanoBananaModel); err != nil { t.Fatalf("Failed to set nanobanana-model flag: %v", err) } - if err := cmd.Flags().Set("nanobanana-text-model", defaultNanoBananaTextModel); err != nil { + if err := cmd.Flags().Set("nanobanana-text-model", config.DefaultNanoBananaTextModel); err != nil { t.Fatalf("Failed to set nanobanana-text-model flag: %v", err) } diff --git a/internal/cli/flags.go b/internal/cli/flags.go index a343767..21e89d7 100644 --- a/internal/cli/flags.go +++ b/internal/cli/flags.go @@ -1,10 +1,8 @@ package cli -import "codeberg.org/snonux/totalrecall/internal/audio" - -const ( - defaultNanoBananaModel = "gemini-3.1-flash-image-preview" - defaultNanoBananaTextModel = "gemini-2.5-flash" +import ( + "codeberg.org/snonux/totalrecall/internal/audio" + "codeberg.org/snonux/totalrecall/internal/config" ) // Flags holds all command-line flag values @@ -84,7 +82,7 @@ func NewFlags() *Flags { OpenAIImageQuality: "standard", OpenAIImageStyle: "natural", GeminiTTSModel: defaults.GeminiTTSModel, - NanoBananaModel: defaultNanoBananaModel, - NanoBananaTextModel: defaultNanoBananaTextModel, + NanoBananaModel: config.DefaultNanoBananaModel, + NanoBananaTextModel: config.DefaultNanoBananaTextModel, } } diff --git a/internal/config/defaults.go b/internal/config/defaults.go new file mode 100644 index 0000000..449e62a --- /dev/null +++ b/internal/config/defaults.go @@ -0,0 +1,36 @@ +package config + +// Central defaults for Nano Banana (Gemini image) models and shared audio settings. +// CLI, GUI, internal/audio, and callers resolve flag/config zero values against these +// constants so model IDs and format strings are not duplicated (DRY). + +const ( + // DefaultNanoBananaModel is the Gemini image model used for Nano Banana generation. + DefaultNanoBananaModel = "gemini-3.1-flash-image-preview" + + // DefaultNanoBananaTextModel is the Gemini text model used for Nano Banana prompt + // and scene-related text generation. + DefaultNanoBananaTextModel = "gemini-2.5-flash" + + // DefaultAudioOutputFormat is the default TTS file extension / container (e.g. mp3, wav). + DefaultAudioOutputFormat = "mp3" + + // DefaultOpenAIAudioModel is the default OpenAI TTS model when that provider is selected. + DefaultOpenAIAudioModel = "gpt-4o-mini-tts" + + // DefaultOpenAIVoice is the default OpenAI TTS voice. + DefaultOpenAIVoice = "alloy" + + // DefaultGeminiTTSModel is the default Gemini TTS model identifier. + DefaultGeminiTTSModel = "gemini-2.5-flash-preview-tts" + + // DefaultOpenAIAudioInstruction is the default system instruction for OpenAI TTS + // when generating Bulgarian learner audio. + DefaultOpenAIAudioInstruction = "You are speaking Bulgarian language (български език). Pronounce the Bulgarian text with authentic Bulgarian phonetics, not Russian. Speak slowly and clearly for language learners." +) + +// Default audio tuning (non-string defaults for internal/audio.Config). +const ( + DefaultOpenAIAudioSpeed = 1.0 + DefaultGeminiAudioSpeed = 1.0 +) diff --git a/internal/gui/app.go b/internal/gui/app.go index 56942e3..ff23acf 100644 --- a/internal/gui/app.go +++ b/internal/gui/app.go @@ -175,8 +175,8 @@ func DefaultConfig() *Config { OutputDir: outputDir, AudioFormat: audioDefaults.OutputFormat, AudioProvider: audioDefaults.Provider, - NanoBananaModel: image.DefaultNanoBananaModel, - NanoBananaTextModel: image.DefaultNanoBananaTextModel, + NanoBananaModel: appconfig.DefaultNanoBananaModel, + NanoBananaTextModel: appconfig.DefaultNanoBananaTextModel, GeminiTTSModel: audioDefaults.GeminiTTSModel, ImageProvider: image.ImageProviderNanoBanana, TranslationProvider: translation.ProviderGemini, @@ -249,7 +249,7 @@ func applyConfigDefaults(config *Config) *Config { if strings.EqualFold(config.AudioProvider, "gemini") { config.AudioFormat = defaults.AudioFormat } else { - config.AudioFormat = "mp3" + config.AudioFormat = appconfig.DefaultAudioOutputFormat } } if config.ImageProvider == "" { @@ -344,7 +344,7 @@ func audioConfigForApp(config *Config) *audio.Config { if provider == "gemini" { outputFormat = defaults.OutputFormat } else { - outputFormat = "mp3" + outputFormat = appconfig.DefaultAudioOutputFormat } } diff --git a/internal/image/nanobanana.go b/internal/image/nanobanana.go index 34a83ba..7694069 100644 --- a/internal/image/nanobanana.go +++ b/internal/image/nanobanana.go @@ -17,15 +17,16 @@ import ( "google.golang.org/genai" + "codeberg.org/snonux/totalrecall/internal/config" "codeberg.org/snonux/totalrecall/internal/httpctx" ) const ( // DefaultNanoBananaModel is the Gemini image model used for Nano Banana generation. - DefaultNanoBananaModel = "gemini-3.1-flash-image-preview" + DefaultNanoBananaModel = config.DefaultNanoBananaModel // DefaultNanoBananaTextModel is the Gemini text model used for translation and scene generation. - DefaultNanoBananaTextModel = "gemini-2.5-flash" + DefaultNanoBananaTextModel = config.DefaultNanoBananaTextModel nanoBananaAspectRatio = "4:3" nanoBananaDataPrefix = "data:image/png;base64," -- cgit v1.2.3