diff --git a/apps/worker/worker_app/tasks/generation.py b/apps/worker/worker_app/tasks/generation.py index e422739e9..a5a11fc1d 100644 --- a/apps/worker/worker_app/tasks/generation.py +++ b/apps/worker/worker_app/tasks/generation.py @@ -1124,14 +1124,14 @@ def _render_video( bgm_config: dict | None = None, voice_ids: list[str] | None = None, custom_title: str = "", -) -> tuple[Path, float]: +) -> tuple[Path, float, str]: """渲染视频(含配音混音)。 - 使用 RenderAdapter 统一渲染入口,复用 BGM/ASR/分辨率/缩略图逻辑。 + 使用 RenderAdapter 统一渲染入口,复用 BGM/ASR/分辨率/封面抽取逻辑。 Args: Returns: - (output_path, render_duration) + (output_path, render_duration, cover_url) """ if not downloaded_videos: raise RuntimeError(f"素材下载结果为空: task_id={task_id}") @@ -1259,8 +1259,9 @@ def _render_video( # 配音素材库音频已在统一渲染引擎内部通过 audio 图层混音处理 output_path = render_output_path + cover_url = getattr(render_result, "cover_url", "") or "" - return output_path, render_duration + return output_path, render_duration, cover_url def _upload_and_record( @@ -1271,6 +1272,7 @@ def _upload_and_record( editing_mode, user_id: str = "", video_name: str = "", + thumbnail_url: str = "", ) -> tuple[str, float, int, int]: """上传 OSS、创建视频记录并查重。 @@ -1531,7 +1533,7 @@ def generate_video(self, task_id: str) -> dict: else: _resolved_resolution = task_info.get("resolution", "") - output_path, render_duration = _render_video( + output_path, render_duration, cover_url = _render_video( task_id=task_id, downloaded_videos=downloaded_videos, voice_path=audio_path, @@ -1551,6 +1553,32 @@ def generate_video(self, task_id: str) -> dict: gen_task.append_log("渲染", f"渲染完成, 时长={render_duration:.1f}s") _flush_logs(task_id, gen_task) + # 持久化封面 URL 到 GenerationTask(统一封面管道:从渲染后视频抽帧) + if cover_url: + try: + _cover_session = SessionLocal() + try: + from packages.adapters.sqlalchemy_impl.models import GenerationTaskModel + _cover_model = _cover_session.query(GenerationTaskModel).filter( + GenerationTaskModel.id == task_id + ).first() + if _cover_model: + _cover_model.cover_url = cover_url + _cover_session.commit() + logger.info( + "[task_id=%s] 封面URL已持久化: %s", + task_id, + cover_url[:80], + ) + finally: + _cover_session.close() + except Exception as cover_err: + logger.warning( + "[task_id=%s] 封面URL持久化失败(不影响主流程): %s", + task_id, + cover_err, + ) + _update_task_progress(task_id, 80, "渲染完成") # ── 4. 上传 OSS + 查重记录 ─────────────────────────────────────── @@ -1563,6 +1591,7 @@ def generate_video(self, task_id: str) -> dict: editing_mode=editing_mode, user_id=user_id, video_name=task_info.get("video_title", ""), + thumbnail_url=cover_url, ) if gen_task: