feat(aurora-ui): add interactive pre-analysis controls and quality report

This commit is contained in:
Apple
2026-03-01 04:10:10 -08:00
parent fe0f2e23c2
commit 79f26ab683
2 changed files with 8563 additions and 0 deletions

View File

@@ -1392,9 +1392,11 @@ async def api_aurora_compare(job_id: str) -> Dict[str, Any]:
"download_url": (result_file or {}).get("url"),
}
output_media_path: Optional[Path] = None
if result_file and output_dir:
out_path = Path(output_dir) / result_file["name"]
if out_path.exists():
output_media_path = out_path
after["file_size_mb"] = round(out_path.stat().st_size / (1024 * 1024), 2)
_probe = _ffprobe_quick(out_path)
if _probe:
@@ -1419,6 +1421,14 @@ async def api_aurora_compare(job_id: str) -> Dict[str, Any]:
"time_ms": step.get("time_ms"),
})
frame_preview = _aurora_ensure_compare_frame_preview(
job_id=job_id,
media_type=str(status.get("media_type") or ""),
input_path=Path(input_path) if input_path else None,
output_path=output_media_path,
output_dir=Path(output_dir) if output_dir else None,
)
return {
"job_id": job_id,
"status": status.get("status"),
@@ -1429,11 +1439,97 @@ async def api_aurora_compare(job_id: str) -> Dict[str, Any]:
"after": after,
"faces_detected": faces_total,
"enhance_steps": enhance_steps,
"frame_preview": frame_preview,
"folder_path": output_dir,
"input_path": input_path,
}
def _aurora_extract_frame_preview(source: Path, target: Path, *, second: float = 1.0) -> bool:
"""Write a JPEG preview frame for image/video sources."""
if not source.exists():
return False
target.parent.mkdir(parents=True, exist_ok=True)
ext = source.suffix.lower()
if ext in {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".tif", ".tiff"}:
try:
target.write_bytes(source.read_bytes())
return True
except Exception:
return False
ffmpeg = [
"ffmpeg",
"-hide_banner",
"-loglevel",
"error",
"-y",
"-ss",
f"{max(0.0, float(second)):.3f}",
"-i",
str(source),
"-frames:v",
"1",
"-q:v",
"2",
str(target),
]
try:
run = subprocess.run(ffmpeg, capture_output=True, text=True, timeout=20)
if run.returncode == 0 and target.exists() and target.stat().st_size > 0:
return True
except Exception:
pass
# Fallback for short videos / odd timestamps.
ffmpeg_fallback = ffmpeg[:]
ffmpeg_fallback[6] = "0.0"
try:
run = subprocess.run(ffmpeg_fallback, capture_output=True, text=True, timeout=20)
return run.returncode == 0 and target.exists() and target.stat().st_size > 0
except Exception:
return False
def _aurora_ensure_compare_frame_preview(
*,
job_id: str,
media_type: str,
input_path: Optional[Path],
output_path: Optional[Path],
output_dir: Optional[Path],
) -> Optional[Dict[str, Any]]:
if not output_dir or not output_dir.exists():
return None
if not input_path or not input_path.exists():
return None
if not output_path or not output_path.exists():
return None
before_name = "_compare_before.jpg"
after_name = "_compare_after.jpg"
before_path = output_dir / before_name
after_path = output_dir / after_name
ts = 1.0 if media_type == "video" else 0.0
if not before_path.exists() or before_path.stat().st_size == 0:
_aurora_extract_frame_preview(input_path, before_path, second=ts)
if not after_path.exists() or after_path.stat().st_size == 0:
_aurora_extract_frame_preview(output_path, after_path, second=ts)
if not before_path.exists() or not after_path.exists():
return None
if before_path.stat().st_size <= 0 or after_path.stat().st_size <= 0:
return None
quoted_job = quote(job_id, safe="")
return {
"timestamp_sec": ts,
"before_url": f"/api/aurora/files/{quoted_job}/{quote(before_name, safe='')}",
"after_url": f"/api/aurora/files/{quoted_job}/{quote(after_name, safe='')}",
}
def _ffprobe_quick(filepath: Path) -> Dict[str, Any]:
"""Quick ffprobe for resolution, codec, duration, fps, frame count."""
if not filepath.exists():

File diff suppressed because it is too large Load Diff