mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 10:03:54 +08:00
fix:重写 audio_to_opus_data_stream 方法,让音频文件处理使用独立编码器,避免与 TTS 流编码器冲突。
This commit is contained in:
@@ -6,6 +6,7 @@ import queue
|
|||||||
import asyncio
|
import asyncio
|
||||||
import traceback
|
import traceback
|
||||||
import websockets
|
import websockets
|
||||||
|
from typing import Callable, Any
|
||||||
from asyncio import Task
|
from asyncio import Task
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
from core.utils import opus_encoder_utils
|
from core.utils import opus_encoder_utils
|
||||||
@@ -383,6 +384,24 @@ class TTSProvider(TTSProviderBase):
|
|||||||
finally:
|
finally:
|
||||||
self._monitor_task = None
|
self._monitor_task = None
|
||||||
|
|
||||||
|
def audio_to_opus_data_stream(
|
||||||
|
self, audio_file_path, callback: Callable[[Any], Any] = None
|
||||||
|
):
|
||||||
|
"""重写父类方法:使用独立的临时编码器处理音频文件,避免与TTS流式编码器并发冲突。
|
||||||
|
双流式TTS中,monitor任务在event loop线程接收TTS音频并使用self.opus_encoder编码,
|
||||||
|
同时tts_text_priority_thread处理音乐文件也使用self.opus_encoder,
|
||||||
|
共享的encoder.buffer非线程安全,并发访问会导致SILK resampler断言失败。
|
||||||
|
"""
|
||||||
|
from core.utils.util import audio_to_data_stream
|
||||||
|
|
||||||
|
return audio_to_data_stream(
|
||||||
|
audio_file_path,
|
||||||
|
is_opus=True,
|
||||||
|
callback=callback,
|
||||||
|
sample_rate=self.conn.sample_rate,
|
||||||
|
opus_encoder=None,
|
||||||
|
)
|
||||||
|
|
||||||
def to_tts(self, text: str) -> list:
|
def to_tts(self, text: str) -> list:
|
||||||
"""非流式生成音频数据,用于生成音频及测试场景"""
|
"""非流式生成音频数据,用于生成音频及测试场景"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import time
|
|||||||
import queue
|
import queue
|
||||||
import asyncio
|
import asyncio
|
||||||
import traceback
|
import traceback
|
||||||
|
from typing import Callable, Any
|
||||||
from asyncio import Task
|
from asyncio import Task
|
||||||
import websockets
|
import websockets
|
||||||
import os
|
import os
|
||||||
@@ -463,6 +464,24 @@ class TTSProvider(TTSProviderBase):
|
|||||||
finally:
|
finally:
|
||||||
self._monitor_task = None
|
self._monitor_task = None
|
||||||
|
|
||||||
|
def audio_to_opus_data_stream(
|
||||||
|
self, audio_file_path, callback: Callable[[Any], Any] = None
|
||||||
|
):
|
||||||
|
"""重写父类方法:使用独立的临时编码器处理音频文件,避免与TTS流式编码器并发冲突。
|
||||||
|
双流式TTS中,monitor任务在event loop线程接收TTS音频并使用self.opus_encoder编码,
|
||||||
|
同时tts_text_priority_thread处理音乐文件也使用self.opus_encoder,
|
||||||
|
共享的encoder.buffer非线程安全,并发访问会导致SILK resampler断言失败。
|
||||||
|
"""
|
||||||
|
from core.utils.util import audio_to_data_stream
|
||||||
|
|
||||||
|
return audio_to_data_stream(
|
||||||
|
audio_file_path,
|
||||||
|
is_opus=True,
|
||||||
|
callback=callback,
|
||||||
|
sample_rate=self.conn.sample_rate,
|
||||||
|
opus_encoder=None,
|
||||||
|
)
|
||||||
|
|
||||||
def to_tts(self, text: str) -> list:
|
def to_tts(self, text: str) -> list:
|
||||||
"""非流式TTS处理,用于测试及保存音频文件的场景"""
|
"""非流式TTS处理,用于测试及保存音频文件的场景"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -683,6 +683,20 @@ class TTSProvider(TTSProviderBase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def audio_to_opus_data_stream(
|
||||||
|
self, audio_file_path, callback: Callable[[Any], Any] = None
|
||||||
|
):
|
||||||
|
"""重写父类方法:使用独立的临时编码器处理音频文件,避免与TTS流式编码器并发冲突。
|
||||||
|
双流式TTS中,monitor任务在event loop线程接收TTS音频并使用self.opus_encoder编码,
|
||||||
|
同时tts_text_priority_thread处理音乐文件也使用self.opus_encoder,
|
||||||
|
共享的encoder.buffer非线程安全,并发访问会导致SILK resampler断言失败。
|
||||||
|
"""
|
||||||
|
from core.utils.util import audio_to_data_stream
|
||||||
|
return audio_to_data_stream(
|
||||||
|
audio_file_path, is_opus=True, callback=callback,
|
||||||
|
sample_rate=self.conn.sample_rate, opus_encoder=None
|
||||||
|
)
|
||||||
|
|
||||||
def wav_to_opus_data_audio_raw_stream(self, raw_data_var, is_end=False, callback: Callable[[Any], Any]=None):
|
def wav_to_opus_data_audio_raw_stream(self, raw_data_var, is_end=False, callback: Callable[[Any], Any]=None):
|
||||||
return self.opus_encoder.encode_pcm_to_opus_stream(raw_data_var, is_end, callback=callback)
|
return self.opus_encoder.encode_pcm_to_opus_stream(raw_data_var, is_end, callback=callback)
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import hashlib
|
|||||||
import asyncio
|
import asyncio
|
||||||
import traceback
|
import traceback
|
||||||
import websockets
|
import websockets
|
||||||
|
from typing import Callable, Any
|
||||||
from asyncio import Task
|
from asyncio import Task
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
from core.utils import opus_encoder_utils
|
from core.utils import opus_encoder_utils
|
||||||
@@ -474,7 +475,25 @@ class TTSProvider(TTSProviderBase):
|
|||||||
logger.bind(tag=TAG).error(f"生成音频数据失败: {str(e)}")
|
logger.bind(tag=TAG).error(f"生成音频数据失败: {str(e)}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _build_base_request(self, status,text=" "):
|
def audio_to_opus_data_stream(
|
||||||
|
self, audio_file_path, callback: Callable[[Any], Any] = None
|
||||||
|
):
|
||||||
|
"""重写父类方法:使用独立的临时编码器处理音频文件,避免与TTS流式编码器并发冲突。
|
||||||
|
双流式TTS中,monitor任务在event loop线程接收TTS音频并使用self.opus_encoder编码,
|
||||||
|
同时tts_text_priority_thread处理音乐文件也使用self.opus_encoder,
|
||||||
|
共享的encoder.buffer非线程安全,并发访问会导致SILK resampler断言失败。
|
||||||
|
"""
|
||||||
|
from core.utils.util import audio_to_data_stream
|
||||||
|
|
||||||
|
return audio_to_data_stream(
|
||||||
|
audio_file_path,
|
||||||
|
is_opus=True,
|
||||||
|
callback=callback,
|
||||||
|
sample_rate=self.conn.sample_rate,
|
||||||
|
opus_encoder=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _build_base_request(self, status, text=" "):
|
||||||
"""构建基础请求结构"""
|
"""构建基础请求结构"""
|
||||||
return {
|
return {
|
||||||
"header": {
|
"header": {
|
||||||
|
|||||||
Reference in New Issue
Block a user