diff --git a/apps/worker/video_processing/render_adapter.py b/apps/worker/video_processing/render_adapter.py index f0fd6192e..42ced1315 100755 --- a/apps/worker/video_processing/render_adapter.py +++ b/apps/worker/video_processing/render_adapter.py @@ -465,7 +465,7 @@ class RenderAdapter: 失败不阻断主流程,返回 None。 """ try: - from services.asr_service_factory import get_asr_service + from apps.worker.services.asr_service_factory import get_asr_service return get_asr_service() except Exception as e: diff --git a/apps/worker/video_processing/unified_render_service.py b/apps/worker/video_processing/unified_render_service.py index 57d8e5b2e..9b07501a9 100755 --- a/apps/worker/video_processing/unified_render_service.py +++ b/apps/worker/video_processing/unified_render_service.py @@ -679,20 +679,40 @@ class UnifiedRenderService: len(top_text), ) # 方式B:voice_id + 自动字幕 → 字幕对齐配音(预设配音模式) - elif top_voice_id and subtitle_cfg.get("auto_generated", False) and self.asr_service is not None: - tts_cfg = { - "enabled": True, - "voice_id": top_voice_id, - "text": "", - "align_mode": "subtitle", - "overlap_mode": "replace", - } - use_subtitle_align = True - logger.info( - "[unified-render] 检测到预设配音+自动字幕,使用字幕对齐模式: plan_id=%s voice_id=%s", - self.plan.id, - top_voice_id, - ) + # ASR 可用时走字幕对齐模式,不可用时降级为整段配音 + elif top_voice_id and subtitle_cfg.get("auto_generated", False): + if self.asr_service is not None: + # 字幕对齐模式 + tts_cfg = { + "enabled": True, + "voice_id": top_voice_id, + "text": "", + "align_mode": "subtitle", + "overlap_mode": "replace", + } + use_subtitle_align = True + logger.info( + "[unified-render] 检测到预设配音+自动字幕,使用字幕对齐模式: plan_id=%s voice_id=%s", + self.plan.id, + top_voice_id, + ) + else: + # 降级:整段配音(预览模式 ASR 不可用时) + # 拼接字幕文本作为配音内容 + subtitle_text_content = subtitle_cfg.get("text", "") or "" + tts_cfg = { + "enabled": True, + "voice_id": top_voice_id, + "text": subtitle_text_content, + "align_mode": "full", + "overlap_mode": "replace", + } + logger.info( + "[unified-render] ASR 不可用,降级为整段配音模式: plan_id=%s voice_id=%s text_len=%d", + self.plan.id, + top_voice_id, + len(subtitle_text_content), + ) # 兼容前端顶层字段:voice_id / custom_text / voice_clone_profile_id # 前端一键生成页面传 config.voice_id + config.custom_text,