真实接口预热

This commit is contained in:
yinsx
2026-01-04 09:58:26 +08:00
parent b56492f80f
commit 2bd183463d
10 changed files with 386 additions and 207 deletions

View File

@ -79,9 +79,10 @@ class TextToBlendShapesService:
yield {'type': 'error', 'message': '文本为空'}
return
# 测试:只处理第一句
sentences = sentences[:1]
print(f"[测试模式] 只处理第一句: {sentences[0]}")
# 确保 is_continuation 长度与 sentences 匹配
if len(self.is_continuation) != len(sentences):
print(f"[警告] is_continuation 长度 ({len(self.is_continuation)}) 与 sentences 长度 ({len(sentences)}) 不匹配,重置")
self.is_continuation = [False] * len(sentences)
yield {
'type': 'status',
@ -92,9 +93,10 @@ class TextToBlendShapesService:
}
# 打印句子列表用于调试
print(f"[调试] 发送给前端的句子列表:")
print(f"[调试] 发送给前端的句子列表 (共{len(sentences)}句, is_continuation长度={len(self.is_continuation)}):")
for i, s in enumerate(sentences):
print(f" [{i}] {s}")
cont = self.is_continuation[i] if i < len(self.is_continuation) else False
print(f" [{i}] {s} (连续={cont})")
# 使用队列来收集处理完成的句子
result_queue = queue.Queue()
@ -113,70 +115,85 @@ class TextToBlendShapesService:
result_queue.put((index, 'error', None, str(e)))
# 提交所有句子到线程池并发处理(增加并发数以加速)
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
for index, sentence in enumerate(sentences):
executor.submit(process_and_queue, index, sentence)
print(f"[调试] 准备提交 {len(sentences)} 个句子到线程池")
try:
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for index, sentence in enumerate(sentences):
future = executor.submit(process_and_queue, index, sentence)
futures.append(future)
print(f"[调试] 已提交句子 {index}: {sentence[:20]}...")
# 按顺序从队列中取出结果并推送
completed = {}
next_index = 0
total_frames = 0
cumulative_time = 0.0 # 累计时间,用于连续句子
# 按顺序从队列中取出结果并推送
completed = {}
next_index = 0
total_frames = 0
cumulative_time = 0.0 # 累计时间,用于连续句子
while next_index < len(sentences):
# 如果下一个句子还没完成,等待队列
if next_index not in completed:
yield {
'type': 'status',
'stage': 'processing',
'sentence_index': next_index,
'sentences': len(sentences),
'message': f'正在处理 {next_index + 1}/{len(sentences)}'
}
print(f"[调试] 开始主循环,共 {len(sentences)} 个句子")
while next_index < len(sentences):
print(f"[调试] 主循环 next_index={next_index}, completed keys={list(completed.keys())}")
# 如果下一个句子还没完成,等待队列
if next_index not in completed:
yield {
'type': 'status',
'stage': 'processing',
'sentence_index': next_index,
'sentences': len(sentences),
'message': f'正在处理 {next_index + 1}/{len(sentences)}'
}
# 从队列中获取结果
while next_index not in completed:
try:
index, status, frames, error = result_queue.get(timeout=1)
completed[index] = (status, frames, error)
print(f"[主线程] 收到句子 {index} 的处理结果")
except queue.Empty:
continue
# 从队列中获取结果
while next_index not in completed:
try:
index, status, frames, error = result_queue.get(timeout=1)
completed[index] = (status, frames, error)
print(f"[主线程] 收到句子 {index} 的处理结果, status={status}")
except queue.Empty:
print(f"[调试] 队列为空,继续等待 next_index={next_index}")
continue
# 推送下一个句子的帧
status, frames, error = completed[next_index]
if status == 'error':
yield {'type': 'error', 'message': f'句子 {next_index} 处理失败: {error}'}
return
# 推送下一个句子的帧
status, frames, error = completed[next_index]
print(f"[主线程] 句子 {next_index} 状态: {status}, 帧数: {len(frames) if frames else 0}, 错误: {error}")
if status == 'error':
print(f"[错误] 句子 {next_index} 处理失败: {error}")
yield {'type': 'error', 'message': f'句子 {next_index} 处理失败: {error}'}
return
# 如果是连续句子,调整时间码使其无缝衔接
is_continuation = self.is_continuation[next_index] if next_index < len(self.is_continuation) else False
# 如果是连续句子,调整时间码使其无缝衔接
is_continuation = self.is_continuation[next_index] if next_index < len(self.is_continuation) else False
print(f"[主线程] 正在推送句子 {next_index}{len(frames)}{'(连续)' if is_continuation else ''}")
print(f"[调试] 句子 {next_index} 对应文本: {sentences[next_index] if next_index < len(sentences) else 'N/A'}")
print(f"[主线程] 正在推送句子 {next_index}/{len(sentences)-1}{len(frames)}{'(连续)' if is_continuation else ''}")
print(f"[调试] 句子 {next_index} 对应文本: {sentences[next_index] if next_index < len(sentences) else 'N/A'}")
# 如果不是连续句子,重置累计时间
if not is_continuation and next_index > 0:
cumulative_time = 0.0
# 如果不是连续句子,重置累计时间
if not is_continuation and next_index > 0:
cumulative_time = 0.0
for frame in frames:
# 调整时间码:从累计时间开始
frame['timeCode'] = cumulative_time + frame['timeCode']
frame['sentenceIndex'] = next_index
total_frames += 1
yield {'type': 'frame', 'frame': frame}
for frame in frames:
# 调整时间码:从累计时间开始
frame['timeCode'] = cumulative_time + frame['timeCode']
frame['sentenceIndex'] = next_index
total_frames += 1
yield {'type': 'frame', 'frame': frame}
# 更新累计时间为当前句子的最后一帧时间
if frames:
cumulative_time = frames[-1]['timeCode']
# 更新累计时间为当前句子的最后一帧时间
if frames:
cumulative_time = frames[-1]['timeCode']
next_index += 1
next_index += 1
print(f"[主线程] 流式传输完成,共 {total_frames}")
yield {
'type': 'end',
'frames': total_frames
}
print(f"[主线程] 流式传输完成,共 {total_frames},处理了 {next_index} 个句子")
yield {
'type': 'end',
'frames': total_frames
}
except Exception as e:
import traceback
print(f"[错误] 流式处理异常: {e}")
traceback.print_exc()
yield {'type': 'error', 'message': f'流式处理异常: {str(e)}'}
def _process_sentence(self, sentence, output_dir, index):
"""处理单个句子: TTS -> A2F -> 解析"""
@ -286,6 +303,9 @@ class TextToBlendShapesService:
# 12字以上前6字再6字剩下的
parts = [first[:6], first[6:12], first[12:]]
# 过滤空字符串
parts = [p for p in parts if p.strip()]
# 替换第一句为多个小句
sentences = parts + sentences[1:]
# 标记后续部分为连续播放
@ -293,18 +313,31 @@ class TextToBlendShapesService:
print(f"[拆分优化] 第一句({length}字)拆分为{len(parts)}部分: {[len(p) for p in parts]} - 连续播放")
if not max_sentence_length or max_sentence_length <= 0:
print(f"[拆分] 最终句子数: {len(sentences)}, is_continuation长度: {len(self.is_continuation)}")
return sentences
limited = []
for sentence in sentences:
new_is_continuation = []
for i, sentence in enumerate(sentences):
if len(sentence) <= max_sentence_length:
limited.append(sentence)
new_is_continuation.append(self.is_continuation[i] if i < len(self.is_continuation) else False)
continue
start = 0
first_part = True
while start < len(sentence):
limited.append(sentence[start:start + max_sentence_length])
# 第一部分继承原来的 is_continuation后续部分标记为连续
if first_part:
new_is_continuation.append(self.is_continuation[i] if i < len(self.is_continuation) else False)
first_part = False
else:
new_is_continuation.append(True)
start += max_sentence_length
self.is_continuation = new_is_continuation
print(f"[拆分] 最终句子数: {len(limited)}, is_continuation长度: {len(self.is_continuation)}")
return limited
def _prepare_output_paths(self, output_dir: str = None, suffix: str = None):