支持语音识别与tts文字转语音

main.py
<import webview
import time
class Api:
def on_speech_result(self, result):
"""处理从前端接收的语音识别结果"""
print(f"语音识别结果: {result}")
# 可以在这里添加后续处理逻辑
return result
if __name__ == '__main__':
# 创建API实例
api = Api()
# 创建窗口
window = webview.create_window(
title='带音色选择的语音功能演示',
url='index.html',
width=900,
height=700,
resizable=True,
js_api=api
)
# 启动pywebview
webview.start(debug=True)
index.html<!DOCTYPE html>
<html>
<head>
<title>带音色选择的语音功能演示</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
.controls { margin: 20px 0; padding: 20px; border: 1px solid #eee; border-radius: 8px; }
button { padding: 10px 20px; margin: 5px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #0056b3; }
#result { margin: 20px 0; padding: 10px; border: 1px solid #ccc; min-height: 50px; border-radius: 4px; }
.form-group { margin: 15px 0; }
select, input[type="text"] { padding: 8px; width: 100%; max-width: 500px; border: 1px solid #ddd; border-radius: 4px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
</style>
</head>
<body>
<h1>Web Speech API 演示(带音色选择)</h1>
<div class="controls">
<h3>语音识别</h3>
<button onclick="startRecognition()">开始语音识别</button>
<button onclick="stopRecognition()">停止语音识别</button>
<div id="result">识别结果将显示在这里...</div>
<h3>语音合成</h3>
<div class="form-group">
<label for="voiceSelect">选择音色:</label>
<select id="voiceSelect"></select>
</div>
<div class="form-group">
<label for="textToSpeak">输入要合成的文本:</label>
<input type="text" id="textToSpeak" placeholder="请输入文字..." value="你好,这是一个带音色选择的语音合成示例">
</div>
<div class="form-group">
<label>语速:</label>
<input type="range" id="rate" min="0.5" max="2" step="0.1" value="1">
<span id="rateValue">1</span>
</div>
<button onclick="speakText(document.getElementById('textToSpeak').value)">开始语音合成</button>
<button onclick="cancelSpeech()">取消合成</button>
</div>
<div id="status" style="margin-top: 20px; color: #666;">状态: 就绪</div>
<script>
// 语音识别相关变量
let recognition;
let isRecognizing = false;
// 语音合成相关变量
let voices = [];
// 页面加载完成后初始化
window.onload = function() {
// 初始化语音识别
initRecognition();
// 初始化语音合成
initSpeechSynthesis();
// 监听语速滑块变化
document.getElementById('rate').addEventListener('input', function() {
document.getElementById('rateValue').textContent = this.value;
});
};
// 初始化语音识别
function initRecognition() {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert("您的浏览器不支持语音识别功能");
return null;
}
recognition = new SpeechRecognition();
recognition.continuous = false;
recognition.interimResults = false;
recognition.lang = 'zh-CN';
recognition.onstart = function() {
document.getElementById('status').textContent = '状态: 正在识别...';
isRecognizing = true;
};
recognition.onresult = function(event) {
const transcript = event.results[0][0].transcript;
document.getElementById('result').textContent = transcript;
document.getElementById('textToSpeak').value = transcript;
window.pywebview.api.on_speech_result(transcript);
};
recognition.onend = function() {
document.getElementById('status').textContent = '状态: 识别结束';
isRecognizing = false;
};
recognition.onerror = function(event) {
document.getElementById('status').textContent = `错误: ${event.error}`;
isRecognizing = false;
};
return recognition;
}
// 初始化语音合成
function initSpeechSynthesis() {
if (!('speechSynthesis' in window)) {
alert("您的浏览器不支持语音合成功能");
return;
}
// 当可用语音列表加载完成时更新选择器
function loadVoices() {
voices = window.speechSynthesis.getVoices();
const voiceSelect = document.getElementById('voiceSelect');
// 清空现有选项
voiceSelect.innerHTML = '';
// 添加所有可用语音
voices.forEach((voice, index) => {
const option = document.createElement('option');
option.value = index;
// 显示语音名称和语言
option.textContent = `${voice.name} (${voice.lang})`;
voiceSelect.appendChild(option);
});
}
// 不同浏览器可能在不同时机加载语音列表
window.speechSynthesis.onvoiceschanged = loadVoices;
// 主动触发一次加载
loadVoices();
}
// 开始语音识别
function startRecognition() {
if (isRecognizing) return;
if (!recognition) {
recognition = initRecognition();
if (!recognition) return;
}
recognition.start();
}
// 停止语音识别
function stopRecognition() {
if (isRecognizing && recognition) {
recognition.stop();
}
}
// 语音合成
function speakText(text) {
if (!text) return;
if (!('speechSynthesis' in window)) return;
// 停止任何正在进行的语音
window.speechSynthesis.cancel();
// 获取选中的语音
const voiceIndex = document.getElementById('voiceSelect').value;
const selectedVoice = voices[voiceIndex];
// 创建语音实例
const utterance = new SpeechSynthesisUtterance(text);
// 设置选中的语音
if (selectedVoice) {
utterance.voice = selectedVoice;
}
// 设置其他参数
utterance.lang = 'zh-CN';
utterance.rate = parseFloat(document.getElementById('rate').value); // 语速
utterance.pitch = 1; // 音调
utterance.volume = 1; // 音量
// 开始合成
window.speechSynthesis.speak(utterance);
document.getElementById('status').textContent = `状态: 正在用 ${selectedVoice.name} 合成语音...`;
utterance.onend = function() {
document.getElementById('status').textContent = '状态: 合成完成';
};
}
// 取消语音合成
function cancelSpeech() {
if ('speechSynthesis' in window) {
window.speechSynthesis.cancel();
document.getElementById('status').textContent = '状态: 已取消合成';
}
}
</script>
</body>
</html>
网友回复


