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://demo.linksoul.ai/alm/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; } }