mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 18:15:34 +00:00
- Add per-tenant TTS configuration endpoints (GET/POST /v1/tts/config) with RoleAdmin auth instead of master scope - Implement TenantTTSResolver for channels to use tenant-specific TTS providers and auto mode settings - Add per-agent voice override in channel TTS auto-apply: - Extend OutboundMessage with AgentID and AgentOtherConfig - Inject AgentAudioSnapshot in dispatch.go from outbound message - MaybeApply reads tts_voice_id/tts_model_id from agent context - Fix events.go to use RunContext.TenantID directly (H3) - Fix dispatch.go error notification to use sendCtx (H1) - Update UI to use new /v1/tts/config endpoints
63 lines
1.9 KiB
Go
63 lines
1.9 KiB
Go
package audio
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
// AutoApplyResult holds the result of TTS auto-apply processing.
|
|
type AutoApplyResult struct {
|
|
// Text is the message content with [[tts]] directives stripped.
|
|
Text string
|
|
// AudioPath is the path to generated audio file (empty if no TTS applied).
|
|
AudioPath string
|
|
// AudioMime is the MIME type of generated audio (e.g. "audio/ogg").
|
|
AudioMime string
|
|
}
|
|
|
|
// AutoApplyToText checks if TTS should be auto-applied to the message content.
|
|
// Returns modified text (directives stripped) and audio path if TTS was applied.
|
|
// channel: "telegram", "discord", etc. - used for format selection (opus for telegram).
|
|
// isVoiceInbound: true if user sent voice message (for "inbound" auto mode).
|
|
// workspace: directory to save generated audio files.
|
|
func (m *Manager) AutoApplyToText(
|
|
ctx context.Context,
|
|
content string,
|
|
channel string,
|
|
isVoiceInbound bool,
|
|
workspace string,
|
|
) (*AutoApplyResult, error) {
|
|
if m == nil || content == "" {
|
|
return &AutoApplyResult{Text: content}, nil
|
|
}
|
|
|
|
// Check if TTS should be applied (respects auto mode: off/always/inbound/tagged)
|
|
result, ok := m.MaybeApply(ctx, content, channel, isVoiceInbound, "final")
|
|
if !ok || result == nil {
|
|
return &AutoApplyResult{Text: StripTTSDirectives(content)}, nil
|
|
}
|
|
|
|
// Write audio to workspace/tts/ directory
|
|
ttsDir := workspace
|
|
if ttsDir == "" {
|
|
ttsDir = os.TempDir()
|
|
}
|
|
ttsDir = filepath.Join(ttsDir, "tts")
|
|
if err := os.MkdirAll(ttsDir, 0755); err != nil {
|
|
return &AutoApplyResult{Text: StripTTSDirectives(content)}, err
|
|
}
|
|
|
|
audioPath := filepath.Join(ttsDir, "auto-"+time.Now().Format("20060102-150405")+"."+result.Extension)
|
|
if err := os.WriteFile(audioPath, result.Audio, 0644); err != nil {
|
|
return &AutoApplyResult{Text: StripTTSDirectives(content)}, err
|
|
}
|
|
|
|
return &AutoApplyResult{
|
|
Text: StripTTSDirectives(content),
|
|
AudioPath: audioPath,
|
|
AudioMime: result.MimeType,
|
|
}, nil
|
|
}
|