-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathaudio_controller.js
89 lines (73 loc) · 3.04 KB
/
audio_controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { Controller } from '@hotwired/stimulus';
import { getComponent } from '@symfony/ux-live-component';
export default class extends Controller {
async initialize() {
this.component = await getComponent(this.element);
this.scrollToBottom();
const resetButton = document.getElementById('chat-reset');
resetButton.addEventListener('click', (event) => {
this.component.action('reset');
});
const startButton = document.getElementById('micro-start');
const stopButton = document.getElementById('micro-stop');
const botThinkingButton = document.getElementById('bot-thinking');
startButton.addEventListener('click', (event) => {
event.preventDefault();
startButton.classList.add('d-none');
stopButton.classList.remove('d-none');
this.startRecording();
});
stopButton.addEventListener('click', (event) => {
event.preventDefault();
stopButton.classList.add('d-none');
botThinkingButton.classList.remove('d-none');
this.mediaRecorder.stop();
});
this.component.on('loading.state:started', (e,r) => {
if (r.actions.includes('reset')) {
return;
}
document.getElementById('welcome')?.remove();
document.getElementById('loading-message').removeAttribute('class');
this.scrollToBottom();
});
this.component.on('loading.state:finished', () => {
document.getElementById('loading-message').setAttribute('class', 'd-none');
botThinkingButton.classList.add('d-none');
startButton.classList.remove('d-none');
});
this.component.on('render:finished', () => {
this.scrollToBottom();
});
};
async startRecording() {
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
this.mediaRecorder = new MediaRecorder(stream);
let audioChunks = [];
this.mediaRecorder.ondataavailable = (event) => {
audioChunks.push(event.data);
};
this.mediaRecorder.onstop = async () => {
const audioBlob = new Blob(audioChunks, {type: 'audio/wav'});
const base64String = await this.blobToBase64(audioBlob);
this.component.action('submit', { audio: base64String });
};
this.mediaRecorder.start();
}
scrollToBottom() {
const chatBody = document.getElementById('chat-body');
chatBody.scrollTop = chatBody.scrollHeight;
}
blobToBase64(blob) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => resolve(reader.result.split(',')[1]);
});
}
playBase64Audio(base64String) {
const audioSrc = "data:audio/wav;base64," + base64String;
const audio = new Audio(audioSrc);
audio.play().catch(error => console.error("Playback error:", error));
}
}