| import cv2 | |
| import os | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| def extract_key_frames(video_path, start_sec, end_sec): | |
| cap = cv2.VideoCapture(video_path) | |
| fps = cap.get(cv2.CAP_PROP_FPS) | |
| start_frame = int(start_sec * fps) | |
| end_frame = int(end_sec * fps) | |
| mid_frame = (start_frame + end_frame) // 2 | |
| frames = [] | |
| for frame_number in [start_frame, mid_frame, end_frame]: | |
| cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number) | |
| ret, frame = cap.read() | |
| if ret: | |
| frames.append(frame) | |
| cap.release() | |
| return frames | |
| def save_frames_locally(frames, event_id): | |
| os.makedirs("/data", exist_ok=True) | |
| frame_paths = [] | |
| for idx, frame in enumerate(frames): | |
| path = f"/data/frame_{event_id}_{idx}.jpg" | |
| cv2.imwrite(path, frame) | |
| frame_paths.append(path) | |
| return frame_paths | |
| def generate_frame_urls(frame_paths): | |
| base_url = os.getenv("SPACE_URL", "http://localhost:8000") | |
| return [f"{base_url}/data/{os.path.basename(path)}" for path in frame_paths] | |
| def match_transcript_to_events(events, transcript): | |
| for event in events: | |
| matched_lines = [ | |
| line["text"] for line in transcript | |
| if line["start_sec"] <= event["end_sec"] and line["end_sec"] >= event["start_sec"] | |
| ] | |
| event["transcript"] = "\n".join(matched_lines) or "(No matching commentary)" | |
| return events | |
| def clip_video_segment(video_path, start_sec, end_sec, event_id): | |
| output_path = f"/data/clip_{event_id}.mp4" | |
| duration = end_sec - start_sec | |
| command = [ | |
| "ffmpeg", "-y", | |
| "-ss", str(start_sec), | |
| "-i", video_path, | |
| "-t", str(duration), | |
| "-c", "copy", output_path | |
| ] | |
| os.system(" ".join(command)) | |
| return output_path | |