diff --git a/apps/api/app/api/routes/cover_templates.py b/apps/api/app/api/routes/cover_templates.py index a8782cc8c..5c6d8402c 100644 --- a/apps/api/app/api/routes/cover_templates.py +++ b/apps/api/app/api/routes/cover_templates.py @@ -7,7 +7,6 @@ API: DELETE /api/v1/cover-templates/{id} - 删除自定义模板(系统模板不可删) """ - import logging from typing import Any diff --git a/apps/api/app/api/routes/generation_cover.py b/apps/api/app/api/routes/generation_cover.py index ddc63df4e..c9bd2bf4d 100644 --- a/apps/api/app/api/routes/generation_cover.py +++ b/apps/api/app/api/routes/generation_cover.py @@ -86,7 +86,9 @@ def generate_cover( # 第二步:如果还没有,通过 generation_task_id 查找预览任务的产物 if not rendered_storage_key: generation_task_id = (plan.config or {}).get("generation_task_id", "") - logger.info("[封面生成] 步骤2: 通过 generation_task_id 查找: plan_id=%s task_id=%s", plan_id, generation_task_id) + logger.info( + "[封面生成] 步骤2: 通过 generation_task_id 查找: plan_id=%s task_id=%s", plan_id, generation_task_id + ) if generation_task_id: try: gen_task_repo = SQLAlchemyGenerationTaskRepository(db) @@ -170,7 +172,8 @@ def generate_cover( # MediaKit 的 HTTP 客户端会规范化 URL 导致 404 if primary_video_url: import re as _re - primary_video_url = _re.sub(r'(? 0: - results.append({ - "local_path": output_path, - "frame_time": round(frame_time, 2), - }) + results.append( + { + "local_path": output_path, + "frame_time": round(frame_time, 2), + } + ) else: Path(output_path).unlink(missing_ok=True) except Exception as e: @@ -256,14 +264,18 @@ def extract_and_upload_cover_frames( url = upload_to_oss(local_path, storage_key) if url: - results.append({ - "image_url": url, - "frame_time": frame_time, - "storage_key": storage_key, - }) + results.append( + { + "image_url": url, + "frame_time": frame_time, + "storage_key": storage_key, + } + ) logger.info( "封面候选帧上传成功: plan_id=%s idx=%d frame_time=%.2f", - plan_id, idx, frame_time, + plan_id, + idx, + frame_time, ) except Exception as e: logger.warning("封面候选帧上传失败: plan_id=%s idx=%d error=%s", plan_id, idx, e) diff --git a/apps/worker/worker_app/tasks/edit_plan_generation.py b/apps/worker/worker_app/tasks/edit_plan_generation.py index 0d740847c..58155e4ab 100644 --- a/apps/worker/worker_app/tasks/edit_plan_generation.py +++ b/apps/worker/worker_app/tasks/edit_plan_generation.py @@ -263,7 +263,8 @@ def _render_with_unified( plan.config = plan_config logger.info( "封面候选帧已写入 plan.config: plan_id=%s count=%d", - plan_id, len(result.cover_candidates), + plan_id, + len(result.cover_candidates), ) return _finalize_render_success( diff --git a/packages/shared/ai_service.py b/packages/shared/ai_service.py index efe7f7c0a..2ae55042e 100755 --- a/packages/shared/ai_service.py +++ b/packages/shared/ai_service.py @@ -379,18 +379,25 @@ def _extract_frames_with_ffmpeg( # 先用 ffprobe 获取视频时长 import subprocess as _subprocess + from packages.shared.ffmpeg_utils import FFPROBE_BIN duration = 30.0 # 默认假设 30 秒 try: probe_result = _subprocess.run( [ - FFPROBE_BIN, "-v", "error", - "-show_entries", "format=duration", - "-of", "default=noprint_wrappers=1:nokey=1", + FFPROBE_BIN, + "-v", + "error", + "-show_entries", + "format=duration", + "-of", + "default=noprint_wrappers=1:nokey=1", video_url, ], - capture_output=True, text=True, timeout=15, + capture_output=True, + text=True, + timeout=15, ) if probe_result.returncode == 0 and probe_result.stdout.strip(): duration = float(probe_result.stdout.strip()) @@ -400,7 +407,7 @@ def _extract_frames_with_ffmpeg( ratios = [i / (num_frames + 1) for i in range(1, num_frames + 1)] results = [] - for idx, ratio in enumerate(ratios): + for _idx, ratio in enumerate(ratios): frame_time = max(0.5, duration * ratio) tmp = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) tmp.close() @@ -409,11 +416,16 @@ def _extract_frames_with_ffmpeg( try: seek_str = f"{int(frame_time // 3600):02d}:{int((frame_time % 3600) // 60):02d}:{frame_time % 60:05.2f}" cmd = [ - FFMPEG_BIN, "-y", - "-ss", seek_str, - "-i", video_url, - "-vframes", "1", - "-q:v", "2", + FFMPEG_BIN, + "-y", + "-ss", + seek_str, + "-i", + video_url, + "-vframes", + "1", + "-q:v", + "2", output_path, ] run_ffmpeg(cmd, capture_output=True, timeout=timeout) @@ -475,6 +487,7 @@ def _call_ai_cover_service( # ai_frame / ai_regenerate - 使用 FFmpeg 本地抽帧 if primary_video_url: import re as _re + primary_video_url = _re.sub(r"(?