Israaabdelghany commited on
Commit
2c3a4f4
·
1 Parent(s): 1d8e215

add graph 2

Browse files
Files changed (1) hide show
  1. UI/pocess_keyframes.py +63 -106
UI/pocess_keyframes.py CHANGED
@@ -1,11 +1,8 @@
 
 
 
1
  import gradio as gr
2
  from pathlib import Path
3
- import warnings
4
- import os
5
- import shutil
6
- import json
7
- import time
8
- import sys
9
 
10
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
11
  warnings.filterwarnings("ignore")
@@ -13,19 +10,11 @@ warnings.filterwarnings("ignore")
13
  from KeyFrameSelection.FeatureExtraction import process_video, save_records
14
  from KeyFrameSelection.Similarties import hash_filter, clip_filter
15
  from FrameProcessor.utils.io_utils import get_frames_from_folder, save_description_to_csv
16
- from FrameProcessor.processor.multi_frame import process_frames
17
  from config.paths import output_csv_file, output_json_file
18
- # from llm.model import model
19
- from langchain_google_genai.chat_models import ChatGoogleGenerativeAI
20
- from dotenv import load_dotenv
21
- import os
22
 
23
- # Log printer
24
- def print_state(text: str):
25
- yield text
26
 
27
- # Keyframe Extraction + Filtering
28
- def extract_and_filter_keyframes(video_path):
29
  keyframe_dir = "outputs/keyframes"
30
  csv_path = "outputs/keyframes.csv"
31
 
@@ -33,13 +22,18 @@ def extract_and_filter_keyframes(video_path):
33
  shutil.rmtree("outputs")
34
  os.makedirs("outputs/final_output", exist_ok=True)
35
 
36
- yield from print_state("✅ Starting video summarization...")
 
 
37
  records, fps = process_video(video_path, interval_sec=10)
38
- yield from print_state("🎞️ Keyframe extraction done.")
39
 
40
- min_frames, max_iterations = 10, 20
 
 
41
  iteration = 0
42
- hash_threshold, ssim_threshold, clip_threshold = 5, 0.95, 0.90
 
 
43
  filtered = records
44
 
45
  while len(filtered) >= min_frames and iteration < max_iterations:
@@ -51,108 +45,71 @@ def extract_and_filter_keyframes(video_path):
51
  iteration += 1
52
 
53
  save_records(filtered, keyframe_dir, csv_path, fps)
54
- yield from print_state(f"✅ Frame filtering done: {len(filtered)} frames saved.")
55
- yield from print_state("📂 Proceeding to multi-frame processing...")
56
-
57
  frame_paths = get_frames_from_folder(keyframe_dir)
58
- yield frame_paths
59
-
60
- # Process frames using multi_frame.py
61
- def process_frames_batch(frame_paths):
62
- if not frame_paths:
63
- yield from print_state("❌ No frames to process.")
64
- return
65
-
66
- yield from print_state(f"🧠 Processing {len(frame_paths)} frames with model...")
67
-
68
- results = process_frames(frame_paths)
69
-
70
- for i, result in enumerate(results):
71
- yield from print_state(f"🖼️ Frame: {os.path.basename(result['frame'])}")
72
- yield from print_state(f"📌 Importance: {result.get('importance')}")
73
- yield from print_state(f"📝 Reason: {result.get('reason')[:100]}")
74
- yield from print_state("-" * 30)
75
 
76
- yield results
77
-
78
- # Save results to JSON & CSV
79
- def save_outputs(results):
80
- important_frames = [r for r in results if r["importance"] == "important"]
81
- for result in important_frames:
82
- save_description_to_csv(result, output_csv_file)
83
-
84
- with open(output_json_file, 'w', encoding='utf-8') as f:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  json.dump(results, f, indent=2, ensure_ascii=False)
86
 
87
- yield from print_state("✅ Final saving done.")
88
- yield from print_state(f"📝 Important frames: {len(important_frames)}")
89
- yield from print_state(f"📁 CSV: {output_csv_file}")
90
- yield from print_state(f"📁 JSON: {output_json_file}")
91
- yield from print_state("🎉 All done!")
92
-
93
- # Main pipeline
94
- def run_full_pipeline(video_path):
95
- start = time.time()
96
 
97
 
98
- load_dotenv()
99
-
100
- model = ChatGoogleGenerativeAI(
101
- model="gemini-1.5-flash",
102
- google_api_key=os.getenv("GOOGLE_API_KEY"),
103
- convert_system_message_to_human=True
104
- )
105
-
106
- if not video_path:
107
- yield from print_state("❌ No video uploaded.")
108
- return
109
-
110
- # Step 1: Extract
111
- frame_paths_gen = extract_and_filter_keyframes(video_path)
112
- frame_paths = None
113
- for out in frame_paths_gen:
114
- if isinstance(out, list):
115
- frame_paths = out
116
- else:
117
- yield out
118
-
119
- # Step 2: Process
120
- results_gen = process_frames_batch(frame_paths)
121
- results = None
122
- for out in results_gen:
123
- if isinstance(out, list):
124
- results = out
125
- else:
126
- yield out
127
-
128
- # Step 3: Save
129
- for out in save_outputs(results):
130
- yield out
131
 
132
- end = time.time()
133
- yield from print_state(f"⏱️ Total Time: {end - start:.2f} sec")
134
 
135
- # Gradio UI
136
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
137
- gr.Markdown("""
138
- <div style='text-align: center; color: #e91e63; line-height: 1.8; margin-bottom: 30px;'>
139
- <h1 style='margin-bottom: 20px;'>🎞️ Video Summarization UI</h1>
140
- <p style='font-size: 18px;'>Upload your lecture or tutorial video</p>
141
- <p style='font-size: 18px;'>Then click <b>Summarize</b> to extract key content</p>
142
- </div>
143
- """)
 
 
144
 
145
  with gr.Row():
146
  with gr.Column(scale=1, min_width=400):
147
  video_upload = gr.File(label="🎥 Upload Video", file_types=["video"], type="filepath")
148
- summarize_btn = gr.Button("✨ Summarize", variant="primary", size="lg")
149
- log_output = gr.Textbox(label="📋 Process Log", lines=25, interactive=False)
150
 
151
  summarize_btn.click(
152
- fn=run_full_pipeline,
153
  inputs=[video_upload],
154
- outputs=[log_output],
155
- show_progress=True
156
  )
157
 
158
  if __name__ == "__main__":
 
1
+ # app.py
2
+
3
+ import os, shutil, time, json, sys, warnings
4
  import gradio as gr
5
  from pathlib import Path
 
 
 
 
 
 
6
 
7
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
8
  warnings.filterwarnings("ignore")
 
10
  from KeyFrameSelection.FeatureExtraction import process_video, save_records
11
  from KeyFrameSelection.Similarties import hash_filter, clip_filter
12
  from FrameProcessor.utils.io_utils import get_frames_from_folder, save_description_to_csv
13
+ from FrameProcessor.graph.workflow import frame_processor
14
  from config.paths import output_csv_file, output_json_file
 
 
 
 
15
 
 
 
 
16
 
17
+ def summarize_video(video_path):
 
18
  keyframe_dir = "outputs/keyframes"
19
  csv_path = "outputs/keyframes.csv"
20
 
 
22
  shutil.rmtree("outputs")
23
  os.makedirs("outputs/final_output", exist_ok=True)
24
 
25
+ start = time.time()
26
+
27
+ # Step 1: Extract raw keyframes
28
  records, fps = process_video(video_path, interval_sec=10)
 
29
 
30
+ # Step 2: Filter
31
+ min_frames = 10
32
+ max_iterations = 20
33
  iteration = 0
34
+ hash_threshold = 5
35
+ ssim_threshold = 0.95
36
+ clip_threshold = 0.90
37
  filtered = records
38
 
39
  while len(filtered) >= min_frames and iteration < max_iterations:
 
45
  iteration += 1
46
 
47
  save_records(filtered, keyframe_dir, csv_path, fps)
 
 
 
48
  frame_paths = get_frames_from_folder(keyframe_dir)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ # Step 3: Graph processing on each frame
51
+ results = []
52
+ for frame_path in frame_paths:
53
+ state = {
54
+ "frame_path": frame_path,
55
+ "frame_data": {},
56
+ "frame_features": {},
57
+ "importance": "not_important",
58
+ "reason": "",
59
+ "description": {},
60
+ "next_step": "describe_frame"
61
+ }
62
+
63
+ try:
64
+ result = frame_processor.invoke(state)
65
+ results.append(result)
66
+
67
+ if result["importance"] == "important":
68
+ save_description_to_csv(result)
69
+
70
+ except Exception as e:
71
+ results.append({
72
+ "frame_path": frame_path,
73
+ "importance": "error",
74
+ "reason": str(e)
75
+ })
76
+
77
+ important = [r for r in results if r["importance"] == "important"]
78
+
79
+ with open(output_json_file, "w") as f:
80
  json.dump(results, f, indent=2, ensure_ascii=False)
81
 
82
+ end = time.time()
83
+ return f" Processed {len(important)} important frames out of {len(results)} in {end - start:.2f}s."
 
 
 
 
 
 
 
84
 
85
 
86
+ def process_uploaded_video(video_file):
87
+ if not video_file:
88
+ raise gr.Error("Please upload a video first.")
89
+ return summarize_video(video_file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
 
 
91
 
 
92
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
93
+ gr.Markdown(
94
+ """
95
+ <div style='text-align: center; color: #e91e63; line-height: 1.8; margin-bottom: 30px;'>
96
+ <h1>🎞️ Video Summarization UI hello</h1>
97
+ <p>Upload your lecture or tutorial video</p>
98
+ <p>Click <b>Summarize</b> to extract important frames and their content</p>
99
+ </div>
100
+ """
101
+ )
102
 
103
  with gr.Row():
104
  with gr.Column(scale=1, min_width=400):
105
  video_upload = gr.File(label="🎥 Upload Video", file_types=["video"], type="filepath")
106
+ summarize_btn = gr.Button("✨ Summarize", variant="primary")
107
+ result_box = gr.Textbox(label="📄 Summary Result")
108
 
109
  summarize_btn.click(
110
+ fn=process_uploaded_video,
111
  inputs=[video_upload],
112
+ outputs=[result_box]
 
113
  )
114
 
115
  if __name__ == "__main__":