Files
dsProject/dsLightRag/static/video-retalk.html
2025-09-02 08:58:30 +08:00

371 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频合成</title>
<link rel="stylesheet" href="/static/layui/css/layui.css">
<style>
* {
margin: 0; padding: 0; box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
body {
background-color: #f5f7fa;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
padding: 40px 20px;
background: linear-gradient(135deg, #3498db, #8e44ad);
color: white;
border-radius: 10px;
margin-bottom: 30px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
h1 {
font-size: 2.2rem;
margin-bottom: 10px;
font-weight: 700;
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
max-width: 800px;
margin: 0 auto;
}
.main-content {
display: flex;
flex-wrap: wrap;
gap: 30px;
margin-bottom: 30px;
}
.form-section {
flex: 1;
min-width: 300px;
background-color: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.result-section {
flex: 1;
min-width: 300px;
background-color: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #2c3e50;
}
select, textarea, input[type="text"] {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border 0.3s;
}
select:focus, textarea:focus, input[type="text"]:focus {
border-color: #3498db;
outline: none;
}
textarea {
min-height: 150px;
resize: vertical;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: background 0.3s;
display: inline-block;
text-align: center;
}
.btn-primary {
background-color: #3498db;
color: white;
}
.btn-primary:hover {
background-color: #2980b9;
}
.btn:disabled {
background-color: #95a5a6;
cursor: not-allowed;
}
.upload-area {
border: 2px dashed #ddd;
border-radius: 6px;
padding: 30px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
margin-bottom: 15px;
}
.upload-area:hover {
border-color: #3498db;
background-color: #f8f9fa;
}
.upload-icon {
font-size: 48px;
color: #95a5a6;
margin-bottom: 10px;
}
.video-preview {
width: 100%;
border-radius: 6px;
margin-top: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.loading {
display: none;
text-align: center;
margin: 20px 0;
}
.loading.active {
display: block;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
border-top: 4px solid #3498db;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 15px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.empty-state {
text-align: center;
padding: 40px 0;
color: #999;
}
.url-input-group {
display: flex;
gap: 10px;
}
.url-input-group input {
flex: 1;
}
@media screen and (max-width: 768px) {
.main-content {
flex-direction: column;
}
h1 {
font-size: 1.8rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>视频合成</h1>
<p class="subtitle">上传图片和音频,合成人物讲话视频</p>
</header>
<div class="main-content">
<div class="form-section">
<h2>素材设置</h2>
<div class="form-group">
<label>图片上传/地址录入</label>
<div class="upload-area" id="image-upload">
<div class="upload-icon">📷</div>
<p>点击上传图片或拖放至此处</p>
<p style="font-size: 0.9rem; color: #999; margin-top: 5px;">支持JPG、PNG格式大小不超过5MB</p>
</div>
<div class="url-input-group">
<input type="text" id="image-url" placeholder="或输入图片URL地址" value="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/LiBai.jpg">
</div>
<div style="margin-top: 15px;">
<label>图片预览</label>
<div style="border: 1px solid #ddd; border-radius: 6px; padding: 10px; text-align: center; margin-top: 8px;">
<img id="image-preview" src="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/LiBai.jpg" style="max-width: 100%; max-height: 200px; border-radius: 4px;" alt="图片预览">
</div>
</div>
</div>
<div class="form-group">
<label>音频上传/地址录入</label>
<div class="upload-area" id="audio-upload">
<div class="upload-icon">🎵</div>
<p>点击上传音频或拖放至此处</p>
<p style="font-size: 0.9rem; color: #999; margin-top: 5px;">支持MP3、WAV格式大小不超过20MB</p>
</div>
<div class="url-input-group">
<input type="text" id="audio-url" placeholder="或输入音频URL地址" value="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/HaiShangShengMingYue.mp3">
</div>
<div style="margin-top: 15px;">
<label>音频试听</label>
<div style="margin-top: 8px;">
<audio id="audio-preview" controls style="width: 100%; border-radius: 4px;">
<source src="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/HaiShangShengMingYue.mp3" type="audio/mpeg">
您的浏览器不支持音频播放
</audio>
</div>
</div>
</div>
<div class="form-group">
<label for="eye-movement">眼睛移动频率</label>
<select id="eye-movement">
<option value="low"></option>
<option value="medium" selected></option>
<option value="high"></option>
</select>
</div>
<button id="generate-btn" class="btn btn-primary">生成视频</button>
</div>
<div class="result-section">
<h2>合成结果</h2>
<div id="loading" class="loading">
<div class="spinner"></div>
<p>正在生成视频,请稍候...</p>
</div>
<div id="video-result" style="display: none;">
<video class="video-preview" id="video-player" controls></video>
</div>
<div id="empty-result" class="empty-state">
<p>暂无合成结果</p>
</div>
</div>
</div>
</div>
<script src="/static/layui/layui.js"></script>
<script>
// 初始化LayUI
layui.use(['layer'], function() {
const layer = layui.layer;
// 上传区域点击事件 - 仅UI展示
document.getElementById('image-upload').addEventListener('click', function() {
layer.msg('图片上传功能敬请期待', {icon: 6});
});
document.getElementById('audio-upload').addEventListener('click', function() {
layer.msg('音频上传功能敬请期待', {icon: 6});
});
// 实时更新预览
document.getElementById('image-url').addEventListener('input', function() {
const preview = document.getElementById('image-preview');
const url = this.value.trim();
if (url) {
preview.src = url;
}
});
document.getElementById('audio-url').addEventListener('input', function() {
const preview = document.getElementById('audio-preview');
const url = this.value.trim();
if (url) {
preview.src = url;
}
});
// 生成按钮点击事件
document.getElementById('generate-btn').addEventListener('click', async function() {
const generateBtn = this;
const loading = document.getElementById('loading');
const videoResult = document.getElementById('video-result');
const emptyResult = document.getElementById('empty-result');
const videoPlayer = document.getElementById('video-player');
// 获取参数
const imageUrl = document.getElementById('image-url').value.trim();
const audioUrl = document.getElementById('audio-url').value.trim();
const eyeMovement = document.getElementById('eye-movement').value;
// 映射眼睛移动频率
const eyeMoveFreqMap = {low: 0.3, medium: 0.5, high: 0.7};
// 显示加载状态
generateBtn.disabled = true;
loading.classList.add('active');
videoResult.style.display = 'none';
emptyResult.style.display = 'none';
try {
// 实际API调用
const response = await fetch('/api/video/generate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
image_url: imageUrl,
audio_url: audioUrl,
eye_move_freq: eyeMoveFreqMap[eyeMovement]
})
});
const data = await response.json();
if (data.success && data.video_url) {
videoPlayer.src = data.video_url;
videoResult.style.display = 'block';
layer.msg('视频合成成功', {icon: 1});
} else {
emptyResult.style.display = 'block';
layer.msg('视频合成失败: ' + data.message, {icon: 2});
}
} catch (error) {
console.error('API调用失败:', error);
emptyResult.style.display = 'block';
layer.msg('网络错误,无法连接服务器', {icon: 2});
} finally {
loading.classList.remove('active');
generateBtn.disabled = false;
}
});
});
</script>
</body>
</html>