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
@@ -452,47 +452,36 @@ export class ConversationManagerService implements OnDestroy {
|
|
452 |
mimeType: message['mime_type']
|
453 |
});
|
454 |
|
455 |
-
//
|
456 |
-
|
457 |
-
// Accumulate audio chunks
|
458 |
-
this.audioQueue.push(message['data']);
|
459 |
-
return;
|
460 |
-
}
|
461 |
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
// Auto-play if in playing_audio state
|
490 |
-
if (this.currentStateSubject.value === 'playing_audio') {
|
491 |
-
this.playQueuedAudio();
|
492 |
}
|
493 |
-
} catch (error) {
|
494 |
-
console.error('Error creating audio blob:', error);
|
495 |
-
this.audioQueue = []; // Clear queue on error
|
496 |
}
|
497 |
} catch (error) {
|
498 |
console.error('Error handling TTS audio:', error);
|
@@ -502,26 +491,10 @@ export class ConversationManagerService implements OnDestroy {
|
|
502 |
|
503 |
private base64ToBlob(base64: string, mimeType: string): Blob {
|
504 |
try {
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
// Validate base64 string
|
509 |
-
if (!cleanBase64 || cleanBase64.length === 0) {
|
510 |
-
throw new Error('Empty base64 string');
|
511 |
-
}
|
512 |
-
|
513 |
-
// Check if string contains MP3 header (ID3 tag)
|
514 |
-
if (cleanBase64.startsWith('SUQz')) {
|
515 |
-
// This is raw MP3 data, not base64 - likely a backend issue
|
516 |
-
console.log('Detected raw MP3 data instead of base64');
|
517 |
-
}
|
518 |
-
|
519 |
-
// Pad base64 string if necessary
|
520 |
-
const padding = cleanBase64.length % 4;
|
521 |
-
const paddedBase64 = padding ? cleanBase64 + '='.repeat(4 - padding) : cleanBase64;
|
522 |
|
523 |
-
|
524 |
-
const byteCharacters = atob(paddedBase64);
|
525 |
const byteNumbers = new Array(byteCharacters.length);
|
526 |
|
527 |
for (let i = 0; i < byteCharacters.length; i++) {
|
@@ -529,11 +502,18 @@ export class ConversationManagerService implements OnDestroy {
|
|
529 |
}
|
530 |
|
531 |
const byteArray = new Uint8Array(byteNumbers);
|
532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
533 |
} catch (error) {
|
534 |
console.error('Error converting base64 to blob:', error);
|
535 |
-
console.
|
536 |
-
console.
|
537 |
throw new Error('Failed to convert audio data');
|
538 |
}
|
539 |
}
|
|
|
452 |
mimeType: message['mime_type']
|
453 |
});
|
454 |
|
455 |
+
// Accumulate audio chunks (already base64)
|
456 |
+
this.audioQueue.push(message['data']);
|
|
|
|
|
|
|
|
|
457 |
|
458 |
+
if (message['is_last']) {
|
459 |
+
try {
|
460 |
+
// All chunks received, combine and create audio blob
|
461 |
+
const combinedBase64 = this.audioQueue.join('');
|
462 |
+
console.log('Combined audio data:', {
|
463 |
+
totalLength: combinedBase64.length,
|
464 |
+
preview: combinedBase64.substring(0, 100)
|
465 |
+
});
|
466 |
+
|
467 |
+
const audioBlob = this.base64ToBlob(combinedBase64, message['mime_type'] || 'audio/mpeg');
|
468 |
+
const audioUrl = URL.createObjectURL(audioBlob);
|
469 |
+
|
470 |
+
// Update last message with audio URL
|
471 |
+
const messages = this.messagesSubject.value;
|
472 |
+
if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
|
473 |
+
messages[messages.length - 1].audioUrl = audioUrl;
|
474 |
+
this.messagesSubject.next([...messages]);
|
475 |
+
}
|
476 |
+
|
477 |
+
// Clear queue
|
478 |
+
this.audioQueue = [];
|
479 |
+
|
480 |
+
console.log('✅ Audio blob created successfully');
|
481 |
+
} catch (error) {
|
482 |
+
console.error('Error creating audio blob:', error);
|
483 |
+
this.audioQueue = [];
|
|
|
|
|
|
|
|
|
484 |
}
|
|
|
|
|
|
|
485 |
}
|
486 |
} catch (error) {
|
487 |
console.error('Error handling TTS audio:', error);
|
|
|
491 |
|
492 |
private base64ToBlob(base64: string, mimeType: string): Blob {
|
493 |
try {
|
494 |
+
console.log('Base64 length:', base64.length);
|
495 |
+
console.log('Base64 preview:', base64.substring(0, 100));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
|
497 |
+
const byteCharacters = atob(base64);
|
|
|
498 |
const byteNumbers = new Array(byteCharacters.length);
|
499 |
|
500 |
for (let i = 0; i < byteCharacters.length; i++) {
|
|
|
502 |
}
|
503 |
|
504 |
const byteArray = new Uint8Array(byteNumbers);
|
505 |
+
const blob = new Blob([byteArray], { type: mimeType });
|
506 |
+
|
507 |
+
console.log('Blob created:', {
|
508 |
+
size: blob.size,
|
509 |
+
type: blob.type
|
510 |
+
});
|
511 |
+
|
512 |
+
return blob;
|
513 |
} catch (error) {
|
514 |
console.error('Error converting base64 to blob:', error);
|
515 |
+
console.log('Base64 length:', base64.length);
|
516 |
+
console.log('Base64 preview:', base64.substring(0, 100));
|
517 |
throw new Error('Failed to convert audio data');
|
518 |
}
|
519 |
}
|