250 lines
7.7 KiB
Go
250 lines
7.7 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/charmbracelet/huh"
|
|
"github.com/leonardotrapani/hyprvoice/internal/config"
|
|
"github.com/leonardotrapani/hyprvoice/internal/provider"
|
|
)
|
|
|
|
// editTranscription handles the transcription section edit with smart provider detection
|
|
func editTranscription(cfg *config.Config, configuredProviders []string) ([]string, error) {
|
|
var transcriptionOptions []huh.Option[string]
|
|
for _, name := range configuredProviders {
|
|
p := provider.GetProvider(name)
|
|
if p != nil && p.SupportsTranscription() {
|
|
switch name {
|
|
case "openai":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("OpenAI Whisper", "openai"))
|
|
case "groq":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("Groq Whisper (transcription)", "groq-transcription"),
|
|
huh.NewOption("Groq Whisper (translate to English)", "groq-translation"))
|
|
case "mistral":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("Mistral Voxtral", "mistral-transcription"))
|
|
case "elevenlabs":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("ElevenLabs Scribe", "elevenlabs"))
|
|
}
|
|
}
|
|
}
|
|
|
|
unconfiguredOptions := getUnconfiguredTranscriptionOptions(configuredProviders)
|
|
if len(unconfiguredOptions) > 0 {
|
|
transcriptionOptions = append(transcriptionOptions, unconfiguredOptions...)
|
|
}
|
|
|
|
if len(transcriptionOptions) == 0 {
|
|
return configuredProviders, fmt.Errorf("no transcription providers available")
|
|
}
|
|
|
|
selectedProvider := cfg.Transcription.Provider
|
|
if selectedProvider == "" && len(transcriptionOptions) > 0 {
|
|
selectedProvider = transcriptionOptions[0].Value
|
|
}
|
|
|
|
providerDesc := "Choose which service to use for speech-to-text"
|
|
if cfg.Transcription.Provider != "" {
|
|
providerDesc = fmt.Sprintf("Currently: %s/%s", cfg.Transcription.Provider, cfg.Transcription.Model)
|
|
}
|
|
|
|
providerForm := huh.NewForm(
|
|
huh.NewGroup(
|
|
huh.NewSelect[string]().
|
|
Title("Transcription Provider").
|
|
Description(providerDesc).
|
|
Options(transcriptionOptions...).
|
|
Value(&selectedProvider),
|
|
),
|
|
).WithTheme(getTheme())
|
|
|
|
if err := providerForm.Run(); err != nil {
|
|
return configuredProviders, err
|
|
}
|
|
|
|
configuredProviders = ensureProviderConfigured(cfg, selectedProvider, configuredProviders)
|
|
cfg.Transcription.Provider = selectedProvider
|
|
|
|
modelOptions := getTranscriptionModelOptions(selectedProvider)
|
|
selectedModel := cfg.Transcription.Model
|
|
if selectedModel == "" && len(modelOptions) > 0 {
|
|
selectedModel = modelOptions[0].Value
|
|
}
|
|
|
|
modelDesc := ""
|
|
if cfg.Transcription.Model != "" {
|
|
modelDesc = fmt.Sprintf("Currently: %s", cfg.Transcription.Model)
|
|
}
|
|
|
|
language := cfg.Transcription.Language
|
|
|
|
langDesc := "ISO-639-1 code (e.g., 'en', 'es', 'fr') or empty for auto-detect"
|
|
if cfg.Transcription.Language != "" {
|
|
langDesc = fmt.Sprintf("Currently: %s. %s", cfg.Transcription.Language, langDesc)
|
|
}
|
|
|
|
modelForm := huh.NewForm(
|
|
huh.NewGroup(
|
|
huh.NewSelect[string]().
|
|
Title("Transcription Model").
|
|
Description(modelDesc).
|
|
Options(modelOptions...).
|
|
Value(&selectedModel),
|
|
huh.NewInput().
|
|
Title("Language").
|
|
Description(langDesc).
|
|
Placeholder("auto-detect").
|
|
Value(&language),
|
|
),
|
|
).WithTheme(getTheme())
|
|
|
|
if err := modelForm.Run(); err != nil {
|
|
return configuredProviders, err
|
|
}
|
|
|
|
cfg.Transcription.Model = selectedModel
|
|
cfg.Transcription.Language = language
|
|
|
|
return configuredProviders, nil
|
|
}
|
|
|
|
// getUnconfiguredTranscriptionOptions returns options for providers not yet configured
|
|
func getUnconfiguredTranscriptionOptions(configuredProviders []string) []huh.Option[string] {
|
|
configured := make(map[string]bool)
|
|
for _, p := range configuredProviders {
|
|
configured[p] = true
|
|
}
|
|
|
|
var options []huh.Option[string]
|
|
if !configured["openai"] {
|
|
options = append(options, huh.NewOption("OpenAI Whisper (not configured)", "openai"))
|
|
}
|
|
if !configured["groq"] {
|
|
options = append(options,
|
|
huh.NewOption("Groq Whisper transcription (not configured)", "groq-transcription"),
|
|
huh.NewOption("Groq Whisper translation (not configured)", "groq-translation"))
|
|
}
|
|
if !configured["mistral"] {
|
|
options = append(options, huh.NewOption("Mistral Voxtral (not configured)", "mistral-transcription"))
|
|
}
|
|
if !configured["elevenlabs"] {
|
|
options = append(options, huh.NewOption("ElevenLabs Scribe (not configured)", "elevenlabs"))
|
|
}
|
|
return options
|
|
}
|
|
|
|
func getTranscriptionModelOptions(provider string) []huh.Option[string] {
|
|
switch provider {
|
|
case "openai":
|
|
return []huh.Option[string]{
|
|
huh.NewOption("whisper-1", "whisper-1"),
|
|
}
|
|
case "groq-transcription":
|
|
return []huh.Option[string]{
|
|
huh.NewOption("whisper-large-v3-turbo (faster)", "whisper-large-v3-turbo"),
|
|
huh.NewOption("whisper-large-v3 (standard)", "whisper-large-v3"),
|
|
}
|
|
case "groq-translation":
|
|
return []huh.Option[string]{
|
|
huh.NewOption("whisper-large-v3 (only option)", "whisper-large-v3"),
|
|
}
|
|
case "mistral-transcription":
|
|
return []huh.Option[string]{
|
|
huh.NewOption("voxtral-mini-latest (recommended)", "voxtral-mini-latest"),
|
|
huh.NewOption("voxtral-mini-2507", "voxtral-mini-2507"),
|
|
}
|
|
case "elevenlabs":
|
|
return []huh.Option[string]{
|
|
huh.NewOption("scribe_v1 (99 languages, best accuracy)", "scribe_v1"),
|
|
huh.NewOption("scribe_v2 (real-time, lower latency)", "scribe_v2"),
|
|
}
|
|
default:
|
|
return []huh.Option[string]{}
|
|
}
|
|
}
|
|
|
|
func configureTranscription(configuredProviders []string, cfg *config.Config) (string, string, string, error) {
|
|
var transcriptionOptions []huh.Option[string]
|
|
for _, name := range configuredProviders {
|
|
p := provider.GetProvider(name)
|
|
if p != nil && p.SupportsTranscription() {
|
|
switch name {
|
|
case "openai":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("OpenAI Whisper", "openai"))
|
|
case "groq":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("Groq Whisper (transcription)", "groq-transcription"),
|
|
huh.NewOption("Groq Whisper (translate to English)", "groq-translation"))
|
|
case "mistral":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("Mistral Voxtral", "mistral-transcription"))
|
|
case "elevenlabs":
|
|
transcriptionOptions = append(transcriptionOptions,
|
|
huh.NewOption("ElevenLabs Scribe", "elevenlabs"))
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(transcriptionOptions) == 0 {
|
|
return "", "", "", fmt.Errorf("no transcription-capable providers configured")
|
|
}
|
|
|
|
var selectedProvider string
|
|
if cfg.Transcription.Provider != "" {
|
|
selectedProvider = cfg.Transcription.Provider
|
|
} else if len(transcriptionOptions) > 0 {
|
|
selectedProvider = transcriptionOptions[0].Value
|
|
}
|
|
|
|
providerForm := huh.NewForm(
|
|
huh.NewGroup(
|
|
huh.NewSelect[string]().
|
|
Title("Transcription Provider").
|
|
Description("Choose which service to use for speech-to-text").
|
|
Options(transcriptionOptions...).
|
|
Value(&selectedProvider),
|
|
),
|
|
).WithTheme(getTheme())
|
|
|
|
if err := providerForm.Run(); err != nil {
|
|
return "", "", "", err
|
|
}
|
|
|
|
modelOptions := getTranscriptionModelOptions(selectedProvider)
|
|
var selectedModel string
|
|
if cfg.Transcription.Model != "" {
|
|
selectedModel = cfg.Transcription.Model
|
|
} else if len(modelOptions) > 0 {
|
|
selectedModel = modelOptions[0].Value
|
|
}
|
|
|
|
var language string
|
|
if cfg.Transcription.Language != "" {
|
|
language = cfg.Transcription.Language
|
|
}
|
|
|
|
modelForm := huh.NewForm(
|
|
huh.NewGroup(
|
|
huh.NewSelect[string]().
|
|
Title("Transcription Model").
|
|
Options(modelOptions...).
|
|
Value(&selectedModel),
|
|
huh.NewInput().
|
|
Title("Language").
|
|
Description("ISO-639-1 code (e.g., 'en', 'es', 'fr') or empty for auto-detect").
|
|
Placeholder("auto-detect").
|
|
Value(&language),
|
|
),
|
|
).WithTheme(getTheme())
|
|
|
|
if err := modelForm.Run(); err != nil {
|
|
return "", "", "", err
|
|
}
|
|
|
|
return selectedProvider, selectedModel, language, nil
|
|
}
|