first commit
This commit is contained in:
commit
3ebdf2931b
20132
duix/duix.js
Normal file
20132
duix/duix.js
Normal file
File diff suppressed because it is too large
Load Diff
379
simple.html
Normal file
379
simple.html
Normal file
@ -0,0 +1,379 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="expires" content="0" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximu-scale=1.0,user-scalable=no" />
|
||||
<title>Duix Sdk Simple Example</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary-100: #FF7F50;
|
||||
--primary-200: #dd6236;
|
||||
--primary-300: #8f1e00;
|
||||
--accent-100: #8B4513;
|
||||
--accent-200: #ffd299;
|
||||
--text-100: #000000;
|
||||
--text-200: #2c2c2c;
|
||||
--bg-100: #F7EEDD;
|
||||
--bg-200: #ede4d3;
|
||||
--bg-300: #c4bcab;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
background: var(--bg-100);
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
background: rgba(247, 238, 221, 0.95);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: transparent;
|
||||
padding: 20px;
|
||||
width: auto;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
animation: fadeIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(-20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: var(--bg-200);
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item>span {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
color: var(--text-200);
|
||||
}
|
||||
|
||||
.input {
|
||||
background: var(--bg-100);
|
||||
height: 48px;
|
||||
border: 1px solid var(--accent-100);
|
||||
outline: none;
|
||||
border-radius: 8px;
|
||||
padding: 0 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
color: var(--text-200);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
border-color: var(--primary-100);
|
||||
box-shadow: 0 0 0 3px var(--accent-200);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
height: 48px;
|
||||
background: var(--primary-100);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 8px rgba(0,0,0,0.15);
|
||||
background: var(--primary-200);
|
||||
}
|
||||
|
||||
.btn-config {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: var(--accent-100);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.btn-config:hover {
|
||||
transform: rotate(90deg);
|
||||
background: var(--primary-200);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdn.bootcss.com/eruda/1.3.2/eruda.min.js"></script>
|
||||
<script>eruda.init()</script>
|
||||
<script src="./duix/duix.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- 数字人容器 -->
|
||||
<div class="container"></div>
|
||||
|
||||
<div id="modal" class="modal">
|
||||
<div class="modal-content" style="text-align: center; padding: 20px; position: relative;">
|
||||
<button id="configBtn" class="btn-config" onclick="toggleConfig()">⚙️</button>
|
||||
<div id="configSection" style="display: none;">
|
||||
<!-- <div style="margin-bottom: 8px; width: 100%; text-align: left; color: var(--text-200);">签名密钥</div> -->
|
||||
<input class="input" style="display: none;" id="sign" placeholder="请输入您的签名密钥" value="" />
|
||||
<input class="input" style="display: none;" id="audio" placeholder="音色" value="" />
|
||||
<div style="margin-bottom: 8px; width: 100%; text-align: left; color: var(--text-200);">性别</div>
|
||||
<select class="input" id="gender" style="margin-bottom: 16px;">
|
||||
<option value="male" selected>男</option>
|
||||
<option value="female" >女</option>
|
||||
</select>
|
||||
<div style="margin-bottom: 8px; width: 100%; text-align: left; color: var(--text-200);">会话ID</div>
|
||||
<input class="input" id="conversationId" placeholder="请输入会话ID" value="1920410565458886658" title="请输入会话ID" />
|
||||
</div>
|
||||
<button id="start" onclick="init()" class="btn" style="width: 200px; margin: 20px auto 0;">
|
||||
<span>开始智能会话</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const duix = new DUIX()
|
||||
|
||||
const sex = {
|
||||
"male": "1920410565458886658",
|
||||
"female": "1933000305591988225"
|
||||
}
|
||||
let conversationL = ""
|
||||
const sex_audio = {
|
||||
"male": "gongzheng-v2",
|
||||
"female": "presenter_female"
|
||||
}
|
||||
const audio = document.getElementById('audio')
|
||||
// Add event listener for gender selection
|
||||
document.getElementById('gender').addEventListener('change', function(e) {
|
||||
const selectedGender = e.target.value;
|
||||
const conversationIdInput = document.getElementById('conversationId');
|
||||
|
||||
conversationIdInput.value = sex[selectedGender];
|
||||
audio.value = sex_audio[selectedGender]
|
||||
});
|
||||
|
||||
// Set initial conversation ID based on default gender
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const genderSelect = document.getElementById('gender');
|
||||
const conversationIdInput = document.getElementById('conversationId');
|
||||
conversationIdInput.value = sex[genderSelect.value];
|
||||
audio.value = sex_audio[genderSelect.value]
|
||||
});
|
||||
|
||||
async function getToken() {
|
||||
try {
|
||||
const response = await fetch('http://192.168.2.183:8080/token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
return data.token;
|
||||
} catch (error) {
|
||||
console.error('Error getting token:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleConfig() {
|
||||
const configSection = document.getElementById('configSection');
|
||||
if (configSection.style.display === 'none') {
|
||||
configSection.style.display = 'block';
|
||||
} else {
|
||||
configSection.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function init() {
|
||||
let sign = document.querySelector('#sign').value;
|
||||
const conversationId = document.querySelector('#conversationId').value;
|
||||
|
||||
if (!sign) {
|
||||
try {
|
||||
sign = await getToken();
|
||||
document.querySelector('#sign').value = sign;
|
||||
} catch (error) {
|
||||
alert('获取token失败,请重试');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conversationId) {
|
||||
return alert('会话ID不能为空');
|
||||
}
|
||||
|
||||
duix.on('error', data => {
|
||||
console.error(data)
|
||||
})
|
||||
duix.on('intialSucccess', () => {
|
||||
console.info('intialSucccess')
|
||||
// 此时初始化成功,可调用start
|
||||
duix.start({ conversationId, openAsr: true, useActSection: true }).then(res => {
|
||||
console.info('start', res)
|
||||
})
|
||||
})
|
||||
duix.on('bye', (data) => {
|
||||
console.info('bye', data)
|
||||
})
|
||||
|
||||
duix.on('progress', progress => {
|
||||
console.info('progress', progress)
|
||||
})
|
||||
duix.on('show', () => {
|
||||
console.info('show')
|
||||
// 此时可确认视频已
|
||||
document.querySelector('#modal').style.display = "none"
|
||||
})
|
||||
duix.on('openAsrSuccess', () => {
|
||||
console.info('openAsrSuccess')
|
||||
})
|
||||
duix.on('asrClose', () => {
|
||||
console.info('asrClose')
|
||||
})
|
||||
// duix.on('speakStart', (data) => {
|
||||
// console.info('speakStart', data)
|
||||
// })
|
||||
// duix.on('speakEnd', (data) => {
|
||||
// console.info('speakEnd', data)
|
||||
// })
|
||||
duix.on('speakSection', (data) => {
|
||||
console.info('speakSection', data)
|
||||
})
|
||||
duix.on('speakError', (data) => {
|
||||
console.info('speakError', data)
|
||||
})
|
||||
duix.on('asrResult', async (data) => {
|
||||
console.info('asrResult', data);
|
||||
duix.break()
|
||||
// if (data == "你好") {
|
||||
try {
|
||||
const response = await fetch('http://192.168.2.183:8080/chat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: data,
|
||||
response_mode: 'streaming',
|
||||
user: 'SYS002',
|
||||
conversation_id: conversationL,
|
||||
audio: audio.value
|
||||
})
|
||||
});
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let fullAnswer = '';
|
||||
let triggered = false;
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
const chunk = decoder.decode(value);
|
||||
const lines = chunk.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data:')) {
|
||||
const responseData = JSON.parse(line.slice(5).trim());
|
||||
|
||||
|
||||
if (responseData.audio_data) {
|
||||
conversationL = responseData.conversation_id
|
||||
duix.speak({
|
||||
content: responseData.answer,
|
||||
audio: responseData.audio_data
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Handle end of stream
|
||||
if (responseData.isEnd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in chat API:', error);
|
||||
}
|
||||
// }
|
||||
|
||||
// test = [
|
||||
// 'https://p3-bot-sign.byteimg.com/tos-cn-i-v4nquku3lp/0f1be92489b849f3b7568e9b17334e42.wav~tplv-v4nquku3lp-image.image?rk3s=68e6b6b5&x-expires=1752754758&x-signature=rXa5LFcZttKGZpHMVIP6SgZTsRI%3D','https://p6-bot-sign.byteimg.com/tos-cn-i-v4nquku3lp/9898244b02be4765a964cf4b3d4afcd0.wav~tplv-v4nquku3lp-image.image?rk3s=68e6b6b5&x-expires=1752754726&x-signature=%2BbIrCv%2B5yAUxZvNqBURCnSRVqWo%3D','https://p9-bot-sign.byteimg.com/tos-cn-i-v4nquku3lp/4bffded0446648a2aef1d2d7e59ddd0c.wav~tplv-v4nquku3lp-image.image?rk3s=68e6b6b5&x-expires=1752754642&x-signature=E5Dr2R%2Fhd%2Ft7K593ka393OlCPNg%3D']
|
||||
// for (let index = 0; index < test.length; index++) {
|
||||
// const element = test[index];
|
||||
// duix.speak({content: "我会尽量帮助您", audio: element})
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
duix.on('report', data => {
|
||||
// console.info('report', data)
|
||||
})
|
||||
duix.on('speakEnd', async(data) => {
|
||||
console.info('公证speakEnd: ', data)
|
||||
|
||||
})
|
||||
duix.init({
|
||||
sign,
|
||||
containerLable: '.container'
|
||||
}).then(data => {
|
||||
console.info('init', data)
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', function(event) {
|
||||
if (duix) {
|
||||
duix.destroy()
|
||||
duix.stop()
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user