Hug0endob commited on
Commit
c1ab3dd
·
verified ·
1 Parent(s): 1e1e0ab

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +116 -22
streamlit_app.py CHANGED
@@ -48,6 +48,8 @@ for key, val in {
48
  "last_error": "",
49
  "api_key": os.getenv("GOOGLE_API_KEY", ""),
50
  "model_input": DEFAULT_MODEL,
 
 
51
  "processing_timeout": 900,
52
  "generation_timeout": 300,
53
  "compress_threshold_mb": 200,
@@ -98,15 +100,15 @@ def download_video(url: str, dst_dir: str, password: str = "") -> str:
98
  with yt_dlp.YoutubeDL(opts) as ydl:
99
  info = ydl.extract_info(url, download=True)
100
 
101
- # yt‑dlp may return a dict or a playlist dict
102
- vid_id = info.get("id") if isinstance(info, dict) else None
103
- ext = info.get("ext", "mp4") if isinstance(info, dict) else "mp4"
104
- candidate = str(Path(dst_dir) / f"{vid_id}.{ext}") if vid_id else None
 
 
 
105
 
106
- if candidate and os.path.exists(candidate):
107
- return convert_to_mp4(candidate)
108
-
109
- # Fallback: pick the newest file in the folder
110
  newest = max(glob(os.path.join(dst_dir, "*")), key=os.path.getmtime)
111
  return convert_to_mp4(newest)
112
 
@@ -132,9 +134,7 @@ def strip_prompt_echo(prompt: str, text: str) -> str:
132
  return text
133
 
134
 
135
- def generate_inline(
136
- video_path: str, prompt: str, model_id: str, timeout: int
137
- ) -> str:
138
  with open(video_path, "rb") as f:
139
  b64 = base64.b64encode(f.read()).decode()
140
  video_part = {
@@ -153,21 +153,21 @@ def generate_inline(
153
 
154
 
155
  # ----------------------------------------------------------------------
156
- # UISidebar (inputs)
157
  # ----------------------------------------------------------------------
158
  st.sidebar.header("Video Input")
159
  st.sidebar.text_input("Video URL", key="url", placeholder="https://")
160
 
161
- with st.sidebar.expander("Settings", expanded=False) as exp:
162
- model = exp.selectbox("Model", MODEL_OPTIONS, index=MODEL_OPTIONS.index(DEFAULT_MODEL))
163
  if model == "custom":
164
- model = exp.text_input("Custom model ID", value=DEFAULT_MODEL, key="custom_model")
165
  st.session_state["model_input"] = model
166
 
167
- exp.text_input("Google API Key", key="api_key", type="password")
168
- exp.text_area("Analysis prompt", value=DEFAULT_PROMPT, key="prompt", height=140)
169
- exp.text_input("Video password (if needed)", key="video_password", type="password")
170
- exp.number_input(
171
  "Processing timeout (s)",
172
  min_value=60,
173
  max_value=3600,
@@ -175,7 +175,7 @@ with st.sidebar.expander("Settings", expanded=False) as exp:
175
  step=30,
176
  key="processing_timeout",
177
  )
178
- exp.number_input(
179
  "Generation timeout (s)",
180
  min_value=30,
181
  max_value=1800,
@@ -183,10 +183,104 @@ with st.sidebar.expander("Settings", expanded=False) as exp:
183
  step=10,
184
  key="generation_timeout",
185
  )
186
- exp.number_input(
187
  "Compress if > (MB)",
188
  min_value=10,
189
  max_value=2000,
190
  value=st.session_state["compress_threshold_mb"],
191
  step=10,
192
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  "last_error": "",
49
  "api_key": os.getenv("GOOGLE_API_KEY", ""),
50
  "model_input": DEFAULT_MODEL,
51
+ "prompt": DEFAULT_PROMPT,
52
+ "video_password": "",
53
  "processing_timeout": 900,
54
  "generation_timeout": 300,
55
  "compress_threshold_mb": 200,
 
100
  with yt_dlp.YoutubeDL(opts) as ydl:
101
  info = ydl.extract_info(url, download=True)
102
 
103
+ # Try to locate the downloaded file
104
+ if isinstance(info, dict) and info.get("id"):
105
+ vid_id = info["id"]
106
+ ext = info.get("ext", "mp4")
107
+ candidate = str(Path(dst_dir) / f"{vid_id}.{ext}")
108
+ if os.path.exists(candidate):
109
+ return convert_to_mp4(candidate)
110
 
111
+ # Fallback: newest file in the folder
 
 
 
112
  newest = max(glob(os.path.join(dst_dir, "*")), key=os.path.getmtime)
113
  return convert_to_mp4(newest)
114
 
 
134
  return text
135
 
136
 
137
+ def generate_inline(video_path: str, prompt: str, model_id: str, timeout: int) -> str:
 
 
138
  with open(video_path, "rb") as f:
139
  b64 = base64.b64encode(f.read()).decode()
140
  video_part = {
 
153
 
154
 
155
  # ----------------------------------------------------------------------
156
+ # Sidebar – inputs & settings
157
  # ----------------------------------------------------------------------
158
  st.sidebar.header("Video Input")
159
  st.sidebar.text_input("Video URL", key="url", placeholder="https://")
160
 
161
+ with st.sidebar.expander("Settings", expanded=False):
162
+ model = st.selectbox("Model", MODEL_OPTIONS, index=MODEL_OPTIONS.index(DEFAULT_MODEL))
163
  if model == "custom":
164
+ model = st.text_input("Custom model ID", value=DEFAULT_MODEL, key="custom_model")
165
  st.session_state["model_input"] = model
166
 
167
+ st.text_input("Google API Key", key="api_key", type="password")
168
+ st.text_area("Analysis prompt", value=DEFAULT_PROMPT, key="prompt", height=140)
169
+ st.text_input("Video password (if needed)", key="video_password", type="password")
170
+ st.number_input(
171
  "Processing timeout (s)",
172
  min_value=60,
173
  max_value=3600,
 
175
  step=30,
176
  key="processing_timeout",
177
  )
178
+ st.number_input(
179
  "Generation timeout (s)",
180
  min_value=30,
181
  max_value=1800,
 
183
  step=10,
184
  key="generation_timeout",
185
  )
186
+ st.number_input(
187
  "Compress if > (MB)",
188
  min_value=10,
189
  max_value=2000,
190
  value=st.session_state["compress_threshold_mb"],
191
  step=10,
192
+ key="compress_threshold_mb",
193
+ )
194
+
195
+ # ----------------------------------------------------------------------
196
+ # Load / preview video
197
+ # ----------------------------------------------------------------------
198
+ if st.sidebar.button("Load Video"):
199
+ try:
200
+ path = download_video(
201
+ st.session_state["url"], str(DATA_DIR), st.session_state["video_password"]
202
+ )
203
+ st.session_state["videos"] = path
204
+ st.session_state["last_error"] = ""
205
+ except Exception as e:
206
+ st.session_state["last_error"] = f"Download failed: {e}"
207
+ st.sidebar.error(st.session_state["last_error"])
208
+
209
+ if st.session_state["videos"]:
210
+ try:
211
+ mp4 = convert_to_mp4(st.session_state["videos"])
212
+ with open(mp4, "rb") as f:
213
+ video_bytes = f.read()
214
+ st.sidebar.video(video_bytes, format="video/mp4")
215
+ except Exception:
216
+ st.sidebar.write("Preview unavailable")
217
+
218
+ if st.sidebar.button("Clear Video"):
219
+ for f in glob(str(DATA_DIR / "*")):
220
+ try:
221
+ os.remove(f)
222
+ except Exception:
223
+ pass
224
+ st.session_state.update(
225
+ {
226
+ "videos": "",
227
+ "analysis_out": "",
228
+ "last_error": "",
229
+ "busy": False,
230
+ }
231
+ )
232
+
233
+ # ----------------------------------------------------------------------
234
+ # Generation
235
+ # ----------------------------------------------------------------------
236
+ col1, col2 = st.columns([1, 3])
237
+ with col1:
238
+ generate_now = st.button("Generate analysis", type="primary")
239
+ with col2:
240
+ if not st.session_state["videos"]:
241
+ st.info("Load a video first.", icon="ℹ️")
242
+
243
+ if generate_now and not st.session_state["busy"]:
244
+ if not st.session_state["videos"]:
245
+ st.error("No video loaded.")
246
+ elif not (st.session_state["api_key"] or os.getenv("GOOGLE_API_KEY")):
247
+ st.error("Google API key missing.")
248
+ else:
249
+ st.session_state["busy"] = True
250
+ try:
251
+ genai.configure(api_key=st.session_state["api_key"] or os.getenv("GOOGLE_API_KEY"))
252
+ model_id = st.session_state["model_input"]
253
+ prompt = st.session_state["prompt"]
254
+
255
+ # Optional compression to stay under inline limits
256
+ video_path = maybe_compress(
257
+ st.session_state["videos"], st.session_state["compress_threshold_mb"]
258
+ )
259
+
260
+ with st.spinner("Generating…"):
261
+ raw_out = generate_inline(
262
+ video_path, prompt, model_id, st.session_state["generation_timeout"]
263
+ )
264
+ out = strip_prompt_echo(prompt, raw_out)
265
+ st.session_state["analysis_out"] = out
266
+ st.subheader("Analysis Result")
267
+ st.markdown(out or "No output.")
268
+ except Exception as e:
269
+ # Capture full traceback for debugging while showing a short message to the user
270
+ tb = traceback.format_exc()
271
+ st.session_state["last_error"] = f"Generation error: {e}"
272
+ st.error("An error occurred during generation. Check the log below.")
273
+ st.code(tb, language="text")
274
+ finally:
275
+ st.session_state["busy"] = False
276
+
277
+ # ----------------------------------------------------------------------
278
+ # Show results / errors
279
+ # ----------------------------------------------------------------------
280
+ if st.session_state["analysis_out"]:
281
+ st.subheader("📝 Analysis")
282
+ st.markdown(st.session_state["analysis_out"])
283
+
284
+ if st.session_state["last_error"]:
285
+ st.subheader("❗️ Error log")
286
+ st.code(st.session_state["last_error"], language="text")