brestok's picture
Update static/js/voice.js
64fd065 verified
const initialMessage = ''
const loadingModal = document.getElementById('loadingModal');
const messageHistory = document.getElementById('chatHistory')
let mediaRecorder;
let audioChunks = [];
let socket
function makeLoading() {
loadingModal.style.visibility = 'visible';
}
function stopLoading() {
loadingModal.style.visibility = 'hidden';
}
function startCall() {
const uuid = generateUUID()
messageHistory.innerHTML = ``
socket = new WebSocket(`wss://brestok-poke-bowl-ai.hf.space/ws/${uuid}`);
socket.onopen = () => {
startRecording()
};
socket.onclose = (event) => console.log('WebSocket disconnected', event);
socket.onerror = (error) => {
alert('Something was wrong. Try again later.')
window.location.reload()
};
socket.onmessage = (event) => playResponse(event.data);
}
const startRecording = () => {
showMessage('You can speak!')
navigator.mediaDevices.getUserMedia({audio: true})
.then(stream => {
mediaRecorder = new MediaRecorder(stream);
try {
mediaRecorder.ondataavailable = (event) => {
audioChunks.push(event.data)
};
} catch (e) {
alert('It is not possible to send an empty message')
}
mediaRecorder.start();
})
.catch(error => {
console.error('Error accessing the microphone', error);
});
};
const stopAndSend = () => {
makeLoading()
mediaRecorder.ondataavailable = (event) => {
audioChunks.push(event.data)
console.log(audioChunks)
const audioBlob = new Blob(audioChunks, {type: 'audio/wav'});
const reader = new FileReader();
reader.readAsDataURL(audioBlob);
reader.onloadend = () => {
let base64String = reader.result;
base64String = base64String.split(',')[1];
const dataWS = {
'audio': base64String,
}
console.log(dataWS)
socket.send(JSON.stringify(dataWS));
audioChunks = [];
}
}
try {
mediaRecorder.stop();
} catch (e) {
return
}
}
const playResponse = (data, initMessage = false) => {
data = JSON.parse(data)
if (!initMessage) {
const aiResponse = data['ai_response']
if (aiResponse.startsWith('https://blue-estate-agency.com/') || aiResponse.startsWith('http://blue-estate-agency.com/')) {
window.open(aiResponse, '_blank');
}
}
const audioSrc = `data:audio/mp3;base64,${data['voice_response']}`;
const audio = new Audio(audioSrc);
stopLoading()
if (!initMessage) {
createMessage('User', data['user_query'])
}
audio.play();
audio.onended = () => {
startRecording()
if (!initMessage) {
createMessage('Assistant', data['ai_response'])
}
};
}
function endCall() {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
audioChunks = []
}
if (socket && socket.readyState === WebSocket.OPEN) {
socket.close();
}
showMessage('The call is ended')
}
function generateUUID() {
const arr = new Uint8Array(16);
window.crypto.getRandomValues(arr);
arr[6] = (arr[6] & 0x0f) | 0x40;
arr[8] = (arr[8] & 0x3f) | 0x80;
return ([...arr].map((b, i) =>
(i === 4 || i === 6 || i === 8 || i === 10 ? "-" : "") + b.toString(16).padStart(2, "0")
).join(""));
}
function showMessage(message_text) {
const message = document.getElementById('message');
message.innerText = message_text
message.style.display = 'block';
setTimeout(function () {
message.style.display = 'none';
}, 2000);
}
function createMessage(type, message) {
const newMessage = document.createElement('div')
newMessage.className = 'message rounded-4 bg-white mb-4 mx-4 py-2 px-3 border'
newMessage.innerHTML = `
<h5>${type}</h5>
${message}
`
messageHistory.appendChild(newMessage)
}