mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-23 07:33:53 +08:00
55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
from abc import ABC, abstractmethod
|
|
from typing import Optional, Tuple, List
|
|
import opuslib_next
|
|
from config.logger import setup_logging
|
|
|
|
TAG = __name__
|
|
logger = setup_logging()
|
|
|
|
|
|
class ASRProviderBase(ABC):
|
|
def __init__(self):
|
|
self.audio_format = "opus"
|
|
|
|
@abstractmethod
|
|
def save_audio_to_file(self, pcm_data: List[bytes], session_id: str) -> str:
|
|
"""PCM数据保存为WAV文件"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def speech_to_text(
|
|
self, opus_data: List[bytes], session_id: str
|
|
) -> Tuple[Optional[str], Optional[str]]:
|
|
"""将语音数据转换为文本"""
|
|
pass
|
|
|
|
def set_audio_format(self, format: str) -> None:
|
|
"""设置音频格式"""
|
|
self.audio_format = format
|
|
|
|
@staticmethod
|
|
def decode_opus(opus_data: List[bytes]) -> bytes:
|
|
"""将Opus音频数据解码为PCM数据"""
|
|
try:
|
|
decoder = opuslib_next.Decoder(16000, 1) # 16kHz, 单声道
|
|
pcm_data = []
|
|
buffer_size = 960 # 每次处理960个采样点
|
|
|
|
for opus_packet in opus_data:
|
|
try:
|
|
# 使用较小的缓冲区大小进行处理
|
|
pcm_frame = decoder.decode(opus_packet, buffer_size)
|
|
if pcm_frame:
|
|
pcm_data.append(pcm_frame)
|
|
except opuslib_next.OpusError as e:
|
|
logger.bind(tag=TAG).warning(f"Opus解码错误,跳过当前数据包: {e}")
|
|
continue
|
|
except Exception as e:
|
|
logger.bind(tag=TAG).error(f"音频处理错误: {e}", exc_info=True)
|
|
continue
|
|
|
|
return pcm_data
|
|
except Exception as e:
|
|
logger.bind(tag=TAG).error(f"音频解码过程发生错误: {e}", exc_info=True)
|
|
return []
|