auto-save 2026-05-14 04:21 (~6)
This commit is contained in:
18
api/main.py
18
api/main.py
@@ -607,6 +607,7 @@ async def pipeline_analyze(
|
||||
frame_count: int = KEYFRAME_COUNT,
|
||||
target: FrameExtractTarget = "balanced",
|
||||
mode: FrameExtractMode = "replace",
|
||||
quality: FrameExtractQuality = "accurate",
|
||||
) -> None:
|
||||
"""阶段 2:拆音轨 + 抽关键帧。ASR/翻译是独立文案轨,不阻塞视觉素材流。"""
|
||||
job = JOBS[job_id]
|
||||
@@ -629,11 +630,11 @@ async def pipeline_analyze(
|
||||
|
||||
n = max(1, min(int(frame_count), 20))
|
||||
target_label = FRAME_TARGET_LABELS.get(target, FRAME_TARGET_LABELS["balanced"])
|
||||
quality_label = FRAME_QUALITY_LABELS.get(quality, FRAME_QUALITY_LABELS["accurate"])
|
||||
duration = max(float(job.duration or 1.0), 0.1)
|
||||
scan_fps = min(2.0, max(0.02, 180.0 / duration))
|
||||
estimated_scan_count = max(1, int(duration * scan_fps))
|
||||
scan_fps, scan_width, metric_width, estimated_scan_count = _scan_profile(duration, quality)
|
||||
|
||||
update(job, message=f"低清扫描候选 · {target_label} · 约 {estimated_scan_count} 帧…", progress=45)
|
||||
update(job, message=f"本地{quality_label}扫描 · {target_label} · 约 {estimated_scan_count} 帧…", progress=45)
|
||||
frames_dir = d / "frames"
|
||||
replacing = mode == "replace"
|
||||
existing_frames = list(job.frames) if not replacing else []
|
||||
@@ -648,7 +649,7 @@ async def pipeline_analyze(
|
||||
# 1) 低分辨率、低帧率扫描。扫描图只用于候选评分,最终不直接作为关键帧。
|
||||
run([
|
||||
"ffmpeg", "-y", "-i", str(mp4),
|
||||
"-vf", f"fps={scan_fps:.4f},scale=360:-2",
|
||||
"-vf", f"fps={scan_fps:.4f},scale={scan_width}:-2",
|
||||
"-q:v", "4",
|
||||
str(scan_dir / "s_%05d.jpg"),
|
||||
])
|
||||
@@ -660,7 +661,7 @@ async def pipeline_analyze(
|
||||
candidates: list[dict] = []
|
||||
for i, p in enumerate(scan_paths):
|
||||
t = min(i / scan_fps, max(duration - 0.05, 0.0))
|
||||
item = _frame_metrics(p, i, t)
|
||||
item = _frame_metrics(p, i, t, metric_width)
|
||||
if item:
|
||||
candidates.append(item)
|
||||
if not candidates:
|
||||
@@ -668,7 +669,7 @@ async def pipeline_analyze(
|
||||
|
||||
# 2) 目标化筛选:pHash 去重 + 清晰度 / 中心细节 / 转场变化 / 动作强度 + 时序分桶。
|
||||
selection_count = n if replacing else min(len(candidates), max(n * 4, n + len(existing_frames) + 2))
|
||||
update(job, message=f"{target_label}筛选 {n} / {len(candidates)} 张…", progress=60)
|
||||
update(job, message=f"{quality_label}筛选 · {target_label} · {n} / {len(candidates)} 张…", progress=60)
|
||||
chosen = _select_keyframes(candidates, selection_count, target)
|
||||
|
||||
# 3) 只对最终选中的时间点,从原视频抽高质量关键帧。
|
||||
@@ -708,7 +709,7 @@ async def pipeline_analyze(
|
||||
status="frames_extracted",
|
||||
frames=merged_frames,
|
||||
progress=70,
|
||||
message=f"已按「{target_label}」{action_label} {len(renamed)} 张关键帧 · 共 {len(merged_frames)} 张",
|
||||
message=f"已按「{quality_label} · {target_label}」{action_label} {len(renamed)} 张关键帧 · 共 {len(merged_frames)} 张",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
@@ -1083,13 +1084,14 @@ async def trigger_analyze(
|
||||
frames: int = KEYFRAME_COUNT,
|
||||
target: FrameExtractTarget = "balanced",
|
||||
mode: FrameExtractMode = "replace",
|
||||
quality: FrameExtractQuality = "accurate",
|
||||
) -> Job:
|
||||
job = JOBS.get(job_id)
|
||||
if not job:
|
||||
raise HTTPException(404, "job not found")
|
||||
if job.status not in {"downloaded", "frames_extracted", "transcribed", "failed"}:
|
||||
raise HTTPException(409, f"status must be downloaded/failed, got {job.status}")
|
||||
bg.add_task(pipeline_analyze, job_id, frames, target, mode)
|
||||
bg.add_task(pipeline_analyze, job_id, frames, target, mode, quality)
|
||||
return job
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user