| import subprocess |
| from pathlib import Path |
| import cv2 |
|
|
| from config import FRAMES_SUBDIR |
|
|
| def ensure_dir(p: Path): |
| p.mkdir(parents=True, exist_ok=True) |
|
|
| def extract_audio_ffmpeg(video_path: Path, wav_path: Path, sr: int = 16000): |
| ensure_dir(wav_path.parent) |
| cmd = [ |
| "ffmpeg", "-y", |
| "-i", str(video_path), |
| "-vn", |
| "-ac", "1", |
| "-ar", str(sr), |
| str(wav_path), |
| ] |
| subprocess.run(cmd, check=True) |
| return wav_path |
|
|
| def extract_frames(video_path: Path, out_dir: Path, interval_sec: float, max_frames: int): |
| ensure_dir(out_dir) |
| cap = cv2.VideoCapture(str(video_path)) |
| if not cap.isOpened(): |
| raise RuntimeError("Cannot open video") |
| fps = cap.get(cv2.CAP_PROP_FPS) or 25.0 |
| step = max(int(fps * interval_sec), 1) |
|
|
| idx, saved = 0, 0 |
| while True: |
| ok, frame = cap.read() |
| if not ok: |
| break |
| if idx % step == 0: |
| (out_dir / f"frame_{saved:05d}.jpg").write_bytes( |
| cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 92])[1].tobytes() |
| ) |
| saved += 1 |
| if saved >= max_frames: |
| break |
| idx += 1 |
| cap.release() |
| return saved |
|
|
| def prepare_dirs(out_root: Path, video_file: Path): |
| base = video_file.stem |
| run_dir = out_root / base |
| frames_dir = run_dir / FRAMES_SUBDIR |
| ensure_dir(run_dir) |
| ensure_dir(frames_dir) |
| return run_dir, frames_dir |
|
|