package audio import ( "fmt" "path/filepath" "strings" "time" ) // AttributionParams describes metadata included in generated audio attribution files. type AttributionParams struct { Word string Model string Voice string Instruction string ProcessedText string Speed float64 GeneratedAt time.Time } // AttributionParamsFrom builds an AttributionParams from a flat Config and the // word being transcribed, reading provider-appropriate sub-config fields to // eliminate the need for callers to switch on config.Provider themselves. func AttributionParamsFrom(config *Config, word, instruction, processedText string, generatedAt time.Time) AttributionParams { base := AttributionParams{ Word: word, Instruction: instruction, ProcessedText: processedText, GeneratedAt: generatedAt, } if config == nil { return base } switch strings.ToLower(strings.TrimSpace(config.Provider)) { case "gemini": g := geminiAudioConfigFrom(config) base.Model = g.TTSModel base.Voice = g.Voice base.Speed = g.Speed default: o := openAIAudioConfigFrom(config) base.Model = o.Model base.Voice = o.Voice base.Speed = o.Speed } return base } // 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 { return buildAttribution("Audio generated by OpenAI TTS", params) } // BuildGeminiAttribution builds the attribution content for Gemini-generated audio. func BuildGeminiAttribution(params AttributionParams) string { return buildAttribution("Audio generated by Google Gemini TTS", params) } func buildAttribution(header string, params AttributionParams) string { var b strings.Builder b.WriteString(header) b.WriteString("\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() }