'commit'
This commit is contained in:
@@ -1,266 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>学伴切换示例</title>
|
|
||||||
<style>
|
|
||||||
.model-selector {
|
|
||||||
position: fixed;
|
|
||||||
top: 20px;
|
|
||||||
left: 20px;
|
|
||||||
z-index: 1000;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
padding: 8px 12px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: white;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.recording-indicator {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
left: 20px;
|
|
||||||
z-index: 1000;
|
|
||||||
padding: 10px 15px;
|
|
||||||
background-color: rgba(220, 53, 69, 0.9);
|
|
||||||
color: white;
|
|
||||||
border-radius: 20px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
display: none;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.recording-dot {
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 8px;
|
|
||||||
animation: pulse 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes pulse {
|
|
||||||
0% { opacity: 1; }
|
|
||||||
50% { opacity: 0.5; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
.record-controls {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
z-index: 1000;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.record-button {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #dc3545;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
font-size: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
.record-button:hover {
|
|
||||||
background-color: #c82333;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="model-selector">
|
|
||||||
<label for="model-select">选择学伴:</label>
|
|
||||||
<select id="model-select">
|
|
||||||
<option value="shizuku">小智</option>
|
|
||||||
<option value="koharu">小荷</option>
|
|
||||||
<option value="wanko">汪喵</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="recording-indicator" id="recordingIndicator">
|
|
||||||
<div class="recording-dot"></div>
|
|
||||||
<span>正在录音...</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="record-controls" id="recordControls">
|
|
||||||
<button class="record-button" id="stopRecordBtn">停止</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://l2dwidget.js.org/lib/L2Dwidget.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// 模型配置
|
|
||||||
const models = {
|
|
||||||
shizuku: {
|
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-shizuku@1.0.5/assets/shizuku.model.json",
|
|
||||||
name: "志津子"
|
|
||||||
},
|
|
||||||
koharu: {
|
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-koharu@1.0.5/assets/koharu.model.json",
|
|
||||||
name: "小春日和"
|
|
||||||
},
|
|
||||||
wanko: {
|
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json",
|
|
||||||
name: "汪喵"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 录音相关变量
|
|
||||||
let mediaRecorder;
|
|
||||||
let audioChunks = [];
|
|
||||||
let isRecording = false;
|
|
||||||
|
|
||||||
// 获取URL参数
|
|
||||||
function getUrlParam(name) {
|
|
||||||
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
|
|
||||||
const r = window.location.search.substr(1).match(reg);
|
|
||||||
if (r != null) return unescape(r[2]);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化录音功能
|
|
||||||
function initRecording() {
|
|
||||||
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
||||||
console.log("录音功能初始化成功");
|
|
||||||
} else {
|
|
||||||
console.error("您的浏览器不支持录音功能");
|
|
||||||
alert("您的浏览器不支持录音功能,请使用现代浏览器");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始录音
|
|
||||||
function startRecording() {
|
|
||||||
if (isRecording) return;
|
|
||||||
|
|
||||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
|
||||||
.then(stream => {
|
|
||||||
mediaRecorder = new MediaRecorder(stream);
|
|
||||||
audioChunks = [];
|
|
||||||
|
|
||||||
mediaRecorder.ondataavailable = event => {
|
|
||||||
if (event.data.size > 0) {
|
|
||||||
audioChunks.push(event.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
mediaRecorder.onstop = () => {
|
|
||||||
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
|
||||||
// 这里可以处理录音完成后的音频数据,例如发送到服务器进行ASR识别
|
|
||||||
console.log("录音完成,音频数据大小:", audioBlob.size);
|
|
||||||
// 示例:创建音频URL并播放
|
|
||||||
const audioUrl = URL.createObjectURL(audioBlob);
|
|
||||||
console.log("录音URL:", audioUrl);
|
|
||||||
// 可以在这里调用ASR服务
|
|
||||||
};
|
|
||||||
|
|
||||||
mediaRecorder.start();
|
|
||||||
isRecording = true;
|
|
||||||
document.getElementById('recordingIndicator').style.display = 'flex';
|
|
||||||
document.getElementById('recordControls').style.display = 'block';
|
|
||||||
console.log("开始录音");
|
|
||||||
|
|
||||||
// 设置最长录音时间为60秒
|
|
||||||
setTimeout(stopRecording, 60000);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error("获取麦克风权限失败:", error);
|
|
||||||
alert("请授权麦克风权限以使用录音功能");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停止录音
|
|
||||||
function stopRecording() {
|
|
||||||
if (!isRecording || !mediaRecorder) return;
|
|
||||||
|
|
||||||
mediaRecorder.stop();
|
|
||||||
isRecording = false;
|
|
||||||
document.getElementById('recordingIndicator').style.display = 'none';
|
|
||||||
document.getElementById('recordControls').style.display = 'none';
|
|
||||||
console.log("停止录音");
|
|
||||||
|
|
||||||
// 停止所有音轨
|
|
||||||
if (mediaRecorder.stream) {
|
|
||||||
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化看板娘
|
|
||||||
function initL2Dwidget() {
|
|
||||||
// 获取模型ID (从URL参数或默认)
|
|
||||||
const modelId = getUrlParam('id') || 'shizuku';
|
|
||||||
const model = models[modelId] || models.shizuku;
|
|
||||||
|
|
||||||
// 设置下拉框选中项
|
|
||||||
document.getElementById('model-select').value = modelId;
|
|
||||||
console.log('加载模型:', model.name, model.jsonPath);
|
|
||||||
|
|
||||||
// 初始化模型
|
|
||||||
L2Dwidget.init({
|
|
||||||
"model": {
|
|
||||||
"jsonPath": model.jsonPath,
|
|
||||||
"scale": 1
|
|
||||||
},
|
|
||||||
"display": {
|
|
||||||
"position": "right",
|
|
||||||
"width": 150,
|
|
||||||
"height": 300,
|
|
||||||
"hOffset": 0,
|
|
||||||
"vOffset": -20
|
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"show": true,
|
|
||||||
"scale": 0.5
|
|
||||||
},
|
|
||||||
"react": {
|
|
||||||
"opacityDefault": 0.8,
|
|
||||||
"opacityOnHover": 1
|
|
||||||
},
|
|
||||||
"dialog": {
|
|
||||||
"enable": true,
|
|
||||||
"script": {
|
|
||||||
'tap body': `你好啊,我是${model.name}。点击我可以开始录音哦~`,
|
|
||||||
'tap face': '有什么问题或者烦心事都可以和我聊聊~',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加点击看板娘任意位置触发录音
|
|
||||||
setTimeout(() => {
|
|
||||||
const live2dElement = document.querySelector('.live2d-widget');
|
|
||||||
if (live2dElement) {
|
|
||||||
live2dElement.addEventListener('click', function(e) {
|
|
||||||
// 检查是否点击了对话框或其他控件
|
|
||||||
if (!e.target.closest('.l2d-dialog') && !e.target.closest('.model-selector') && !e.target.closest('.record-controls')) {
|
|
||||||
if (isRecording) {
|
|
||||||
stopRecording();
|
|
||||||
} else {
|
|
||||||
startRecording();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听下拉框变化
|
|
||||||
document.getElementById('model-select').addEventListener('change', function() {
|
|
||||||
const modelId = this.value;
|
|
||||||
console.log('切换模型至:', modelId);
|
|
||||||
// 更新URL参数并刷新页面
|
|
||||||
window.location.search = '?id=' + modelId;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 停止录音按钮事件
|
|
||||||
document.getElementById('stopRecordBtn').addEventListener('click', stopRecording);
|
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
|
||||||
window.onload = function() {
|
|
||||||
initL2Dwidget();
|
|
||||||
initRecording();
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -6,69 +6,41 @@
|
|||||||
<title>学伴切换示例</title>
|
<title>学伴切换示例</title>
|
||||||
<style>
|
<style>
|
||||||
.model-selector {
|
.model-selector {
|
||||||
position: fixed;
|
position: fixed; top: 20px; left: 20px; z-index: 1000;
|
||||||
top: 20px;
|
padding: 10px; background-color: rgba(255, 255, 255, 0.8);
|
||||||
left: 20px;
|
border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
z-index: 1000;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
select {
|
select { padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px; background-color: white; font-size: 14px; }
|
||||||
padding: 8px 12px;
|
.recording-controls {
|
||||||
border: 1px solid #ccc;
|
position: fixed; bottom: 20px; right: 20px; z-index: 1000;
|
||||||
border-radius: 4px;
|
display: flex; flex-direction: column; gap: 10px;
|
||||||
background-color: white;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.recording-indicator {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
left: 20px;
|
|
||||||
z-index: 1000;
|
|
||||||
padding: 10px 15px;
|
|
||||||
background-color: rgba(220, 53, 69, 0.9);
|
|
||||||
color: white;
|
|
||||||
border-radius: 20px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
display: none;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.recording-dot {
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 8px;
|
|
||||||
animation: pulse 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes pulse {
|
|
||||||
0% { opacity: 1; }
|
|
||||||
50% { opacity: 0.5; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
.record-controls {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
z-index: 1000;
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
.record-button {
|
.record-button {
|
||||||
width: 60px;
|
width: 70px; height: 70px; border-radius: 50%;
|
||||||
height: 60px;
|
background-color: #dc3545; border: none; color: white;
|
||||||
border-radius: 50%;
|
font-size: 16px; cursor: pointer; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
background-color: #dc3545;
|
display: flex; align-items: center; justify-content: center;
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
font-size: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
.record-button:hover {
|
.record-button:hover { background-color: #c82333; }
|
||||||
background-color: #c82333;
|
.stop-button {
|
||||||
|
width: 70px; height: 70px; border-radius: 50%;
|
||||||
|
background-color: #6c757d; border: none; color: white;
|
||||||
|
font-size: 16px; cursor: pointer; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
.stop-button:hover { background-color: #5a6268; }
|
||||||
|
.recording-indicator {
|
||||||
|
position: fixed; bottom: 20px; left: 20px; z-index: 1000;
|
||||||
|
padding: 10px 15px; background-color: rgba(220, 53, 69, 0.9);
|
||||||
|
color: white; border-radius: 20px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
display: none; align-items: center;
|
||||||
|
}
|
||||||
|
.recording-dot {
|
||||||
|
width: 10px; height: 10px; background-color: white;
|
||||||
|
border-radius: 50%; margin-right: 8px; animation: pulse 1.5s infinite;
|
||||||
|
}
|
||||||
|
@keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -86,81 +58,58 @@
|
|||||||
<span>正在录音...</span>
|
<span>正在录音...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="record-controls" id="recordControls">
|
<div class="recording-controls">
|
||||||
<button class="record-button" id="stopRecordBtn">停止</button>
|
<button class="record-button" id="startRecordBtn">开始录音</button>
|
||||||
|
<button class="stop-button" id="stopRecordBtn">停止录音</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://l2dwidget.js.org/lib/L2Dwidget.min.js"></script>
|
<script src="https://l2dwidget.js.org/lib/L2Dwidget.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// 模型配置
|
// 模型配置
|
||||||
const models = {
|
const models = {
|
||||||
shizuku: {
|
shizuku: { jsonPath: "https://unpkg.com/live2d-widget-model-shizuku@1.0.5/assets/shizuku.model.json", name: "志津子" },
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-shizuku@1.0.5/assets/shizuku.model.json",
|
koharu: { jsonPath: "https://unpkg.com/live2d-widget-model-koharu@1.0.5/assets/koharu.model.json", name: "小春日和" },
|
||||||
name: "志津子"
|
wanko: { jsonPath: "https://unpkg.com/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json", name: "汪喵" }
|
||||||
},
|
|
||||||
koharu: {
|
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-koharu@1.0.5/assets/koharu.model.json",
|
|
||||||
name: "小春日和"
|
|
||||||
},
|
|
||||||
wanko: {
|
|
||||||
jsonPath: "https://unpkg.com/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json",
|
|
||||||
name: "汪喵"
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 录音相关变量
|
// 录音相关变量
|
||||||
let mediaRecorder;
|
let mediaRecorder; let audioChunks = []; let isRecording = false;
|
||||||
let audioChunks = [];
|
|
||||||
let isRecording = false;
|
|
||||||
|
|
||||||
// 获取URL参数
|
// 获取URL参数
|
||||||
function getUrlParam(name) {
|
function getUrlParam(name) {
|
||||||
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
|
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
|
||||||
const r = window.location.search.substr(1).match(reg);
|
const r = window.location.search.substr(1).match(reg);
|
||||||
if (r != null) return unescape(r[2]);
|
return r ? unescape(r[2]) : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化录音功能
|
|
||||||
function initRecording() {
|
|
||||||
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
||||||
console.log("录音功能初始化成功");
|
|
||||||
} else {
|
|
||||||
console.error("您的浏览器不支持录音功能");
|
|
||||||
alert("您的浏览器不支持录音功能,请使用现代浏览器");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始录音
|
// 开始录音
|
||||||
function startRecording() {
|
function startRecording() {
|
||||||
if (isRecording) return;
|
if (isRecording) return;
|
||||||
|
|
||||||
|
console.log("尝试开始录音");
|
||||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
navigator.mediaDevices.getUserMedia({ audio: true })
|
||||||
.then(stream => {
|
.then(stream => {
|
||||||
mediaRecorder = new MediaRecorder(stream);
|
mediaRecorder = new MediaRecorder(stream);
|
||||||
audioChunks = [];
|
audioChunks = [];
|
||||||
|
|
||||||
mediaRecorder.ondataavailable = event => {
|
mediaRecorder.ondataavailable = event => {
|
||||||
if (event.data.size > 0) {
|
if (event.data.size > 0) audioChunks.push(event.data);
|
||||||
audioChunks.push(event.data);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mediaRecorder.onstop = () => {
|
mediaRecorder.onstop = () => {
|
||||||
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
||||||
// 这里可以处理录音完成后的音频数据,例如发送到服务器进行ASR识别
|
|
||||||
console.log("录音完成,音频数据大小:", audioBlob.size);
|
console.log("录音完成,音频数据大小:", audioBlob.size);
|
||||||
// 示例:创建音频URL并播放
|
|
||||||
const audioUrl = URL.createObjectURL(audioBlob);
|
const audioUrl = URL.createObjectURL(audioBlob);
|
||||||
console.log("录音URL:", audioUrl);
|
console.log("录音URL:", audioUrl);
|
||||||
// 可以在这里调用ASR服务
|
// 这里可以调用ASR服务
|
||||||
};
|
};
|
||||||
|
|
||||||
mediaRecorder.start();
|
mediaRecorder.start();
|
||||||
isRecording = true;
|
isRecording = true;
|
||||||
document.getElementById('recordingIndicator').style.display = 'flex';
|
document.getElementById('recordingIndicator').style.display = 'flex';
|
||||||
document.getElementById('recordControls').style.display = 'block';
|
document.getElementById('startRecordBtn').style.display = 'none';
|
||||||
console.log("开始录音");
|
document.getElementById('stopRecordBtn').style.display = 'flex';
|
||||||
|
console.log("开始录音成功");
|
||||||
|
|
||||||
// 设置最长录音时间为60秒
|
// 设置最长录音时间为60秒
|
||||||
setTimeout(stopRecording, 60000);
|
setTimeout(stopRecording, 60000);
|
||||||
@@ -178,10 +127,10 @@
|
|||||||
mediaRecorder.stop();
|
mediaRecorder.stop();
|
||||||
isRecording = false;
|
isRecording = false;
|
||||||
document.getElementById('recordingIndicator').style.display = 'none';
|
document.getElementById('recordingIndicator').style.display = 'none';
|
||||||
document.getElementById('recordControls').style.display = 'none';
|
document.getElementById('startRecordBtn').style.display = 'flex';
|
||||||
|
document.getElementById('stopRecordBtn').style.display = 'none';
|
||||||
console.log("停止录音");
|
console.log("停止录音");
|
||||||
|
|
||||||
// 停止所有音轨
|
|
||||||
if (mediaRecorder.stream) {
|
if (mediaRecorder.stream) {
|
||||||
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
||||||
}
|
}
|
||||||
@@ -189,77 +138,48 @@
|
|||||||
|
|
||||||
// 初始化看板娘
|
// 初始化看板娘
|
||||||
function initL2Dwidget() {
|
function initL2Dwidget() {
|
||||||
// 获取模型ID (从URL参数或默认)
|
|
||||||
const modelId = getUrlParam('id') || 'shizuku';
|
const modelId = getUrlParam('id') || 'shizuku';
|
||||||
const model = models[modelId] || models.shizuku;
|
const model = models[modelId] || models.shizuku;
|
||||||
|
|
||||||
// 设置下拉框选中项
|
|
||||||
document.getElementById('model-select').value = modelId;
|
document.getElementById('model-select').value = modelId;
|
||||||
console.log('加载模型:', model.name, model.jsonPath);
|
console.log('加载模型:', model.name, model.jsonPath);
|
||||||
|
|
||||||
// 初始化模型
|
// 初始化模型
|
||||||
L2Dwidget.init({
|
L2Dwidget.init({
|
||||||
"model": {
|
"model": { "jsonPath": model.jsonPath, "scale": 1 },
|
||||||
"jsonPath": model.jsonPath,
|
"display": { "position": "right", "width": 150, "height": 300, "hOffset": 0, "vOffset": -20 },
|
||||||
"scale": 1
|
"mobile": { "show": true, "scale": 0.5 },
|
||||||
},
|
"react": { "opacityDefault": 0.8, "opacityOnHover": 1 },
|
||||||
"display": {
|
"dialog": { "enable": true, "script": {
|
||||||
"position": "right",
|
'tap body': `你好啊,我是${model.name}。`,
|
||||||
"width": 150,
|
'tap face': '有什么问题或者烦心事都可以和我聊聊~'
|
||||||
"height": 300,
|
}}
|
||||||
"hOffset": 0,
|
|
||||||
"vOffset": -20
|
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"show": true,
|
|
||||||
"scale": 0.5
|
|
||||||
},
|
|
||||||
"react": {
|
|
||||||
"opacityDefault": 0.8,
|
|
||||||
"opacityOnHover": 1
|
|
||||||
},
|
|
||||||
"dialog": {
|
|
||||||
"enable": true,
|
|
||||||
"script": {
|
|
||||||
'tap body': `你好啊,我是${model.name}。点击我可以开始录音哦~`,
|
|
||||||
'tap face': '有什么问题或者烦心事都可以和我聊聊~',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 添加点击看板娘任意位置触发录音
|
|
||||||
setTimeout(() => {
|
|
||||||
const live2dElement = document.querySelector('.live2d-widget');
|
|
||||||
if (live2dElement) {
|
|
||||||
live2dElement.addEventListener('click', function(e) {
|
|
||||||
// 检查是否点击了对话框或其他控件
|
|
||||||
if (!e.target.closest('.l2d-dialog') && !e.target.closest('.model-selector') && !e.target.closest('.record-controls')) {
|
|
||||||
if (isRecording) {
|
|
||||||
stopRecording();
|
|
||||||
} else {
|
|
||||||
startRecording();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听下拉框变化
|
// 监听下拉框变化
|
||||||
document.getElementById('model-select').addEventListener('change', function() {
|
document.getElementById('model-select').addEventListener('change', function() {
|
||||||
const modelId = this.value;
|
window.location.search = '?id=' + this.value;
|
||||||
console.log('切换模型至:', modelId);
|
|
||||||
// 更新URL参数并刷新页面
|
|
||||||
window.location.search = '?id=' + modelId;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 停止录音按钮事件
|
// 绑定录音按钮事件
|
||||||
|
document.getElementById('startRecordBtn').addEventListener('click', startRecording);
|
||||||
document.getElementById('stopRecordBtn').addEventListener('click', stopRecording);
|
document.getElementById('stopRecordBtn').addEventListener('click', stopRecording);
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
// 页面加载完成后初始化
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
initL2Dwidget();
|
initL2Dwidget();
|
||||||
initRecording();
|
// 页面加载时请求麦克风权限
|
||||||
|
navigator.mediaDevices.getUserMedia({ audio: true })
|
||||||
|
.then(stream => {
|
||||||
|
console.log("麦克风权限已授予");
|
||||||
|
// 立即停止流,只获取权限
|
||||||
|
stream.getTracks().forEach(track => track.stop());
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("获取麦克风权限失败:", error);
|
||||||
|
alert("请授权麦克风权限以使用录音功能");
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
Reference in New Issue
Block a user