-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspeech_processor.py
More file actions
89 lines (74 loc) · 2.68 KB
/
speech_processor.py
File metadata and controls
89 lines (74 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""
Speech Processing Module for the Enhanced AGI Pipeline.
"""
import os
import tempfile
import pyttsx3
import whisper
from fastapi import UploadFile
from loguru import logger
class SpeechProcessor:
"""
A module for Speech-to-Text (STT) and Text-to-Speech (TTS) processing.
"""
def __init__(self):
"""
Initializes the Whisper model and the TTS engine.
"""
self.whisper_model = whisper.load_model("base")
try:
self.tts = pyttsx3.init()
logger.info("Speech processor (TTS) initialized successfully.")
except Exception as e: # pylint: disable=broad-exception-caught
self.tts = None
logger.error(f"Failed to initialize TTS engine: {e}")
logger.info("Whisper model loaded successfully.")
def speech_to_text(self, audio_file: UploadFile) -> str:
"""
Converts speech from an uploaded audio file to text.
Args:
audio_file (UploadFile): The uploaded audio file.
Returns:
str: The transcribed text.
"""
logger.debug(f"Transcribing audio file: {audio_file.filename}")
# Save UploadFile to a temporary file
suffix = os.path.splitext(audio_file.filename)[1]
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
tmp.write(audio_file.file.read())
tmp_path = tmp.name
try:
result = self.whisper_model.transcribe(tmp_path)
return result["text"]
finally:
if os.path.exists(tmp_path):
os.remove(tmp_path)
def text_to_speech(self, text: str) -> None:
"""
Converts text to speech and plays it.
Args:
text (str): The text to synthesize.
Raises:
ValueError: If the text is empty.
"""
if not text.strip():
raise ValueError("Text cannot be empty.")
if self.tts is None:
logger.warning("TTS engine not available. Skipping speech synthesis.")
return
try:
logger.debug(f"Synthesizing text: {text}")
self.tts.say(text)
self.tts.runAndWait()
except Exception as e: # pylint: disable=broad-exception-caught
logger.error(f"TTS synthesis failed: {e}")
def __del__(self):
"""
Cleans up the TTS engine resources.
"""
if hasattr(self, "tts") and self.tts:
try:
self.tts.stop()
except Exception as e: # pylint: disable=broad-exception-caught
# Use logging instead of 'pass' to satisfy Bandit B110
logger.debug(f"Could not stop TTS engine: {e}")