Commit
·
9104277
1
Parent(s):
0526375
fix build
Browse files- config.py +2 -4
- routes/summarize.py +15 -9
- services/extractor.py +1 -1
- services/summarizer.py +2 -20
- static/.gitignore +6 -0
- static/README.md +1 -0
- static/uploads/77ea55af6d744160a5c7e8440b294bb6_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4 +0 -3
- static/uploads/84daab3df51f418ebff312b2ed129bc1_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4 +0 -3
- static/uploads/8ba4aec007f5404db2e9ac9570e59ca6_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4 +0 -3
- static/uploads/b0b93f4bcdcb4662865bb4dc26c1b243_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4 +0 -3
- static/uploads/e051610a8a634fd9a9de3c016d38ce73_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4 +0 -3
- utils/__init__.py +0 -0
- utils/file_utils.py +0 -10
config.py
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
-
# config.py
|
2 |
-
import torch
|
3 |
import os
|
4 |
-
|
5 |
-
|
6 |
FRAME_RATE = 15
|
7 |
SCORE_THRESHOLD = 0.4
|
8 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
|
|
|
|
|
|
1 |
import os
|
2 |
+
import torch
|
3 |
+
|
4 |
FRAME_RATE = 15
|
5 |
SCORE_THRESHOLD = 0.4
|
6 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
routes/summarize.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1 |
from fastapi import APIRouter, UploadFile, File
|
2 |
from fastapi.responses import JSONResponse
|
3 |
-
from utils.file_utils import save_uploaded_file
|
4 |
from services.extractor import extract_frames, extract_features
|
5 |
from services.summarizer import get_scores, get_selected_indices, save_summary_video
|
6 |
-
from
|
|
|
|
|
7 |
|
8 |
router = APIRouter()
|
9 |
|
@@ -12,11 +13,18 @@ def summarize_video(video: UploadFile = File(...)):
|
|
12 |
if not video.filename.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
|
13 |
return JSONResponse(content={"error": "Unsupported file format"}, status_code=400)
|
14 |
|
15 |
-
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
print("\n-----------> Extracting Frames ....")
|
19 |
-
frames, picks = extract_frames(
|
20 |
|
21 |
print("\n-----------> Extracting Features ....")
|
22 |
features = extract_features(frames)
|
@@ -26,14 +34,12 @@ def summarize_video(video: UploadFile = File(...)):
|
|
26 |
|
27 |
print("\n-----------> Selecting Indices ....")
|
28 |
selected = get_selected_indices(scores, picks)
|
29 |
-
output_path = f"{OUTPUT_DIR}/summary_{video.filename}"
|
30 |
|
31 |
print("\n-----------> Saving Video ....")
|
32 |
-
save_summary_video(
|
33 |
-
summary_url = f"/static/outputs/summary_{video.filename}"
|
34 |
|
35 |
print("\n-----------> Returning Response ....")
|
36 |
return JSONResponse(content={
|
37 |
"message": "Summarization complete",
|
38 |
-
"summary_video_url":
|
39 |
})
|
|
|
1 |
from fastapi import APIRouter, UploadFile, File
|
2 |
from fastapi.responses import JSONResponse
|
|
|
3 |
from services.extractor import extract_frames, extract_features
|
4 |
from services.summarizer import get_scores, get_selected_indices, save_summary_video
|
5 |
+
from uuid import uuid4
|
6 |
+
import time
|
7 |
+
import os
|
8 |
|
9 |
router = APIRouter()
|
10 |
|
|
|
13 |
if not video.filename.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
|
14 |
return JSONResponse(content={"error": "Unsupported file format"}, status_code=400)
|
15 |
|
16 |
+
extension = video.filename.split('.')[-1].lower()
|
17 |
+
id = time.time()
|
18 |
+
filename = f"{id}.{extension}"
|
19 |
+
filepath = os.path.join(os.getcwd(), "static", filename)
|
20 |
+
url = f"/static/{filename}"
|
21 |
+
|
22 |
+
print("\n-----------> Saving Video Locally ....")
|
23 |
+
with open(filepath, "wb") as f:
|
24 |
+
f.write(video.file.read())
|
25 |
|
26 |
print("\n-----------> Extracting Frames ....")
|
27 |
+
frames, picks = extract_frames(filepath)
|
28 |
|
29 |
print("\n-----------> Extracting Features ....")
|
30 |
features = extract_features(frames)
|
|
|
34 |
|
35 |
print("\n-----------> Selecting Indices ....")
|
36 |
selected = get_selected_indices(scores, picks)
|
|
|
37 |
|
38 |
print("\n-----------> Saving Video ....")
|
39 |
+
save_summary_video(filepath, selected, filepath)
|
|
|
40 |
|
41 |
print("\n-----------> Returning Response ....")
|
42 |
return JSONResponse(content={
|
43 |
"message": "Summarization complete",
|
44 |
+
"summary_video_url": url
|
45 |
})
|
services/extractor.py
CHANGED
@@ -46,7 +46,7 @@ def extract_frames(video_path):
|
|
46 |
frames = []
|
47 |
indices = []
|
48 |
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
49 |
-
total_frames =
|
50 |
|
51 |
for idx in tqdm(range(0, total_frames, FRAME_RATE)):
|
52 |
cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
|
|
|
46 |
frames = []
|
47 |
indices = []
|
48 |
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
49 |
+
total_frames = 300 # TEMP
|
50 |
|
51 |
for idx in tqdm(range(0, total_frames, FRAME_RATE)):
|
52 |
cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
|
services/summarizer.py
CHANGED
@@ -45,26 +45,8 @@ def save_summary_video(video_path, selected_indices, output_path, fps=15):
|
|
45 |
|
46 |
h, w, _ = list(frames.values())[0].shape
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
writer = cv2.VideoWriter(raw_output_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
|
51 |
for fid in sorted(frames.keys()):
|
52 |
writer.write(frames[fid])
|
53 |
writer.release()
|
54 |
-
|
55 |
-
# 2️⃣ Use FFmpeg to fix video (browser-compatible)
|
56 |
-
try:
|
57 |
-
subprocess.run([
|
58 |
-
"ffmpeg",
|
59 |
-
"-y", # overwrite if file exists
|
60 |
-
"-i", raw_output_path,
|
61 |
-
"-vcodec", "libx264",
|
62 |
-
"-acodec", "aac",
|
63 |
-
output_path
|
64 |
-
], check=True)
|
65 |
-
os.remove(raw_output_path) # optional: remove raw file
|
66 |
-
print(f"✅ FFmpeg re-encoded video saved to: {output_path}")
|
67 |
-
except subprocess.CalledProcessError as e:
|
68 |
-
print("❌ FFmpeg failed:", e)
|
69 |
-
print("⚠️ Using raw video instead.")
|
70 |
-
os.rename(raw_output_path, output_path)
|
|
|
45 |
|
46 |
h, w, _ = list(frames.values())[0].shape
|
47 |
|
48 |
+
os.remove(output_path)
|
49 |
+
writer = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
|
|
|
50 |
for fid in sorted(frames.keys()):
|
51 |
writer.write(frames[fid])
|
52 |
writer.release()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static/.gitignore
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Ignore everything
|
2 |
+
*
|
3 |
+
|
4 |
+
# But not this file
|
5 |
+
!README.md
|
6 |
+
!.gitignore
|
static/README.md
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
All uploaded and summarized videos are stored here.
|
static/uploads/77ea55af6d744160a5c7e8440b294bb6_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:99183f4ca670013008f6a45943bf878532a1db1ad0753f671d289f55f45dac93
|
3 |
-
size 22890415
|
|
|
|
|
|
|
|
static/uploads/84daab3df51f418ebff312b2ed129bc1_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:99183f4ca670013008f6a45943bf878532a1db1ad0753f671d289f55f45dac93
|
3 |
-
size 22890415
|
|
|
|
|
|
|
|
static/uploads/8ba4aec007f5404db2e9ac9570e59ca6_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:99183f4ca670013008f6a45943bf878532a1db1ad0753f671d289f55f45dac93
|
3 |
-
size 22890415
|
|
|
|
|
|
|
|
static/uploads/b0b93f4bcdcb4662865bb4dc26c1b243_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:99183f4ca670013008f6a45943bf878532a1db1ad0753f671d289f55f45dac93
|
3 |
-
size 22890415
|
|
|
|
|
|
|
|
static/uploads/e051610a8a634fd9a9de3c016d38ce73_Paris Saint-Germain vs Atlético de Madrid Highlights | FIFA Club World Cup 2025.mp4
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:99183f4ca670013008f6a45943bf878532a1db1ad0753f671d289f55f45dac93
|
3 |
-
size 22890415
|
|
|
|
|
|
|
|
utils/__init__.py
DELETED
File without changes
|
utils/file_utils.py
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
import os
|
2 |
-
from uuid import uuid4
|
3 |
-
|
4 |
-
def save_uploaded_file(uploaded_file, upload_dir):
|
5 |
-
os.makedirs(upload_dir, exist_ok=True)
|
6 |
-
filename = f"{uuid4().hex}_{uploaded_file.filename}"
|
7 |
-
filepath = os.path.join(upload_dir, filename)
|
8 |
-
with open(filepath, "wb") as f:
|
9 |
-
f.write(uploaded_file.file.read())
|
10 |
-
return filepath
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|