summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-08 08:44:11 +0200
committerPaul Buetow <paul@buetow.org>2026-03-08 08:44:11 +0200
commit6e2635afc69579fdc895d6b7890538ca98dabaae (patch)
tree5db5aa603ab5ac3b372c2ac8512c84627fb063e1
parentaa733f9a86b02d7b4d6edd8022a44e4ba417b24c (diff)
refactor(task-376): share audio attribution builder
-rw-r--r--internal/audio/attribution.go49
-rw-r--r--internal/gui/generator.go21
-rw-r--r--internal/processor/processor.go25
3 files changed, 68 insertions, 27 deletions
diff --git a/internal/audio/attribution.go b/internal/audio/attribution.go
new file mode 100644
index 0000000..80f2bc3
--- /dev/null
+++ b/internal/audio/attribution.go
@@ -0,0 +1,49 @@
+package audio
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+// AttributionParams describes metadata included in OpenAI TTS attribution files.
+type AttributionParams struct {
+ Word string
+ Model string
+ Voice string
+ Instruction string
+ ProcessedText string
+ Speed float64
+ GeneratedAt time.Time
+}
+
+// AttributionPath returns the sidecar attribution file path for a generated audio file.
+func AttributionPath(audioFile string) string {
+ return strings.TrimSuffix(audioFile, filepath.Ext(audioFile)) + "_attribution.txt"
+}
+
+// BuildOpenAIAttribution builds the attribution content for OpenAI-generated audio.
+func BuildOpenAIAttribution(params AttributionParams) string {
+ var b strings.Builder
+ b.WriteString("Audio generated by OpenAI TTS\n\n")
+ fmt.Fprintf(&b, "Bulgarian word: %s\n", params.Word)
+ fmt.Fprintf(&b, "Model: %s\n", params.Model)
+ fmt.Fprintf(&b, "Voice: %s\n", params.Voice)
+ fmt.Fprintf(&b, "Speed: %.2f\n", params.Speed)
+
+ if params.Instruction != "" {
+ fmt.Fprintf(&b, "\nVoice instructions:\n%s\n", params.Instruction)
+ }
+ if params.ProcessedText != "" {
+ fmt.Fprintf(&b, "\nProcessed text sent to TTS: %s\n", params.ProcessedText)
+ }
+
+ generatedAt := params.GeneratedAt
+ if generatedAt.IsZero() {
+ generatedAt = time.Now()
+ }
+ fmt.Fprintf(&b, "\nGenerated at: %s\n", generatedAt.Format("2006-01-02 15:04:05"))
+
+ return b.String()
+}
diff --git a/internal/gui/generator.go b/internal/gui/generator.go
index 14f0f60..09ff534 100644
--- a/internal/gui/generator.go
+++ b/internal/gui/generator.go
@@ -367,20 +367,17 @@ func (a *Application) generateImagesWithPrompt(ctx context.Context, word string,
// saveAudioAttribution saves attribution info for generated audio
func (a *Application) saveAudioAttribution(word, audioFile, voice string, speed float64) error {
- attribution := fmt.Sprintf("Audio generated by OpenAI TTS\n\n")
- attribution += fmt.Sprintf("Bulgarian word: %s\n", word)
- attribution += fmt.Sprintf("Model: %s\n", a.audioConfig.OpenAIModel)
- attribution += fmt.Sprintf("Voice: %s\n", voice)
- attribution += fmt.Sprintf("Speed: %.2f\n", speed)
-
- if a.audioConfig.OpenAIInstruction != "" {
- attribution += fmt.Sprintf("\nVoice instructions:\n%s\n", a.audioConfig.OpenAIInstruction)
- }
-
- attribution += fmt.Sprintf("\nGenerated at: %s\n", time.Now().Format("2006-01-02 15:04:05"))
+ attribution := audio.BuildOpenAIAttribution(audio.AttributionParams{
+ Word: word,
+ Model: a.audioConfig.OpenAIModel,
+ Voice: voice,
+ Speed: speed,
+ Instruction: a.audioConfig.OpenAIInstruction,
+ GeneratedAt: time.Now(),
+ })
// Save to file
- attrPath := strings.TrimSuffix(audioFile, filepath.Ext(audioFile)) + "_attribution.txt"
+ attrPath := audio.AttributionPath(audioFile)
if err := os.WriteFile(attrPath, []byte(attribution), 0644); err != nil {
return fmt.Errorf("failed to write audio attribution file: %w", err)
}
diff --git a/internal/processor/processor.go b/internal/processor/processor.go
index 3b49cf0..d52ca53 100644
--- a/internal/processor/processor.go
+++ b/internal/processor/processor.go
@@ -728,17 +728,6 @@ func (p *Processor) isWordFullyProcessed(word string) bool {
return true // All required files exist
}
func (p *Processor) saveAudioAttribution(word, audioFile string, config *audio.Config) error {
- // Create attribution text
- attribution := fmt.Sprintf("Audio generated by OpenAI TTS\n\n")
- attribution += fmt.Sprintf("Bulgarian word: %s\n", word)
- attribution += fmt.Sprintf("Model: %s\n", config.OpenAIModel)
- attribution += fmt.Sprintf("Voice: %s\n", config.OpenAIVoice)
- attribution += fmt.Sprintf("Speed: %.2f\n", config.OpenAISpeed)
-
- if config.OpenAIInstruction != "" {
- attribution += fmt.Sprintf("\nVoice instructions:\n%s\n", config.OpenAIInstruction)
- }
-
// Add preprocessing information
cleanedWord := strings.TrimSpace(word)
punctuationToRemove := []string{"!", "?", ".", ",", ";", ":", "\"", "'", "(", ")", "[", "]", "{", "}", "-", "—", "–"}
@@ -746,12 +735,18 @@ func (p *Processor) saveAudioAttribution(word, audioFile string, config *audio.C
cleanedWord = strings.ReplaceAll(cleanedWord, punct, "")
}
processedText := fmt.Sprintf("%s...", strings.TrimSpace(cleanedWord))
- attribution += fmt.Sprintf("\nProcessed text sent to TTS: %s\n", processedText)
-
- attribution += fmt.Sprintf("\nGenerated at: %s\n", time.Now().Format("2006-01-02 15:04:05"))
+ attribution := audio.BuildOpenAIAttribution(audio.AttributionParams{
+ Word: word,
+ Model: config.OpenAIModel,
+ Voice: config.OpenAIVoice,
+ Speed: config.OpenAISpeed,
+ Instruction: config.OpenAIInstruction,
+ ProcessedText: processedText,
+ GeneratedAt: time.Now(),
+ })
// Save to file
- attrPath := strings.TrimSuffix(audioFile, filepath.Ext(audioFile)) + "_attribution.txt"
+ attrPath := audio.AttributionPath(audioFile)
if err := os.WriteFile(attrPath, []byte(attribution), 0644); err != nil {
return fmt.Errorf("failed to write audio attribution file: %w", err)
}