app.py
CHANGED
@@ -32,53 +32,53 @@ def format_duration(seconds: int) -> str:
|
|
32 |
return f"{minutes}:{secs:02d}"
|
33 |
|
34 |
|
35 |
-
@spaces.GPU
|
36 |
-
def process_video(
|
37 |
-
|
38 |
-
|
39 |
-
) -> Tuple[str, str, str, str]:
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
|
52 |
-
|
53 |
-
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
|
59 |
-
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
|
65 |
-
|
66 |
-
|
67 |
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
72 |
|
73 |
-
|
74 |
-
|
75 |
|
76 |
def create_ui(examples_path: str):
|
77 |
examples_data = load_examples(examples_path)
|
78 |
|
79 |
with gr.Blocks() as app:
|
80 |
gr.Markdown("# Video Highlight Generator")
|
81 |
-
gr.Markdown("Upload a video
|
82 |
|
83 |
with gr.Row():
|
84 |
gr.Markdown("## Example Results")
|
@@ -111,68 +111,98 @@ def create_ui(examples_path: str):
|
|
111 |
with gr.Column(scale=1):
|
112 |
input_video = gr.Video(
|
113 |
label="Upload your video (max 20 minutes)",
|
114 |
-
interactive=True
|
115 |
-
max_length = 1200
|
116 |
)
|
117 |
process_btn = gr.Button("Process Video", variant="primary")
|
118 |
-
status = gr.Markdown(visible=True)
|
119 |
|
120 |
-
# Right column: Progress
|
121 |
with gr.Column(scale=1):
|
122 |
-
|
123 |
-
|
124 |
# Output video (initially hidden)
|
125 |
output_video = gr.Video(
|
126 |
label="Highlight Video",
|
127 |
visible=False,
|
128 |
interactive=False,
|
|
|
129 |
)
|
130 |
-
|
131 |
-
|
|
|
132 |
with gr.Accordion("Model chain of thought details", open=True, visible=False) as analysis_accordion:
|
133 |
-
video_description = gr.Markdown(
|
134 |
-
highlight_types = gr.Markdown(
|
|
|
135 |
|
|
|
136 |
def on_process(video, progress=gr.Progress()):
|
137 |
if not video:
|
138 |
return {
|
139 |
status: "Please upload a video",
|
140 |
-
|
141 |
-
|
|
|
142 |
}
|
143 |
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
return {
|
149 |
-
status:
|
150 |
-
|
151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
}
|
153 |
-
|
154 |
-
# Format the analysis text
|
155 |
-
desc = f"#Summary: {desc[:500] + '...' if len(desc) > 500 else desc}"
|
156 |
-
highlights = f"#Highlights to search for: {highlights[:500] + '...' if len(highlights) > 500 else highlights}"
|
157 |
-
|
158 |
-
return {
|
159 |
-
status: "Processing complete!",
|
160 |
-
output_video: gr.update(value=output_path, visible=True),
|
161 |
-
analysis_accordion: gr.update(visible=True),
|
162 |
-
video_description: desc,
|
163 |
-
highlight_types: highlights,
|
164 |
-
}
|
165 |
|
166 |
process_btn.click(
|
167 |
on_process,
|
168 |
inputs=[input_video],
|
169 |
-
outputs=[
|
170 |
-
status,
|
171 |
-
output_video,
|
172 |
-
analysis_accordion,
|
173 |
-
video_description,
|
174 |
-
highlight_types,
|
175 |
-
]
|
176 |
)
|
177 |
|
178 |
return app
|
|
|
32 |
return f"{minutes}:{secs:02d}"
|
33 |
|
34 |
|
35 |
+
# @spaces.GPU
|
36 |
+
# def process_video(
|
37 |
+
# video_path: str,
|
38 |
+
# progress = gr.Progress()
|
39 |
+
# ) -> Tuple[str, str, str, str]:
|
40 |
+
# try:
|
41 |
+
# # duration = get_video_duration_seconds(video_path)
|
42 |
+
# # if duration > 1200: # 20 minutes
|
43 |
+
# # return None, None, None, "Video must be shorter than 20 minutes"
|
44 |
+
|
45 |
+
# progress(0.1, desc="Loading model...")
|
46 |
+
# model, processor = load_model()
|
47 |
+
# detector = BatchedVideoHighlightDetector(model, processor, batch_size=8)
|
48 |
+
|
49 |
+
# progress(0.2, desc="Analyzing video content...")
|
50 |
+
# video_description = detector.analyze_video_content(video_path)
|
51 |
|
52 |
+
# progress(0.3, desc="Determining highlight types...")
|
53 |
+
# highlight_types = detector.determine_highlights(video_description)
|
54 |
|
55 |
+
# progress(0.4, desc="Detecting and extracting highlights...")
|
56 |
+
# with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as tmp_file:
|
57 |
+
# output_path = tmp_file.name
|
58 |
|
59 |
+
# detector.create_highlight_video(video_path, output_path)
|
60 |
|
61 |
+
# # progress(0.9, desc="Adding watermark...")
|
62 |
+
# # output_path = temp_output.replace('.mp4', '_watermark.mp4')
|
63 |
+
# # add_watermark(temp_output, output_path)
|
64 |
|
65 |
+
# os.unlink(output_path)
|
66 |
+
# progress(1.0, desc="Complete!")
|
67 |
|
68 |
+
# video_description = video_description[:500] + "..." if len(video_description) > 500 else video_description
|
69 |
+
# highlight_types = highlight_types[:500] + "..." if len(highlight_types) > 500 else highlight_types
|
70 |
|
71 |
+
# return output_path, video_description, highlight_types, None
|
72 |
|
73 |
+
# except Exception as e:
|
74 |
+
# return None, None, None, f"Error processing video: {str(e)}"
|
75 |
|
76 |
def create_ui(examples_path: str):
|
77 |
examples_data = load_examples(examples_path)
|
78 |
|
79 |
with gr.Blocks() as app:
|
80 |
gr.Markdown("# Video Highlight Generator")
|
81 |
+
gr.Markdown("Upload a video and get an automated highlight reel!")
|
82 |
|
83 |
with gr.Row():
|
84 |
gr.Markdown("## Example Results")
|
|
|
111 |
with gr.Column(scale=1):
|
112 |
input_video = gr.Video(
|
113 |
label="Upload your video (max 20 minutes)",
|
114 |
+
interactive=True
|
|
|
115 |
)
|
116 |
process_btn = gr.Button("Process Video", variant="primary")
|
|
|
117 |
|
118 |
+
# Right column: Progress and Analysis
|
119 |
with gr.Column(scale=1):
|
120 |
+
|
|
|
121 |
# Output video (initially hidden)
|
122 |
output_video = gr.Video(
|
123 |
label="Highlight Video",
|
124 |
visible=False,
|
125 |
interactive=False,
|
126 |
+
downloadable=True
|
127 |
)
|
128 |
+
|
129 |
+
status = gr.Markdown()
|
130 |
+
|
131 |
with gr.Accordion("Model chain of thought details", open=True, visible=False) as analysis_accordion:
|
132 |
+
video_description = gr.Markdown("", elem_id="video_desc")
|
133 |
+
highlight_types = gr.Markdown("", elem_id="highlight_types")
|
134 |
+
|
135 |
|
136 |
+
@spaces.GPU
|
137 |
def on_process(video, progress=gr.Progress()):
|
138 |
if not video:
|
139 |
return {
|
140 |
status: "Please upload a video",
|
141 |
+
video_description: "",
|
142 |
+
highlight_types: "",
|
143 |
+
output_video: gr.update(visible=False)
|
144 |
}
|
145 |
|
146 |
+
try:
|
147 |
+
duration = get_video_duration_seconds(video)
|
148 |
+
if duration > 1200: # 20 minutes
|
149 |
+
return {
|
150 |
+
status: "Video must be shorter than 20 minutes",
|
151 |
+
video_description: "",
|
152 |
+
highlight_types: "",
|
153 |
+
output_video: gr.update(visible=False)
|
154 |
+
}
|
155 |
+
|
156 |
+
progress(0.1, desc="Loading model...")
|
157 |
+
status.value = "Loading model..."
|
158 |
+
model, processor = load_model()
|
159 |
+
detector = BatchedVideoHighlightDetector(model, processor, batch_size=8)
|
160 |
+
|
161 |
+
progress(0.2, desc="Analyzing video content...")
|
162 |
+
status.value = "Analyzing video content..."
|
163 |
+
video_desc = detector.analyze_video_content(video)
|
164 |
+
# Update description in real-time
|
165 |
+
video_description.value = f"#Summary: {video_desc[:500] + '...' if len(video_desc) > 500 else video_desc}"
|
166 |
+
|
167 |
+
progress(0.3, desc="Determining highlight types...")
|
168 |
+
status.value = "Determining highlight types..."
|
169 |
+
highlights = detector.determine_highlights(video_desc)
|
170 |
+
# Update highlights in real-time
|
171 |
+
highlight_types.value = f"#Highlights to search for: {highlights[:500] + '...' if len(highlights) > 500 else highlights}"
|
172 |
+
|
173 |
+
progress(0.4, desc="Detecting and extracting highlights...")
|
174 |
+
status.value = "Detecting and extracting highlights..."
|
175 |
+
with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as tmp_file:
|
176 |
+
temp_output = tmp_file.name
|
177 |
+
detector.create_highlight_video(video, temp_output)
|
178 |
+
|
179 |
+
# progress(0.9, desc="Adding watermark...")
|
180 |
+
# status.value = "Adding watermark..."
|
181 |
+
# output_path = temp_output.replace('.mp4', '_watermark.mp4')
|
182 |
+
# add_watermark(temp_output, output_path)
|
183 |
+
|
184 |
+
# os.unlink(temp_output)
|
185 |
+
progress(1.0, desc="Complete!")
|
186 |
+
|
187 |
return {
|
188 |
+
status: "Processing complete!",
|
189 |
+
video_description: video_description.value,
|
190 |
+
highlight_types: highlight_types.value,
|
191 |
+
output_video: gr.update(value=temp_output, visible=True)
|
192 |
+
}
|
193 |
+
|
194 |
+
except Exception as e:
|
195 |
+
return {
|
196 |
+
status: f"Error processing video: {str(e)}",
|
197 |
+
video_description: "",
|
198 |
+
highlight_types: "",
|
199 |
+
output_video: gr.update(visible=False)
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
process_btn.click(
|
203 |
on_process,
|
204 |
inputs=[input_video],
|
205 |
+
outputs=[status, video_description, highlight_types, output_video]
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
)
|
207 |
|
208 |
return app
|