Spaces:
Building
Building
Update flare-ui/src/app/services/conversation-manager.service.ts
Browse files
flare-ui/src/app/services/conversation-manager.service.ts
CHANGED
@@ -444,75 +444,82 @@ export class ConversationManagerService implements OnDestroy {
|
|
444 |
}
|
445 |
|
446 |
private handleTTSAudio(message: any): void {
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
// Detailed log
|
455 |
-
console.log('π΅ TTS chunk received:', {
|
456 |
-
chunkIndex: message['chunk_index'],
|
457 |
-
totalChunks: message['total_chunks'],
|
458 |
-
dataLength: message['data'].length,
|
459 |
-
dataPreview: message['data'].substring(0, 50) + '...',
|
460 |
-
isLast: message['is_last'],
|
461 |
-
mimeType: message['mime_type']
|
462 |
-
});
|
463 |
-
|
464 |
-
// Accumulate audio chunks (already base64)
|
465 |
-
this.audioQueue.push(message['data']);
|
466 |
-
console.log(`π¦ Audio queue size: ${this.audioQueue.length} chunks`);
|
467 |
-
|
468 |
-
if (message['is_last']) {
|
469 |
-
console.log('π§ Processing final audio chunk...');
|
470 |
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
const audioBlob = this.base64ToBlob(combinedBase64, message['mime_type'] || 'audio/mpeg');
|
488 |
-
const audioUrl = URL.createObjectURL(audioBlob);
|
489 |
-
console.log('π§ Audio URL created:', audioUrl);
|
490 |
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
499 |
}
|
500 |
-
|
501 |
-
// Clear queue
|
502 |
-
this.audioQueue = [];
|
503 |
-
console.log('π§Ή Audio queue cleared');
|
504 |
-
|
505 |
-
console.log('β
Audio processing completed successfully');
|
506 |
-
} catch (error) {
|
507 |
-
console.error('β Error creating audio blob:', error);
|
508 |
-
console.error('Queue size was:', this.audioQueue.length);
|
509 |
-
this.audioQueue = [];
|
510 |
}
|
|
|
|
|
|
|
511 |
}
|
512 |
-
} catch (error) {
|
513 |
-
console.error('β Error handling TTS audio:', error);
|
514 |
-
this.audioQueue = []; // Clear queue on error
|
515 |
-
}
|
516 |
}
|
517 |
|
518 |
private isValidBase64(str: string): boolean {
|
|
|
444 |
}
|
445 |
|
446 |
private handleTTSAudio(message: any): void {
|
447 |
+
try {
|
448 |
+
// Validate audio data
|
449 |
+
if (!message['data']) {
|
450 |
+
console.warn('β TTS audio message missing data');
|
451 |
+
return;
|
452 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
453 |
|
454 |
+
// Detailed log
|
455 |
+
console.log('π΅ TTS chunk received:', {
|
456 |
+
chunkIndex: message['chunk_index'],
|
457 |
+
totalChunks: message['total_chunks'],
|
458 |
+
dataLength: message['data'].length,
|
459 |
+
dataPreview: message['data'].substring(0, 50) + '...',
|
460 |
+
isLast: message['is_last'],
|
461 |
+
mimeType: message['mime_type']
|
462 |
+
});
|
463 |
+
|
464 |
+
// Accumulate audio chunks (already base64)
|
465 |
+
this.audioQueue.push(message['data']);
|
466 |
+
console.log(`π¦ Audio queue size: ${this.audioQueue.length} chunks`);
|
467 |
+
|
468 |
+
if (message['is_last']) {
|
469 |
+
console.log('π§ Processing final audio chunk...');
|
|
|
|
|
|
|
470 |
|
471 |
+
try {
|
472 |
+
// All chunks received, combine and create audio blob
|
473 |
+
const combinedBase64 = this.audioQueue.join('');
|
474 |
+
console.log('β
Combined audio data:', {
|
475 |
+
totalLength: combinedBase64.length,
|
476 |
+
queueSize: this.audioQueue.length,
|
477 |
+
preview: combinedBase64.substring(0, 100) + '...'
|
478 |
+
});
|
479 |
+
|
480 |
+
// Validate base64
|
481 |
+
console.log('π Validating base64...');
|
482 |
+
if (!this.isValidBase64(combinedBase64)) {
|
483 |
+
throw new Error('Invalid base64 data received');
|
484 |
+
}
|
485 |
+
console.log('β
Base64 validation passed');
|
486 |
+
|
487 |
+
const audioBlob = this.base64ToBlob(combinedBase64, message['mime_type'] || 'audio/mpeg');
|
488 |
+
const audioUrl = URL.createObjectURL(audioBlob);
|
489 |
+
console.log('π§ Audio URL created:', audioUrl);
|
490 |
+
|
491 |
+
// Update last message with audio URL
|
492 |
+
const messages = this.messagesSubject.value;
|
493 |
+
if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
|
494 |
+
messages[messages.length - 1].audioUrl = audioUrl;
|
495 |
+
this.messagesSubject.next([...messages]);
|
496 |
+
console.log('β
Audio URL attached to assistant message');
|
497 |
+
|
498 |
+
// Auto-play welcome message
|
499 |
+
if (messages.length === 1) {
|
500 |
+
setTimeout(() => {
|
501 |
+
this.playAudio(audioUrl);
|
502 |
+
}, 500);
|
503 |
+
}
|
504 |
+
} else {
|
505 |
+
console.warn('β οΈ No assistant message found to attach audio');
|
506 |
+
}
|
507 |
+
|
508 |
+
// Clear queue
|
509 |
+
this.audioQueue = [];
|
510 |
+
console.log('π§Ή Audio queue cleared');
|
511 |
+
|
512 |
+
console.log('β
Audio processing completed successfully');
|
513 |
+
} catch (error) {
|
514 |
+
console.error('β Error creating audio blob:', error);
|
515 |
+
console.error('Queue size was:', this.audioQueue.length);
|
516 |
+
this.audioQueue = [];
|
517 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
}
|
519 |
+
} catch (error) {
|
520 |
+
console.error('β Error handling TTS audio:', error);
|
521 |
+
this.audioQueue = []; // Clear queue on error
|
522 |
}
|
|
|
|
|
|
|
|
|
523 |
}
|
524 |
|
525 |
private isValidBase64(str: string): boolean {
|