summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-22 07:54:57 +0300
committerPaul Buetow <paul@buetow.org>2025-07-22 07:54:57 +0300
commit1cc15cfbd68d45ae6d561e5659422e72bf9ecd1d (patch)
tree92bd29d34fed9c4d28cfe4d94e35b040c0b505bc /internal
parent1365dde5c25e1865b82fbfea50208327d5e3a51c (diff)
Remove audio cache feature to simplify codebase and avoid cache-related issues
πŸ€– Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <noreply@opencode.ai>
Diffstat (limited to 'internal')
-rw-r--r--internal/audio/openai_provider.go111
-rw-r--r--internal/audio/openai_provider_test.go195
-rw-r--r--internal/audio/provider.go5
-rw-r--r--internal/audio/provider_test.go7
-rw-r--r--internal/gui/app.go2
-rw-r--r--internal/processor/processor.go9
6 files changed, 6 insertions, 323 deletions
diff --git a/internal/audio/openai_provider.go b/internal/audio/openai_provider.go
index 0f3a0ad..3c2a22d 100644
--- a/internal/audio/openai_provider.go
+++ b/internal/audio/openai_provider.go
@@ -2,8 +2,6 @@ package audio
import (
"context"
- "crypto/md5"
- "encoding/hex"
"fmt"
"io"
"os"
@@ -15,10 +13,8 @@ import (
// OpenAIProvider implements Provider interface for OpenAI TTS
type OpenAIProvider struct {
- client *openai.Client
- config *Config
- cacheDir string
- enableCache bool
+ client *openai.Client
+ config *Config
}
// NewOpenAIProvider creates a new OpenAI TTS provider
@@ -30,17 +26,8 @@ func NewOpenAIProvider(config *Config) (Provider, error) {
client := openai.NewClient(config.OpenAIKey)
provider := &OpenAIProvider{
- client: client,
- config: config,
- cacheDir: config.CacheDir,
- enableCache: config.EnableCache,
- }
-
- // Create cache directory if caching is enabled
- if provider.enableCache && provider.cacheDir != "" {
- if err := os.MkdirAll(provider.cacheDir, 0755); err != nil {
- return nil, fmt.Errorf("failed to create cache directory: %w", err)
- }
+ client: client,
+ config: config,
}
return provider, nil
@@ -53,15 +40,6 @@ func (p *OpenAIProvider) GenerateAudio(ctx context.Context, text string, outputF
return err
}
- // Check cache first
- if p.enableCache {
- cacheFile := p.getCacheFilePath(text)
- if _, err := os.Stat(cacheFile); err == nil {
- // Cache hit - copy cached file
- return p.copyFile(cacheFile, outputFile)
- }
- }
-
// Preprocess text for clearer Bulgarian pronunciation
processedText := p.preprocessBulgarianText(text)
@@ -142,12 +120,6 @@ func (p *OpenAIProvider) GenerateAudio(ctx context.Context, text string, outputF
return fmt.Errorf("no audio data received from OpenAI")
}
- // Cache the result if caching is enabled
- if p.enableCache {
- cacheFile := p.getCacheFilePath(text)
- _ = p.copyFile(outputFile, cacheFile) // Ignore cache errors
- }
-
return nil
}
@@ -187,78 +159,3 @@ func (p *OpenAIProvider) preprocessBulgarianText(text string) string {
return processedText
}
-
-// getCacheFilePath generates a cache file path for the given text
-func (p *OpenAIProvider) getCacheFilePath(text string) string {
- // Create a hash of the text and settings
- h := md5.New()
- h.Write([]byte(text))
- h.Write([]byte(p.config.OpenAIModel))
- h.Write([]byte(p.config.OpenAIVoice))
- h.Write([]byte(fmt.Sprintf("%.2f", p.config.OpenAISpeed)))
- // Include instruction in cache key for gpt-4o-mini-tts
- if p.config.OpenAIModel == "gpt-4o-mini-tts" && p.config.OpenAIInstruction != "" {
- h.Write([]byte(p.config.OpenAIInstruction))
- }
- hash := hex.EncodeToString(h.Sum(nil))
-
- // Use first 2 chars as subdirectory for better file system performance
- subdir := hash[:2]
- filename := hash[2:] + ".mp3"
-
- return filepath.Join(p.cacheDir, subdir, filename)
-}
-
-// copyFile copies a file from src to dst
-func (p *OpenAIProvider) copyFile(src, dst string) error {
- // Ensure destination directory exists
- dir := filepath.Dir(dst)
- if dir != "" && dir != "." {
- if err := os.MkdirAll(dir, 0755); err != nil {
- return err
- }
- }
-
- source, err := os.Open(src)
- if err != nil {
- return err
- }
- defer source.Close()
-
- destination, err := os.Create(dst)
- if err != nil {
- return err
- }
- defer destination.Close()
-
- _, err = io.Copy(destination, source)
- return err
-}
-
-// ClearCache removes all cached audio files
-func (p *OpenAIProvider) ClearCache() error {
- if p.cacheDir == "" {
- return nil
- }
- return os.RemoveAll(p.cacheDir)
-}
-
-// GetCacheStats returns cache statistics
-func (p *OpenAIProvider) GetCacheStats() (fileCount int, totalSize int64, err error) {
- if !p.enableCache || p.cacheDir == "" {
- return 0, 0, nil
- }
-
- err = filepath.Walk(p.cacheDir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !info.IsDir() {
- fileCount++
- totalSize += info.Size()
- }
- return nil
- })
-
- return fileCount, totalSize, err
-}
diff --git a/internal/audio/openai_provider_test.go b/internal/audio/openai_provider_test.go
index 7e3f9e5..ae16ca0 100644
--- a/internal/audio/openai_provider_test.go
+++ b/internal/audio/openai_provider_test.go
@@ -2,8 +2,6 @@ package audio
import (
"context"
- "os"
- "path/filepath"
"strings"
"testing"
)
@@ -24,19 +22,9 @@ func TestNewOpenAIProvider(t *testing.T) {
errMsg: "OpenAI API key is required",
},
{
- name: "valid config with cache",
+ name: "valid config",
config: &Config{
- OpenAIKey: "test-key",
- EnableCache: true,
- CacheDir: "./test_cache",
- },
- wantErr: false,
- },
- {
- name: "valid config without cache",
- config: &Config{
- OpenAIKey: "test-key",
- EnableCache: false,
+ OpenAIKey: "test-key",
},
wantErr: false,
},
@@ -52,11 +40,6 @@ func TestNewOpenAIProvider(t *testing.T) {
t.Errorf("NewOpenAIProvider() error = %v, want %v", err.Error(), tt.errMsg)
}
- // Cleanup cache dir if created
- if !tt.wantErr && tt.config.EnableCache && tt.config.CacheDir != "" {
- os.RemoveAll(tt.config.CacheDir)
- }
-
// Check provider properties
if !tt.wantErr && provider != nil {
if provider.Name() != "openai" {
@@ -149,180 +132,6 @@ func TestPreprocessBulgarianText(t *testing.T) {
}
}
-func TestGetCacheFilePath(t *testing.T) {
- provider := &OpenAIProvider{
- config: &Config{
- OpenAIModel: "tts-1",
- OpenAIVoice: "alloy",
- OpenAISpeed: 1.0,
- },
- cacheDir: "./test_cache",
- }
-
- // Test basic cache path generation
- path1 := provider.getCacheFilePath("ябълка")
- if !strings.HasPrefix(path1, "test_cache/") {
- t.Errorf("Cache path should start with cache dir, got %s", path1)
- }
- if !strings.HasSuffix(path1, ".mp3") {
- t.Errorf("Cache path should end with .mp3, got %s", path1)
- }
-
- // Test that same input produces same path
- path2 := provider.getCacheFilePath("ябълка")
- if path1 != path2 {
- t.Errorf("Same input should produce same cache path, got %s and %s", path1, path2)
- }
-
- // Test that different input produces different path
- path3 := provider.getCacheFilePath("ΠΊΠΎΡ‚ΠΊΠ°")
- if path1 == path3 {
- t.Errorf("Different input should produce different cache path")
- }
-
- // Test that different settings produce different paths
- provider.config.OpenAIVoice = "nova"
- path4 := provider.getCacheFilePath("ябълка")
- if path1 == path4 {
- t.Errorf("Different voice should produce different cache path")
- }
-
- // Test with instruction for gpt-4o-mini-tts
- provider.config.OpenAIModel = "gpt-4o-mini-tts"
- provider.config.OpenAIInstruction = "Test instruction"
- path5 := provider.getCacheFilePath("ябълка")
-
- provider.config.OpenAIInstruction = "Different instruction"
- path6 := provider.getCacheFilePath("ябълка")
- if path5 == path6 {
- t.Errorf("Different instruction should produce different cache path for gpt-4o-mini-tts")
- }
-}
-
-func TestCopyFile(t *testing.T) {
- // Create a temporary directory for testing
- tempDir := t.TempDir()
-
- provider := &OpenAIProvider{}
-
- // Create source file
- srcPath := filepath.Join(tempDir, "source.txt")
- srcContent := []byte("test content")
- if err := os.WriteFile(srcPath, srcContent, 0644); err != nil {
- t.Fatalf("Failed to create source file: %v", err)
- }
-
- // Test copying to new file
- dstPath := filepath.Join(tempDir, "dest.txt")
- err := provider.copyFile(srcPath, dstPath)
- if err != nil {
- t.Errorf("copyFile() error = %v", err)
- }
-
- // Verify content
- dstContent, err := os.ReadFile(dstPath)
- if err != nil {
- t.Fatalf("Failed to read destination file: %v", err)
- }
- if string(dstContent) != string(srcContent) {
- t.Errorf("Copied content doesn't match: got %q, want %q", dstContent, srcContent)
- }
-
- // Test copying to subdirectory
- dstPath2 := filepath.Join(tempDir, "subdir", "dest2.txt")
- err = provider.copyFile(srcPath, dstPath2)
- if err != nil {
- t.Errorf("copyFile() to subdirectory error = %v", err)
- }
-
- // Test copying non-existent file
- err = provider.copyFile(filepath.Join(tempDir, "nonexistent.txt"), dstPath)
- if err == nil {
- t.Error("copyFile() expected error for non-existent source")
- }
-}
-
-func TestClearCache(t *testing.T) {
- tempDir := t.TempDir()
-
- provider := &OpenAIProvider{
- cacheDir: filepath.Join(tempDir, "cache"),
- }
-
- // Create cache directory with some files
- os.MkdirAll(filepath.Join(provider.cacheDir, "ab"), 0755)
- os.WriteFile(filepath.Join(provider.cacheDir, "ab", "test1.mp3"), []byte("data1"), 0644)
- os.WriteFile(filepath.Join(provider.cacheDir, "ab", "test2.mp3"), []byte("data2"), 0644)
-
- // Clear cache
- err := provider.ClearCache()
- if err != nil {
- t.Errorf("ClearCache() error = %v", err)
- }
-
- // Verify cache directory is gone
- if _, err := os.Stat(provider.cacheDir); !os.IsNotExist(err) {
- t.Error("Cache directory should be removed")
- }
-
- // Test clearing with empty cache dir
- provider.cacheDir = ""
- err = provider.ClearCache()
- if err != nil {
- t.Errorf("ClearCache() with empty dir should not error: %v", err)
- }
-}
-
-func TestGetCacheStats(t *testing.T) {
- tempDir := t.TempDir()
-
- provider := &OpenAIProvider{
- enableCache: true,
- cacheDir: filepath.Join(tempDir, "cache"),
- }
-
- // Create the cache directory first
- os.MkdirAll(provider.cacheDir, 0755)
-
- // Test with no cache files
- count, size, err := provider.GetCacheStats()
- if err != nil {
- t.Errorf("GetCacheStats() error = %v", err)
- }
- if count != 0 || size != 0 {
- t.Errorf("Expected empty cache stats, got count=%d, size=%d", count, size)
- }
- // Create cache files
- os.MkdirAll(filepath.Join(provider.cacheDir, "ab"), 0755)
- data1 := []byte("test data 1")
- data2 := []byte("test data 22")
- os.WriteFile(filepath.Join(provider.cacheDir, "ab", "test1.mp3"), data1, 0644)
- os.WriteFile(filepath.Join(provider.cacheDir, "ab", "test2.mp3"), data2, 0644)
-
- // Get stats
- count, size, err = provider.GetCacheStats()
- if err != nil {
- t.Errorf("GetCacheStats() error = %v", err)
- }
- if count != 2 {
- t.Errorf("Expected 2 files, got %d", count)
- }
- expectedSize := int64(len(data1) + len(data2))
- if size != expectedSize {
- t.Errorf("Expected size %d, got %d", expectedSize, size)
- }
-
- // Test with cache disabled
- provider.enableCache = false
- count, size, err = provider.GetCacheStats()
- if err != nil {
- t.Errorf("GetCacheStats() with cache disabled error = %v", err)
- }
- if count != 0 || size != 0 {
- t.Errorf("Expected zero stats with cache disabled, got count=%d, size=%d", count, size)
- }
-}
-
func TestGenerateAudioValidation(t *testing.T) {
provider := &OpenAIProvider{
config: &Config{
diff --git a/internal/audio/provider.go b/internal/audio/provider.go
index 0142fb3..06894bf 100644
--- a/internal/audio/provider.go
+++ b/internal/audio/provider.go
@@ -30,9 +30,6 @@ type Config struct {
OpenAISpeed float64 // 0.25 to 4.0
OpenAIInstruction string // Voice instructions for gpt-4o-mini-tts model
- // Caching settings
- EnableCache bool
- CacheDir string
}
// DefaultConfig returns default configuration
@@ -46,8 +43,6 @@ func DefaultProviderConfig() *Config {
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.",
- EnableCache: true,
- CacheDir: "./.audio_cache",
}
}
diff --git a/internal/audio/provider_test.go b/internal/audio/provider_test.go
index 7fda932..97d3e9c 100644
--- a/internal/audio/provider_test.go
+++ b/internal/audio/provider_test.go
@@ -50,13 +50,6 @@ func TestDefaultProviderConfig(t *testing.T) {
t.Errorf("Expected OpenAI speed 1.0, got %f", config.OpenAISpeed)
}
- if !config.EnableCache {
- t.Error("Expected cache to be enabled by default")
- }
-
- if config.CacheDir != "./.audio_cache" {
- t.Errorf("Expected cache dir './.audio_cache', got '%s'", config.CacheDir)
- }
}
func TestNewProvider(t *testing.T) {
diff --git a/internal/gui/app.go b/internal/gui/app.go
index cd4b711..6a58286 100644
--- a/internal/gui/app.go
+++ b/internal/gui/app.go
@@ -170,8 +170,6 @@ func New(config *Config) *Application {
OpenAIVoice: "nova",
OpenAISpeed: 0.9,
OpenAIInstruction: "You are speaking Bulgarian language (Π±ΡŠΠ»Π³Π°Ρ€ΡΠΊΠΈ Π΅Π·ΠΈΠΊ). Pronounce the Bulgarian text with authentic Bulgarian phonetics, not Russian. Speak slowly and clearly for language learners.",
- EnableCache: true,
- CacheDir: "./.audio_cache",
}
app.setupUI()
diff --git a/internal/processor/processor.go b/internal/processor/processor.go
index 43e75ca..1e1c20f 100644
--- a/internal/processor/processor.go
+++ b/internal/processor/processor.go
@@ -263,15 +263,6 @@ func (p *Processor) generateAudioWithVoice(word, voice string) error {
OpenAIVoice: voice,
OpenAISpeed: speed,
OpenAIInstruction: p.flags.OpenAIInstruction,
-
- // Caching
- EnableCache: viper.GetBool("audio.enable_cache"),
- CacheDir: viper.GetString("audio.cache_dir"),
- }
-
- // Set defaults
- if providerConfig.CacheDir == "" {
- providerConfig.CacheDir = "./.audio_cache"
}
// Use config file values if not overridden by flags