import logger import pyttsx3 from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QLabel from uas.io.base_io import BaseOutput, IOType, IOData from uas.io.outputs.text_output import HAS_TTS from uas.io.signals import io_signals class SpeechOutput(BaseOutput): def __init__(self): super().__init__("speech_output", [IOType.TEXT, IOType.SPEECH]) self._engine = None if HAS_TTS: self._init_tts() def _init_tts(self): try: self._engine = pyttsx3.init() self._engine.setProperty("rate", 180) self._engine.setProperty("volume", 0.9) logger.info("✅ TTS 引擎初始化成功") except Exception as e: logger.error(f"TTS 初始化失败: {e}") def render(self, data: IOData) -> None: text = str(data.processed or data.raw) self._tts_label.setText(f"朗读: {text[:80]}...") if not self._mute_btn.isChecked() and self._engine: try: self._engine.say(text) self._engine.runAndWait() io_signals.tts_finished.emit(text) except Exception as e: logger.error(f"TTS 朗读失败: {e}") # ───────────────────────────────────────────────────────────────── # 语音输出(TTS) # ───────────────────────────────────────────────────────────────── class SpeechOutputWidget(QWidget, SpeechOutput): """ 语音输出(TTS)组件 基于 pyttsx3,在独立 QThread 中朗读,不阻塞 UI """ def __init__(self, parent=None): QWidget.__init__(self, parent) SpeechOutput.__init__(self) self._build_ui() def _build_ui(self): layout = QVBoxLayout(self) layout.setContentsMargins(8, 8, 8, 8) title = QLabel("🔊 语音输出 (TTS)") title.setStyleSheet("font-weight: bold; font-size: 13px;") layout.addWidget(title) self._tts_label = QLabel("等待输出...") self._tts_label.setWordWrap(True) self._tts_label.setStyleSheet( "background:#e8f5e9; padding:6px; border-radius:4px;" ) layout.addWidget(self._tts_label) self._mute_btn = QPushButton("🔇 静音") self._mute_btn.setCheckable(True) layout.addWidget(self._mute_btn)