Spaces:
Running
Running
window.HELP_IMPROVE_VIDEOJS = false; | |
// var INTERP_BASE = "./static/interpolation/stacked"; | |
var NUM_INTERP_FRAMES = 240; | |
var interp_images = []; | |
// function preloadInterpolationImages() { | |
// for (var i = 0; i < NUM_INTERP_FRAMES; i++) { | |
// var path = INTERP_BASE + '/' + String(i).padStart(6, '0') + '.jpg'; | |
// interp_images[i] = new Image(); | |
// interp_images[i].src = path; | |
// } | |
// } | |
// function setInterpolationImage(i) { | |
// var image = interp_images[i]; | |
// image.ondragstart = function() { return false; }; | |
// image.oncontextmenu = function() { return false; }; | |
// $('#interpolation-image-wrapper').empty().append(image); | |
// } | |
$(document).ready(function() { | |
// Check for click events on the navbar burger icon | |
$(".navbar-burger").click(function() { | |
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu" | |
$(".navbar-burger").toggleClass("is-active"); | |
$(".navbar-menu").toggleClass("is-active"); | |
}); | |
var options = { | |
slidesToScroll: 1, | |
slidesToShow: 3, | |
loop: true, | |
infinite: true, | |
autoplay: false, | |
autoplaySpeed: 3000, | |
} | |
// Initialize all div with carousel class | |
var carousels = bulmaCarousel.attach('.carousel', options); | |
// Loop on each carousel initialized | |
for(var i = 0; i < carousels.length; i++) { | |
// Add listener to event | |
carousels[i].on('before:show', state => { | |
console.log(state); | |
}); | |
} | |
// Access to bulmaCarousel instance of an element | |
var element = document.querySelector('#my-element'); | |
if (element && element.bulmaCarousel) { | |
// bulmaCarousel instance is available as element.bulmaCarousel | |
element.bulmaCarousel.on('before-show', function(state) { | |
console.log(state); | |
}); | |
} | |
/*var player = document.getElementById('interpolation-video'); | |
player.addEventListener('loadedmetadata', function() { | |
$('#interpolation-slider').on('input', function(event) { | |
console.log(this.value, player.duration); | |
player.currentTime = player.duration / 100 * this.value; | |
}) | |
}, false);*/ | |
// preloadInterpolationImages(); | |
// $('#interpolation-slider').on('input', function(event) { | |
// setInterpolationImage(this.value); | |
// }); | |
// setInterpolationImage(0); | |
// $('#interpolation-slider').prop('max', NUM_INTERP_FRAMES - 1); | |
bulmaSlider.attach(); | |
}) | |
// 全局初始化 | |
// connect ws | |
var ws = null; | |
var recorder = null; | |
var isRecording = false; | |
var vc_enabled = location.search.split('vc=')[1] == '1' ? true : false; | |
var text = '' | |
var audio_base64 = null; | |
Recorder.CLog = function(){} //update | |
var wave = Recorder.WaveView({elem:"#waveform"}); //创建wave对象,写这里面浏览器妥妥的; | |
const audioPlayer = document.getElementById('audioPlayer'); | |
const waveformDiv = document.getElementById('waveform'); | |
const resultsDiv = document.getElementById('results'); | |
const llasaLoading = document.getElementById('llasaLoading'); | |
const container = document.getElementById('llasa'); | |
// sent text element | |
function createSentMessageElement(message) { | |
const sentDiv = document.createElement('div'); | |
sentDiv.id = 'sent'; | |
sentDiv.setAttribute('class', 'd-flex flex-row justify-content-end mb-2 pt-1 text-start'); | |
const sentMessageP = document.createElement('p'); | |
sentMessageP.setAttribute('class', 'sent-message small p-2 me-2 mb-1 text-white rounded-3 bg-primary'); | |
sentMessageP.textContent = message['value']; | |
sentMessageP.id = message['cid'] | |
const imageDiv = document.createElement('div'); | |
const senderImage = document.createElement('img'); | |
senderImage.setAttribute('src', './images/user.png'); | |
senderImage.setAttribute('class', 'rounded-4'); | |
senderImage.setAttribute('alt', 'avatar 1'); | |
senderImage.setAttribute('height', '30'); | |
senderImage.setAttribute('width', '30'); | |
imageDiv.appendChild(senderImage); | |
sentDiv.appendChild(sentMessageP); | |
sentDiv.appendChild(imageDiv); | |
return sentDiv; | |
} | |
// Function to add a new sent message to the DOM | |
function addSentMessageToDOM(message) { | |
const sentDiv = createSentMessageElement(message); | |
resultsDiv.appendChild(sentDiv); | |
} | |
function createRecieveMessageElement(message) { | |
const responseDiv = document.createElement("div"); | |
responseDiv.id = "response"; | |
responseDiv.classList.add("d-flex", "flex-row", "justify-content-start", "pt-2", "mb-2"); | |
const imageDiv = document.createElement('div') | |
const avatarImg = document.createElement("img"); | |
avatarImg.src = "../../images/gpt.png"; | |
avatarImg.classList.add("rounded-4"); | |
avatarImg.alt = "avatar 1"; | |
avatarImg.height = 30; | |
avatarImg.width = 30; | |
imageDiv.appendChild(avatarImg) | |
responseDiv.appendChild(imageDiv); | |
const responseMessageP = document.createElement("p"); | |
responseMessageP.id = message['cid']; | |
responseMessageP.classList.add("small", "p-2", "ms-2", "mb-1", "rounded-3"); | |
responseMessageP.style.backgroundColor = "#f5f6f7"; | |
responseMessageP.innerText = message['value']; | |
responseDiv.appendChild(responseMessageP); | |
return responseDiv; | |
} | |
// Function to add a new recieve message to the DOM | |
function addRecieveMessageToDOM(message) { | |
const reciDiv = createRecieveMessageElement(message); | |
resultsDiv.appendChild(reciDiv); | |
resultsDiv.scrollTo(0, resultsDiv.scrollHeight); | |
} | |
function createSentAudioMessageElement(message) { | |
const sentDiv = document.createElement('div'); | |
sentDiv.id = 'sent'; | |
sentDiv.className = 'd-flex flex-row justify-content-end mb-2 pt-1 text-start'; | |
const audio = document.createElement('audio'); | |
audio.controls = true; | |
audio.id = message['cid']; | |
audio.className = 'sent-message p-2 me-2 bg-primagry'; | |
// audio.style.width = '200px'; | |
const sourceElement = document.createElement('source'); | |
sourceElement.src = message['value']; | |
// sourceElement.type = 'audio/ogg'; | |
const unsupportedText = document.createTextNode('Your browser does not support the audio element.'); | |
audio.appendChild(sourceElement); | |
audio.appendChild(unsupportedText); | |
const imageDiv = document.createElement('div') | |
const image = document.createElement('img'); | |
image.src = '../../images/user.png'; | |
image.id = 'sender-image'; | |
image.className = 'rounded-4'; | |
image.alt = 'avatar 1'; | |
image.height = 30; | |
image.width = 30; | |
imageDiv.appendChild(image); | |
sentDiv.appendChild(audio); | |
sentDiv.appendChild(imageDiv); | |
return sentDiv; | |
} | |
// Function to add a new audio sent message to the DOM | |
function addAudioSentMessageToDOM(message) { | |
const sentDiv = createSentAudioMessageElement(message); | |
resultsDiv.appendChild(sentDiv); | |
resultsDiv.scrollTo(0, resultsDiv.scrollHeight); | |
} | |
// stream update response | |
function updateResponse(cID, answer) { | |
const responseP = document.getElementById("a_text_" + cID); | |
responseP.innerText = answer; | |
} | |
// connect ws | |
window.onload = async () => { | |
await connect(); | |
} | |
async function connect() { | |
// url = ((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/api"; | |
url = "wss://alm.linksoul.ai/api"; | |
ws = new WebSocket(url); | |
ws.onopen = function (e) { | |
console.log('握手成功'); | |
if (ws.readyState == 1) { //ws进入连接状态,则每隔500毫秒发送一包数据 | |
console.log('连接状态成功'); | |
// resultsDiv.style.display = ''; | |
// llasaLoading.style.display = 'none'; | |
container.style.opacity = 1; | |
llasaLoading.style.display = 'none'; | |
} | |
}; | |
ws.onmessage = function (e) { | |
console.log(e['data']) | |
var response = JSON.parse(e['data']); | |
if(response["action"] == "qa"){ | |
// nothing to do | |
if(response['msg'] == 'ok') { | |
console.log(response["data"]) | |
updateResponse(response['data']['cid'], response['data']['answer']) | |
}else{ | |
console.log(response['msg']); | |
} | |
} | |
} | |
ws.onerror = function (err) { | |
console.info('ws error: '+err) | |
} | |
ws.onclose=function(e){ | |
console.info('ws close: '+e); | |
}; | |
} | |
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay)) | |
const submitTextButton = document.getElementById('send_button'); | |
submitTextButton.onclick = async () => { | |
await sendMessage(); | |
} | |
async function sendMessage() { | |
if(ws == null || ws.readyState != 1) { | |
// alert('服务未连接,请刷新页面'); | |
// return; | |
await connect(); | |
await sleep(800); | |
} | |
var userTextDiv = document.getElementById('user-text'); | |
text = userTextDiv.value | |
userTextDiv.value = '' | |
console.log('user input text', text); | |
console.log('user input audio', audio_base64); | |
if (text.length == 0 && audio_base64 == null) return; | |
var cid = crypto.randomUUID(); | |
if (text.length > 0) { | |
addSentMessageToDOM({ | |
'cid': "q_text_" + cid, | |
'from': 'human', | |
'value': text, | |
'type': 'text' | |
}); | |
} | |
if (audio_base64 != null) { | |
addAudioSentMessageToDOM({ | |
'cid': "q_audio_" + cid, | |
'from': 'human', | |
'value': audio_base64, | |
'type': 'audio' | |
}); | |
} | |
ws.send(JSON.stringify({"action": "qa", "data":{"cid": cid, "text": text, "audio": audio_base64, "vc_enabled": vc_enabled}})); | |
addRecieveMessageToDOM({ | |
'cid': "a_text_" + cid, | |
'from': 'gpt', | |
'value': '', | |
'type': 'text' | |
}) | |
if (text != '') { | |
text = ''; | |
} | |
if (audio_base64 != null) { | |
audio_base64 = null; | |
// 清空缓存区 | |
audioPlayer.src = ''; | |
audioPlayer.style.display = 'none'; | |
} | |
} | |
function blobToDataURI(blob, callback) { | |
var reader = new FileReader(); | |
reader.onload = function (e) { | |
callback(e.target.result); | |
} | |
reader.readAsDataURL(blob); | |
} | |
const resetButton = document.getElementById('delete_button'); | |
resetButton.onclick = () => { | |
clear(); | |
resultsDiv.innerHTML = ''; | |
audioPlayer.src = ''; | |
audioPlayer.style.display = 'none'; | |
waveformDiv.style.display = 'none'; | |
} | |
function clear() {//update | |
ws.send(JSON.stringify({"action": "clear"})); | |
} | |
const recordButton = document.getElementById('start_button'); | |
recordButton.onclick = () => { | |
record_audio(); | |
} | |
function record_audio() {//update | |
if (!isRecording) { | |
recorder = Recorder({type:"mp3", sampleRate:44100, bitRate:128, onProcess:function(buffers,powerLevel,bufferDuration,bufferSampleRate,newBufferIdx,asyncEnd){ | |
wave&&wave.input(buffers[buffers.length-1],powerLevel,bufferSampleRate); | |
}}); | |
recorder.open(function(){ | |
isRecording = true; | |
recorder.start(); | |
audioPlayer.style.display = 'none'; | |
waveformDiv.style.display = ''; | |
recordButton.style.filter = "invert(18%) sepia(66%) saturate(5808%) hue-rotate(338deg) brightness(91%) contrast(125%)"; | |
},function(msg,isUserNotAllow){ | |
alert("请允许浏览器获取麦克风录音权限"); | |
console.log((isUserNotAllow?"UserNotAllow, ":"")+"无法录音:"+msg); | |
}); | |
}else { | |
isRecording = false; | |
recorder.stop(function(blob, duration){ | |
audioPlayer.style.display = ''; | |
waveformDiv.style.display = 'none'; | |
blobToDataURI(blob, function(audio_base64_data){ | |
audio_base64 = audio_base64_data; | |
// document.getElementById('audioPlayer').src = URL.createObjectURL(blob); | |
recorder.close(); | |
recorder=null; | |
// 移动 audio 到暂存区 | |
audioPlayer.src = audio_base64; | |
// sendMessage(); | |
}); | |
},function(msg){ | |
alert("录音失败"); | |
console.log("录音失败:"+msg); | |
recorder.close(); | |
recorder=null; | |
}); | |
recordButton.style.filter = null; | |
} | |
} | |