2026-05-18-20-18-20 对齐结果视频时长

This commit is contained in:
2026-05-18 20:22:11 +08:00
parent 88cbcc65c2
commit 5264c5c7fc
7 changed files with 154 additions and 23 deletions

View File

@@ -181,6 +181,21 @@ def _selected_frame(index: int, stride: int, selected_count: int, max_frames: in
return index % max(1, stride) == 0 and selected_count < max_frames
def _selected_frame_indices(frame_count: int, stride: int, max_frames: int) -> set[int]:
if frame_count <= 0:
return set()
candidates = list(range(0, frame_count, max(1, stride)))
if len(candidates) <= max_frames:
return set(candidates)
if max_frames <= 1:
return {candidates[0]}
last = len(candidates) - 1
return {
candidates[round(position * last / (max_frames - 1))]
for position in range(max_frames)
}
def _process_video(
job_path: Path,
source: Path,
@@ -197,27 +212,30 @@ def _process_video(
previous = None
frame_index = 0
selected_count = 0
written_count = 0
writer = None
result_fps = 8.0
raw_video_path = job_path / f"{method}_overlay.raw.mp4"
video_path = job_path / f"{method}_overlay.mp4"
source_fps = float(capture.get(cv2.CAP_PROP_FPS) or 0.0)
if source_fps <= 0:
source_fps = 12.0
result_fps = source_fps
frame_count = int(capture.get(cv2.CAP_PROP_FRAME_COUNT) or 0)
duration = round(frame_count / source_fps, 4) if frame_count else 0.0
selected_indices = _selected_frame_indices(frame_count, frame_stride, max_frames)
try:
while True:
ok, frame = capture.read()
if not ok:
break
if not _selected_frame(frame_index, frame_stride, selected_count, max_frames):
previous = frame
frame_index += 1
continue
should_process = (
frame_index in selected_indices
if selected_indices
else _selected_frame(frame_index, frame_stride, selected_count, max_frames)
)
video_frame = frame
if method == "compare":
if should_process and method == "compare":
outputs = compare_frame(frame, previous, sensitivity)
for output in outputs:
frames.append(
@@ -228,12 +246,14 @@ def _process_video(
frame,
output,
frame_index / source_fps,
selected_count / result_fps,
selected_count,
frame_index / source_fps,
frame_index,
)
)
video_output = next(item for item in outputs if item.method == "fusion")
else:
video_frame = video_output.overlay
selected_count += 1
elif should_process:
video_output = segment_frame(frame, method, previous, sensitivity)
frames.append(
_save_frame_outputs(
@@ -243,18 +263,20 @@ def _process_video(
frame,
video_output,
frame_index / source_fps,
selected_count / result_fps,
selected_count,
frame_index / source_fps,
frame_index,
)
)
video_frame = video_output.overlay
selected_count += 1
if writer is None:
height, width = video_output.overlay.shape[:2]
height, width = frame.shape[:2]
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
writer = cv2.VideoWriter(str(raw_video_path), fourcc, result_fps, (width, height))
writer.write(video_output.overlay)
writer.write(video_frame)
written_count += 1
selected_count += 1
previous = frame
frame_index += 1
finally:
@@ -266,14 +288,15 @@ def _process_video(
raise HTTPException(status_code=400, detail="视频没有可处理帧")
if raw_video_path.exists():
_browser_video(raw_video_path, video_path)
duration = round(written_count / source_fps, 4) if written_count else 0.0
return {
"kind": "video",
"frames": frames,
"video_url": _public(video_path) if video_path.exists() else None,
"source_fps": round(source_fps, 4),
"result_fps": result_fps,
"result_fps": round(result_fps, 4),
"duration": duration,
"result_duration": round(len({frame["result_index"] for frame in frames}) / result_fps, 4) if frames else 0.0,
"result_duration": duration,
}