2025-09-15 02:45:50 +08:00

454 lines
23 KiB
HTML
Raw Permalink 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.

{% extends "base.html" %}
{% block title %}语音克隆测试 - 儿童语言学习系统{% endblock %}
{% block content %}
<div class="container py-4">
<!-- 页面标题 -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex align-items-center">
<a href="{{ url_for('main.dashboard') }}" class="btn btn-outline-secondary me-3">
<i class="fas fa-arrow-left me-2"></i>返回主页
</a>
<div>
<h2 class="fw-bold mb-1">
<i class="fas fa-magic text-primary me-2"></i>
语音克隆技术测试
</h2>
<p class="text-muted mb-0">体验"听自己说"的神奇技术 - 让AI学会你的声音</p>
</div>
</div>
</div>
</div>
<!-- 连接状态检测 -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5 class="card-title">
<i class="fas fa-plug me-2"></i>服务连接状态
</h5>
<div class="d-flex align-items-center">
<button id="test-connection-btn" class="btn btn-primary me-3">
<i class="fas fa-wifi me-2"></i>测试连接
</button>
<div id="connection-status" class="flex-grow-1">
<span class="text-muted">点击测试连接按钮检查服务状态</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 核心功能:语音克隆工作流程 -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm border-primary" style="border-width: 2px !important;">
<div class="card-body">
<h4 class="card-title text-primary">
<i class="fas fa-clone me-2"></i>语音克隆工作流程
<span class="badge bg-primary ms-2">核心功能</span>
</h4>
<p class="text-muted mb-4">按照步骤操作,体验完整的语音克隆过程</p>
<!-- 步骤指示器 -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between position-relative">
<div class="step-indicator active" id="step-1-indicator">
<div class="step-circle">1</div>
<div class="step-label">录制声音</div>
</div>
<div class="step-line"></div>
<div class="step-indicator" id="step-2-indicator">
<div class="step-circle">2</div>
<div class="step-label">识别文字</div>
</div>
<div class="step-line"></div>
<div class="step-indicator" id="step-3-indicator">
<div class="step-circle">3</div>
<div class="step-label">克隆生成</div>
</div>
<div class="step-line"></div>
<div class="step-indicator" id="step-4-indicator">
<div class="step-circle">4</div>
<div class="step-label">效果对比</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- 步骤1语音样本采集 -->
<div class="col-lg-6 mb-4">
<div class="step-content" id="step-1-content">
<h5 class="text-success">
<i class="fas fa-microphone me-2"></i>步骤1录制你的声音样本
</h5>
<p class="text-muted">录制一段3-10秒的清晰语音作为语音克隆的模板</p>
<form id="voice-sample-form" enctype="multipart/form-data">
<div class="mb-3">
<label class="form-label">方式一:上传音频文件</label>
<input type="file" class="form-control" id="voice-sample-upload"
accept=".wav,.mp3,.m4a,.flac">
<div class="form-text">建议WAV格式16kHz采样率3-10秒时长</div>
</div>
<div class="mb-3 text-center">
<span class="text-muted"></span>
</div>
<div class="mb-3">
<label class="form-label">方式二:在线录音</label>
<div class="text-center">
<button type="button" id="start-recording" class="btn btn-danger me-2">
<i class="fas fa-record-vinyl me-2"></i>开始录音
</button>
<button type="button" id="stop-recording" class="btn btn-secondary" disabled>
<i class="fas fa-stop me-2"></i>停止录音
</button>
<div class="mt-2">
<small id="recording-status" class="text-muted">点击开始录音</small>
</div>
</div>
</div>
<button type="submit" class="btn btn-success w-100" disabled id="upload-sample-btn">
<i class="fas fa-upload me-2"></i>上传语音样本
</button>
</form>
<!-- 样本播放区域 -->
<div id="sample-player" class="mt-3" style="display: none;">
<div class="alert alert-info">
<h6><i class="fas fa-headphones me-2"></i>你的语音样本:</h6>
<audio controls class="w-100 mt-2" id="sample-audio">
<source id="sample-audio-source" type="audio/wav">
</audio>
</div>
</div>
</div>
</div>
<!-- 步骤2语音识别 -->
<div class="col-lg-6 mb-4">
<div class="step-content" id="step-2-content">
<h5 class="text-info">
<i class="fas fa-text-width me-2"></i>步骤2语音识别结果
</h5>
<p class="text-muted">AI识别出你说的内容这将用于语音克隆训练</p>
<div id="recognition-result" style="display: none;">
<div class="mb-3">
<label class="form-label">识别的文本内容:</label>
<textarea class="form-control" id="recognized-text" rows="3"
placeholder="语音识别结果将显示在这里..."></textarea>
<div class="form-text">你可以手动修正识别错误的文字</div>
</div>
<div class="d-flex justify-content-between">
<small class="text-success">
<i class="fas fa-check-circle me-1"></i>识别完成
</small>
<button class="btn btn-outline-primary btn-sm" onclick="goToStep(3)">
下一步:克隆生成 <i class="fas fa-arrow-right ms-1"></i>
</button>
</div>
</div>
<div id="recognition-waiting" class="text-center text-muted">
<i class="fas fa-clock fa-2x mb-2"></i>
<p>等待上传语音样本...</p>
</div>
</div>
</div>
<!-- 步骤3语音克隆生成 -->
<div class="col-lg-6 mb-4">
<div class="step-content" id="step-3-content">
<h5 class="text-warning">
<i class="fas fa-magic me-2"></i>步骤3克隆你的声音
</h5>
<p class="text-muted">让AI用你的声音说新的话</p>
<form id="clone-generation-form">
<div class="mb-3">
<label class="form-label">想让AI用你的声音说什么</label>
<textarea class="form-control" id="clone-text" rows="3"
placeholder="例如你好我是AI克隆的声音听起来像真的一样">你好我是AI克隆的声音听起来像真的一样</textarea>
</div>
<div class="row mb-3">
<div class="col-6">
<label class="form-label">随机种子</label>
<div class="input-group">
<input type="number" class="form-control" id="clone-seed" value="42">
<button type="button" class="btn btn-outline-secondary" id="clone-random-seed">
<i class="fas fa-dice"></i>
</button>
</div>
</div>
<div class="col-6">
<label class="form-label">克隆质量</label>
<select class="form-select">
<option>高质量(推荐)</option>
</select>
</div>
</div>
<button type="submit" class="btn btn-warning w-100" disabled id="generate-clone-btn">
<i class="fas fa-magic me-2"></i>生成克隆语音
</button>
</form>
</div>
</div>
<!-- 步骤4效果对比 -->
<div class="col-lg-6 mb-4">
<div class="step-content" id="step-4-content">
<h5 class="text-success">
<i class="fas fa-balance-scale me-2"></i>步骤4效果对比
</h5>
<p class="text-muted">对比原声和克隆声音的效果</p>
<div id="comparison-result" style="display: none;">
<div class="row">
<div class="col-6">
<h6><i class="fas fa-user me-2"></i>原声样本</h6>
<audio controls class="w-100" id="original-audio">
<source id="original-audio-source" type="audio/wav">
</audio>
<small class="text-muted">你录制的原始声音</small>
</div>
<div class="col-6">
<h6><i class="fas fa-robot me-2"></i>克隆声音</h6>
<audio controls class="w-100" id="cloned-audio">
<source id="cloned-audio-source" type="audio/wav">
</audio>
<small class="text-muted">AI克隆的声音</small>
</div>
</div>
<div class="mt-3 p-3 bg-light rounded">
<h6><i class="fas fa-star me-2"></i>给克隆效果打分:</h6>
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="rating" id="rating1">
<label class="btn btn-outline-warning" for="rating1">1★</label>
<input type="radio" class="btn-check" name="rating" id="rating2">
<label class="btn btn-outline-warning" for="rating2">2★</label>
<input type="radio" class="btn-check" name="rating" id="rating3">
<label class="btn btn-outline-warning" for="rating3">3★</label>
<input type="radio" class="btn-check" name="rating" id="rating4">
<label class="btn btn-outline-warning" for="rating4">4★</label>
<input type="radio" class="btn-check" name="rating" id="rating5">
<label class="btn btn-outline-warning" for="rating5">5★</label>
</div>
</div>
</div>
<div id="comparison-waiting" class="text-center text-muted">
<i class="fas fa-hourglass-half fa-2x mb-2"></i>
<p>等待生成克隆语音...</p>
</div>
</div>
</div>
</div>
<!-- 重新开始按钮 -->
<div class="text-center mt-4">
<button class="btn btn-outline-primary" onclick="resetWorkflow()">
<i class="fas fa-redo me-2"></i>重新开始克隆流程
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 高级功能区域 -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5 class="card-title">
<i class="fas fa-cogs me-2"></i>高级功能
<button class="btn btn-outline-secondary btn-sm float-end" type="button" data-bs-toggle="collapse" data-bs-target="#advanced-features">
<i class="fas fa-chevron-down"></i>
</button>
</h5>
<div class="collapse" id="advanced-features">
<div class="row">
<!-- 预训练音色测试 -->
<div class="col-lg-6 mb-4">
<h6 class="text-secondary">预训练音色测试</h6>
<form id="preset-voice-form">
<div class="mb-3">
<textarea class="form-control" id="preset-text" rows="2"
placeholder="输入要转换成语音的文字...">今天天气真不错,适合出门散步。</textarea>
</div>
<div class="mb-3">
<select class="form-select" id="preset-voice">
<option value="中文女">中文女</option>
</select>
</div>
<button type="submit" class="btn btn-secondary btn-sm">
<i class="fas fa-play me-2"></i>生成语音
</button>
</form>
<div id="preset-result" class="mt-2" style="display: none;">
<audio controls class="w-100">
<source id="preset-audio-source" type="audio/wav">
</audio>
</div>
</div>
<!-- 自然语言控制测试 -->
<div class="col-lg-6 mb-4">
<h6 class="text-secondary">自然语言控制</h6>
<form id="natural-control-form">
<div class="mb-3">
<textarea class="form-control" id="natural-text" rows="2"
placeholder="输入要合成的文字...">这是自然语言控制测试。</textarea>
</div>
<div class="mb-3">
<input class="form-control" id="natural-instruction"
placeholder="语音指令,如:请用温柔甜美的女声朗读"
value="请用温柔甜美的女声朗读">
</div>
<button type="submit" class="btn btn-secondary btn-sm">
<i class="fas fa-magic me-2"></i>生成语音
</button>
</form>
<div id="natural-result" class="mt-2" style="display: none;">
<audio controls class="w-100">
<source id="natural-audio-source" type="audio/wav">
</audio>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 操作日志 -->
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5 class="card-title">
<i class="fas fa-history me-2"></i>操作日志
<button class="btn btn-outline-secondary btn-sm float-end" id="clear-log">
<i class="fas fa-trash me-1"></i>清空
</button>
</h5>
<div id="test-log" class="border rounded p-3" style="height: 300px; overflow-y: auto; background-color: #f8f9fa;">
<p class="text-muted">操作记录将显示在这里...</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Loading Modal -->
<div class="modal fade" id="loadingModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body text-center py-4">
<div class="spinner-border text-primary mb-3" role="status"></div>
<h5 id="loading-message">正在处理中...</h5>
<p id="loading-detail" class="text-muted">请稍候...</p>
</div>
</div>
</div>
</div>
<!-- 添加步骤指示器样式 -->
<style>
.step-indicator {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
}
.step-circle {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #e9ecef;
color: #6c757d;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
margin-bottom: 8px;
transition: all 0.3s ease;
}
.step-indicator.active .step-circle {
background-color: #0d6efd;
color: white;
}
.step-indicator.completed .step-circle {
background-color: #198754;
color: white;
}
.step-label {
font-size: 0.9rem;
text-align: center;
color: #6c757d;
}
.step-indicator.active .step-label {
color: #0d6efd;
font-weight: 600;
}
.step-indicator.completed .step-label {
color: #198754;
font-weight: 600;
}
.step-line {
flex: 1;
height: 2px;
background-color: #e9ecef;
margin: 20px 0;
position: relative;
z-index: 1;
}
.step-line.completed {
background-color: #198754;
}
@media (max-width: 768px) {
.step-indicator {
flex-direction: row;
align-items: center;
margin-bottom: 10px;
}
.step-circle {
margin-bottom: 0;
margin-right: 10px;
}
}
</style>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/voice_test.js') }}"></script>
{% endblock %}