diff --git a/mnemo_cards_admin/src/api/voiceService.ts b/mnemo_cards_admin/src/api/voiceService.ts index 64cbf17..6e68373 100644 --- a/mnemo_cards_admin/src/api/voiceService.ts +++ b/mnemo_cards_admin/src/api/voiceService.ts @@ -11,17 +11,20 @@ export const voiceServiceApi = { * Backend calls voice-service, which handles caching, and saves to MinIO * @param text Text to convert to speech * @param voice Voice identifier (optional, defaults to 'alloy') + * @param language Language code (optional) * @returns Object ID and presigned URL */ async generateTTS( text: string, - voice?: string + voice?: string, + language?: string ): Promise { const response = await adminApiClient.post( '/api/v2/media/generate-tts', { text, voice: voice || 'alloy', + ...(language && { language }), } ) diff --git a/mnemo_cards_admin/src/components/CardVoicesManager.tsx b/mnemo_cards_admin/src/components/CardVoicesManager.tsx index 98a7a09..08c4997 100644 --- a/mnemo_cards_admin/src/components/CardVoicesManager.tsx +++ b/mnemo_cards_admin/src/components/CardVoicesManager.tsx @@ -24,7 +24,7 @@ export function CardVoicesManager({ const queryClient = useQueryClient() const [showAddForm, setShowAddForm] = useState(false) const [newAudio, setNewAudio] = useState(undefined) - const [newLanguage, setNewLanguage] = useState('en') + const [newLanguage, setNewLanguage] = useState('es') const [isGeneratingTTS, setIsGeneratingTTS] = useState(false) // Load voices for the card @@ -65,7 +65,7 @@ export function CardVoicesManager({ // Auto-close form and reset after successful addition setShowAddForm(false) setNewAudio(undefined) - setNewLanguage('en') + setNewLanguage('es') }, onError: (error: unknown) => { console.error('❌ CardVoicesManager: addVoiceMutation.onError', error) @@ -111,14 +111,14 @@ export function CardVoicesManager({ try { const text = cardOriginal.trim() // Use default voice 'alloy' for TTS generation - // Language (newLanguage) is used only when saving the voice to the card + // Language (newLanguage) is used for both TTS generation and saving the voice to the card const voice = 'alloy' - console.log('🔄 CardVoicesManager: Requesting TTS generation', { text, voice }) + console.log('🔄 CardVoicesManager: Requesting TTS generation', { text, voice, language: newLanguage }) // Generate TTS via backend API // Backend calls voice-service (which handles caching) and saves to MinIO - const ttsResponse = await voiceServiceApi.generateTTS(text, voice) + const ttsResponse = await voiceServiceApi.generateTTS(text, voice, newLanguage) console.log('✅ CardVoicesManager: TTS generated and saved to MinIO', { objectId: ttsResponse.objectId }) @@ -126,7 +126,7 @@ export function CardVoicesManager({ // Add voice to card using the objectId from backend await addVoiceMutation.mutateAsync({ voiceUrl: ttsResponse.objectId, - language: newLanguage || 'en', + language: newLanguage || 'es', }) } catch (error) { console.error('❌ CardVoicesManager: TTS generation failed', error) @@ -224,7 +224,7 @@ export function CardVoicesManager({ onClick={() => { setShowAddForm(false) setNewAudio(undefined) - setNewLanguage('en') + setNewLanguage('es') }} disabled={disabled || addVoiceMutation.isPending} > diff --git a/mnemo_cards_backend/lib/api/v2/media_api_v2.dart b/mnemo_cards_backend/lib/api/v2/media_api_v2.dart index a1fe80d..8635d5b 100644 --- a/mnemo_cards_backend/lib/api/v2/media_api_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/media_api_v2.dart @@ -508,13 +508,14 @@ class MediaApiV2 { final json = jsonDecode(body) as Map; final text = json['text'] as String?; final voice = json['voice'] as String?; + final language = json['language'] as String?; if (text == null || text.trim().isEmpty) { return _badRequest('Text is required'); } print( - '🔄 MediaApiV2: Requesting TTS from voice-service: text="${text.substring(0, text.length > 50 ? 50 : text.length)}", voice="${voice ?? 'default'}"', + '🔄 MediaApiV2: Requesting TTS from voice-service: text="${text.substring(0, text.length > 50 ? 50 : text.length)}", voice="${voice ?? 'default'}", language="${language ?? 'not provided'}"', ); // Call voice-service @@ -524,6 +525,7 @@ class MediaApiV2 { 'text': text, if (voice != null) 'voice': voice, 'format': 'mp3', + if (language != null) 'language': language, }, options: dio.Options( responseType: dio.ResponseType.bytes,