Chaitanya-aitf commited on
Commit
84bf8bd
Β·
verified Β·
1 Parent(s): 838a27f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -93
app.py CHANGED
@@ -1,5 +1,5 @@
1
  """
2
- ShortSmith v2 - Gradio Application (Simplified)
3
 
4
  Hugging Face Space interface for video highlight extraction.
5
  """
@@ -10,19 +10,26 @@ import tempfile
10
  import shutil
11
  from pathlib import Path
12
  import time
 
13
 
14
  import gradio as gr
15
 
16
  # Add project root to path
17
  sys.path.insert(0, str(Path(__file__).parent))
18
 
19
- # Initialize logging first
20
- from utils.logger import setup_logging, get_logger
21
- setup_logging(log_level="INFO", log_to_console=True)
22
- logger = get_logger("app")
 
 
 
 
 
 
23
 
24
 
25
- def process_video(video_file, api_key, domain, num_clips, clip_duration, reference_image, custom_prompt):
26
  """Main processing function."""
27
 
28
  log_messages = []
@@ -36,18 +43,18 @@ def process_video(video_file, api_key, domain, num_clips, clip_duration, referen
36
  log("Validating inputs...")
37
 
38
  if not video_file:
39
- return [], "❌ Error: No video file provided", "\n".join(log_messages)
40
 
41
  video_path = Path(video_file)
42
  log(f"Video: {video_path.name}")
43
 
44
- # Import here to avoid schema issues at startup
45
  from utils.helpers import validate_video_file, validate_image_file, format_duration
46
  from pipeline.orchestrator import PipelineOrchestrator
47
 
48
  validation = validate_video_file(video_file)
49
  if not validation.is_valid:
50
- return [], f"❌ Error: {validation.error_message}", "\n".join(log_messages)
51
 
52
  log(f"Video size: {validation.file_size / (1024*1024):.1f} MB")
53
 
@@ -91,7 +98,6 @@ def process_video(video_file, api_key, domain, num_clips, clip_duration, referen
91
  domain=domain_value,
92
  reference_image=ref_path,
93
  custom_prompt=custom_prompt if custom_prompt and custom_prompt.strip() else None,
94
- api_key=api_key if api_key and api_key.strip() else None,
95
  )
96
 
97
  # Handle result
@@ -109,111 +115,79 @@ def process_video(video_file, api_key, domain, num_clips, clip_duration, referen
109
  status = f"βœ… Successfully extracted {len(clip_paths)} highlight clips!\nProcessing time: {result.processing_time:.1f}s"
110
 
111
  pipeline.cleanup()
112
- return clip_paths, status, "\n".join(log_messages)
113
  else:
114
  log(f"❌ Processing failed: {result.error_message}")
115
  pipeline.cleanup()
116
- return [], f"❌ Error: {result.error_message}", "\n".join(log_messages)
117
 
118
  except Exception as e:
119
  error_msg = f"Unexpected error: {str(e)}"
120
  log(f"❌ {error_msg}")
121
- logger.exception("Pipeline error")
122
- return [], f"❌ {error_msg}", "\n".join(log_messages)
123
 
124
 
125
- def create_interface():
126
- """Create the Gradio interface."""
 
 
 
127
 
128
- domains = ["Sports", "Vlogs", "Music Videos", "Podcasts", "Gaming", "General"]
 
129
 
130
- with gr.Blocks(
131
- title="ShortSmith v2",
132
- theme=gr.themes.Soft(),
133
- ) as demo:
134
- gr.Markdown("""
135
- # 🎬 ShortSmith v2
136
- ### AI-Powered Video Highlight Extractor
137
 
138
- Upload a video and extract the most engaging highlight clips automatically.
139
- """)
140
 
141
- with gr.Row():
142
- with gr.Column(scale=1):
143
- gr.Markdown("### πŸ“€ Input")
 
 
144
 
145
- video_input = gr.Video(label="Upload Video")
 
 
 
 
 
 
 
 
146
 
147
- with gr.Accordion("βš™οΈ Settings", open=True):
148
- domain_dropdown = gr.Dropdown(
149
- choices=domains,
150
- value="General",
151
- label="Content Domain",
152
- )
153
 
154
- with gr.Row():
155
- num_clips_slider = gr.Slider(
156
- minimum=1, maximum=10, value=3, step=1,
157
- label="Number of Clips",
158
- )
159
- duration_slider = gr.Slider(
160
- minimum=5, maximum=30, value=15, step=1,
161
- label="Clip Duration (seconds)",
162
- )
163
 
164
- with gr.Accordion("πŸ‘€ Person Filtering (Optional)", open=False):
165
- reference_image = gr.Image(label="Reference Image", type="filepath")
166
 
167
- with gr.Accordion("πŸ“ Custom Instructions (Optional)", open=False):
168
- custom_prompt = gr.Textbox(
169
- label="Additional Instructions",
170
- placeholder="E.g., 'Focus on crowd reactions'",
171
- lines=2,
172
- )
173
 
174
- process_btn = gr.Button("πŸš€ Extract Highlights", variant="primary", size="lg")
 
175
 
176
- # Hidden API key input (for future use)
177
- api_key_input = gr.Textbox(visible=False, value="")
178
 
179
- with gr.Column(scale=1):
180
- gr.Markdown("### πŸ“₯ Output")
181
 
182
- status_output = gr.Textbox(label="Status", lines=3, interactive=False)
183
-
184
- # Output clips as downloadable files
185
- clip_files = gr.Files(label="Extracted Clips")
186
-
187
- with gr.Accordion("πŸ“‹ Processing Log", open=False):
188
- log_output = gr.Textbox(label="Log", lines=10, interactive=False)
189
-
190
- gr.Markdown("---\n**ShortSmith v2** | Powered by Qwen2-VL, InsightFace, and Librosa")
191
-
192
- # Event handler
193
- def on_process(video, api_key, domain, num_clips, duration, ref_img, prompt):
194
- clips, status, logs = process_video(video, api_key, domain, num_clips, duration, ref_img, prompt)
195
- return status, clips, logs
196
-
197
- process_btn.click(
198
- fn=on_process,
199
- inputs=[video_input, api_key_input, domain_dropdown, num_clips_slider, duration_slider, reference_image, custom_prompt],
200
- outputs=[status_output, clip_files, log_output],
201
- )
202
-
203
- return demo
204
-
205
-
206
- def main():
207
- """Main entry point."""
208
- logger.info("Starting ShortSmith v2 Gradio interface...")
209
-
210
- demo = create_interface()
211
- demo.queue()
212
- demo.launch(
213
- server_name="0.0.0.0",
214
- server_port=7860,
215
  )
216
 
217
-
218
  if __name__ == "__main__":
219
- main()
 
 
1
  """
2
+ ShortSmith v2 - Gradio Application
3
 
4
  Hugging Face Space interface for video highlight extraction.
5
  """
 
10
  import shutil
11
  from pathlib import Path
12
  import time
13
+ import traceback
14
 
15
  import gradio as gr
16
 
17
  # Add project root to path
18
  sys.path.insert(0, str(Path(__file__).parent))
19
 
20
+ # Initialize logging
21
+ try:
22
+ from utils.logger import setup_logging, get_logger
23
+ setup_logging(log_level="INFO", log_to_console=True)
24
+ logger = get_logger("app")
25
+ except Exception as e:
26
+ import logging
27
+ logging.basicConfig(level=logging.INFO)
28
+ logger = logging.getLogger("app")
29
+ logger.warning(f"Custom logger failed, using basic: {e}")
30
 
31
 
32
+ def process_video(video_file, domain, num_clips, clip_duration, reference_image, custom_prompt):
33
  """Main processing function."""
34
 
35
  log_messages = []
 
43
  log("Validating inputs...")
44
 
45
  if not video_file:
46
+ return None, "❌ Error: No video file provided", "\n".join(log_messages)
47
 
48
  video_path = Path(video_file)
49
  log(f"Video: {video_path.name}")
50
 
51
+ # Import here to avoid issues at startup
52
  from utils.helpers import validate_video_file, validate_image_file, format_duration
53
  from pipeline.orchestrator import PipelineOrchestrator
54
 
55
  validation = validate_video_file(video_file)
56
  if not validation.is_valid:
57
+ return None, f"❌ Error: {validation.error_message}", "\n".join(log_messages)
58
 
59
  log(f"Video size: {validation.file_size / (1024*1024):.1f} MB")
60
 
 
98
  domain=domain_value,
99
  reference_image=ref_path,
100
  custom_prompt=custom_prompt if custom_prompt and custom_prompt.strip() else None,
 
101
  )
102
 
103
  # Handle result
 
115
  status = f"βœ… Successfully extracted {len(clip_paths)} highlight clips!\nProcessing time: {result.processing_time:.1f}s"
116
 
117
  pipeline.cleanup()
118
+ return clip_paths if clip_paths else None, status, "\n".join(log_messages)
119
  else:
120
  log(f"❌ Processing failed: {result.error_message}")
121
  pipeline.cleanup()
122
+ return None, f"❌ Error: {result.error_message}", "\n".join(log_messages)
123
 
124
  except Exception as e:
125
  error_msg = f"Unexpected error: {str(e)}"
126
  log(f"❌ {error_msg}")
127
+ log(traceback.format_exc())
128
+ return None, f"❌ {error_msg}", "\n".join(log_messages)
129
 
130
 
131
+ # Create interface
132
+ with gr.Blocks(title="ShortSmith v2", theme=gr.themes.Soft()) as demo:
133
+ gr.Markdown("""
134
+ # 🎬 ShortSmith v2
135
+ ### AI-Powered Video Highlight Extractor
136
 
137
+ Upload a video and extract the most engaging highlight clips automatically.
138
+ """)
139
 
140
+ with gr.Row():
141
+ with gr.Column(scale=1):
142
+ gr.Markdown("### πŸ“€ Input")
 
 
 
 
143
 
144
+ video_input = gr.Video(label="Upload Video")
 
145
 
146
+ domain_dropdown = gr.Dropdown(
147
+ choices=["Sports", "Vlogs", "Music Videos", "Podcasts", "Gaming", "General"],
148
+ value="General",
149
+ label="Content Domain",
150
+ )
151
 
152
+ with gr.Row():
153
+ num_clips_slider = gr.Slider(
154
+ minimum=1, maximum=10, value=3, step=1,
155
+ label="Number of Clips",
156
+ )
157
+ duration_slider = gr.Slider(
158
+ minimum=5, maximum=30, value=15, step=1,
159
+ label="Clip Duration (seconds)",
160
+ )
161
 
162
+ with gr.Accordion("πŸ‘€ Person Filtering (Optional)", open=False):
163
+ reference_image = gr.Image(label="Reference Image", type="filepath")
 
 
 
 
164
 
165
+ with gr.Accordion("πŸ“ Custom Instructions (Optional)", open=False):
166
+ custom_prompt = gr.Textbox(
167
+ label="Additional Instructions",
168
+ placeholder="E.g., 'Focus on crowd reactions'",
169
+ lines=2,
170
+ )
 
 
 
171
 
172
+ process_btn = gr.Button("πŸš€ Extract Highlights", variant="primary", size="lg")
 
173
 
174
+ with gr.Column(scale=1):
175
+ gr.Markdown("### πŸ“₯ Output")
 
 
 
 
176
 
177
+ status_output = gr.Textbox(label="Status", lines=3, interactive=False)
178
+ clip_files = gr.Files(label="Extracted Clips")
179
 
180
+ with gr.Accordion("πŸ“‹ Processing Log", open=False):
181
+ log_output = gr.Textbox(label="Log", lines=10, interactive=False)
182
 
183
+ gr.Markdown("---\n**ShortSmith v2** | Powered by Qwen2-VL, InsightFace, and Librosa")
 
184
 
185
+ process_btn.click(
186
+ fn=process_video,
187
+ inputs=[video_input, domain_dropdown, num_clips_slider, duration_slider, reference_image, custom_prompt],
188
+ outputs=[clip_files, status_output, log_output],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  )
190
 
 
191
  if __name__ == "__main__":
192
+ demo.queue()
193
+ demo.launch(server_name="0.0.0.0", server_port=7860)