Hug0endob commited on
Commit
2e55d8f
·
verified ·
1 Parent(s): 376a1ee

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +96 -87
streamlit_app.py CHANGED
@@ -248,7 +248,6 @@ def _strip_prompt_echo(prompt: str, text: str, threshold: float = 0.68) -> str:
248
  return text[cut:].lstrip(" \n:-")
249
  return text
250
 
251
-
252
  # ----------------------------------------------------------------------
253
  # Streamlit UI
254
  # ----------------------------------------------------------------------
@@ -259,7 +258,7 @@ def main() -> None:
259
  col_sidebar, col_main = st.columns([1, 3])
260
 
261
  # ---------- Sidebar ----------
262
- with col_sidebar:
263
  st.header("Video Input")
264
  st.text_input("Video URL", key="url", placeholder="https://")
265
 
@@ -268,7 +267,9 @@ def main() -> None:
268
  "Model", MODEL_OPTIONS, index=MODEL_OPTIONS.index(DEFAULT_MODEL)
269
  )
270
  if model == "custom":
271
- model = st.text_input("Custom model ID", value=DEFAULT_MODEL, key="custom_model")
 
 
272
  st.session_state["model_input"] = model
273
 
274
  # API key handling
@@ -277,35 +278,42 @@ def main() -> None:
277
  st.session_state["api_key"] = secret_key
278
  st.text_input("Google API Key", key="api_key", type="password")
279
 
280
- st.text_area("Analysis prompt", value=DEFAULT_PROMPT, key="prompt", height=140)
281
- st.text_input("Video password (if needed)", key="video_password", type="password")
 
 
 
 
 
 
 
282
  st.number_input(
283
  "Compress if > (MB)",
284
  min_value=10,
285
  max_value=2000,
286
- value=st.session_state["compress_mb"],
287
  step=10,
288
  key="compress_mb",
289
  )
290
 
291
  # ---------- Load video ----------
292
  if st.button("Load Video"):
293
- try:
294
- with st.spinner("Downloading video…"):
295
- raw_path = download_video(
296
- st.session_state["url"], DATA_DIR, st.session_state["video_password"]
297
- )
298
- # ALWAYS convert to MP4 before storing
299
- mp4_path = _convert_to_mp4(Path(raw_path))
300
- st.session_state["video_path"] = str(mp4_path) # <-- guaranteed MP4
301
- st.session_state["last_error"] = ""
302
- st.success("Video loaded successfully.")
303
- except Exception as e:
304
- st.session_state["last_error"] = f"Download failed: {e}"
305
- st.sidebar.error(st.session_state["last_error"])
306
 
307
  # ---------- Preview & clear ----------
308
- if st.session_state["video_path"]:
309
  try:
310
  mp4 = _convert_to_mp4(Path(st.session_state["video_path"]))
311
  st.sidebar.video(str(mp4))
@@ -332,83 +340,84 @@ def main() -> None:
332
  )
333
  st.success("Session cleared.")
334
 
335
- # ---------- Generation ----------
336
  with col_main:
337
- # ---------- Generation ----------
338
  col1, col2 = st.columns([1, 3])
339
  with col1:
340
  generate_now = st.button(
341
- "Generate analysis", type="primary", disabled=st.session_state["busy"]
342
  )
343
  with col2:
344
- if not st.session_state["video_path"]:
345
  st.info("Load a video first.", icon="ℹ️")
346
 
347
- if generate_now and not st.session_state["busy"]:
348
- api_key = st.session_state["api_key"] or os.getenv("GOOGLE_API_KEY")
349
- if not st.session_state["video_path"]:
350
- st.error("No video loaded.")
351
- elif not api_key:
352
- st.error("Google API key missing.")
353
- else:
354
- try:
355
- st.session_state["busy"] = True
356
- genai.configure(api_key=api_key)
357
-
358
- # ---- optional compression ----
359
- with st.spinner("Checking video size…"):
360
- video_path, was_compressed = _maybe_compress(
361
- Path(st.session_state["video_path"]),
362
- st.session_state["compress_mb"],
363
- )
364
-
365
- # ---- generation ----
366
- with st.spinner("Generating analysis…"):
367
- raw_out = generate_report(
368
- video_path,
369
- st.session_state["prompt"],
370
- st.session_state["model_input"],
371
- st.session_state.get("generation_timeout", 300),
372
- )
373
- # store the untouched response for debugging
374
- st.session_state["raw_output"] = raw_out
375
-
376
- # clean up temporary compressed file
377
- if was_compressed:
378
  try:
379
- video_path.unlink()
380
- except OSError:
381
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
- out = _strip_prompt_echo(st.session_state["prompt"], raw_out)
384
- st.session_state["analysis_out"] = out
385
- st.success("Analysis generated.")
386
- st.markdown(out or "*(no output)*")
387
- except Exception as exc:
388
- tb = traceback.format_exc()
389
- # keep both traceback and whatever raw output we might have
390
- st.session_state["last_error_detail"] = f"{tb}\n\nRaw Gemini output:\n{st.session_state.get('raw_output','')}"
391
- st.session_state["last_error"] = f"Generation error: {exc}"
392
- # indicate that raw output should be shown in the main area
393
- st.session_state["show_raw_on_error"] = True
394
- st.error("An error occurred during generation.")
395
- finally:
396
- st.session_state["busy"] = False
397
-
398
- # ---------- Results ----------
399
- if st.session_state["analysis_out"]:
400
- st.subheader("📝 Analysis")
401
- st.markdown(st.session_state["analysis_out"])
402
-
403
- # Show raw Gemini output only when it exists (no extra expander)
404
- if st.session_state["raw_output"]:
405
- st.subheader("🔎 Full Gemini output")
406
- st.code(st.session_state["raw_output"], language="text")
407
-
408
- # ---------- Errors ----------
409
- if st.session_state["last_error"]:
410
- with st.expander("❗️ Error details"):
411
- st.code(st.session_state["last_error_detail"], language="text")
412
 
413
  if __name__ == "__main__":
414
  main()
 
248
  return text[cut:].lstrip(" \n:-")
249
  return text
250
 
 
251
  # ----------------------------------------------------------------------
252
  # Streamlit UI
253
  # ----------------------------------------------------------------------
 
258
  col_sidebar, col_main = st.columns([1, 3])
259
 
260
  # ---------- Sidebar ----------
261
+ with col_sidebar:
262
  st.header("Video Input")
263
  st.text_input("Video URL", key="url", placeholder="https://")
264
 
 
267
  "Model", MODEL_OPTIONS, index=MODEL_OPTIONS.index(DEFAULT_MODEL)
268
  )
269
  if model == "custom":
270
+ model = st.text_input(
271
+ "Custom model ID", value=DEFAULT_MODEL, key="custom_model"
272
+ )
273
  st.session_state["model_input"] = model
274
 
275
  # API key handling
 
278
  st.session_state["api_key"] = secret_key
279
  st.text_input("Google API Key", key="api_key", type="password")
280
 
281
+ st.text_area(
282
+ "Analysis prompt",
283
+ value=DEFAULT_PROMPT,
284
+ key="prompt",
285
+ height=140,
286
+ )
287
+ st.text_input(
288
+ "Video password (if needed)", key="video_password", type="password"
289
+ )
290
  st.number_input(
291
  "Compress if > (MB)",
292
  min_value=10,
293
  max_value=2000,
294
+ value=st.session_state.get("compress_mb", 100),
295
  step=10,
296
  key="compress_mb",
297
  )
298
 
299
  # ---------- Load video ----------
300
  if st.button("Load Video"):
301
+ try:
302
+ with st.spinner("Downloading video…"):
303
+ raw_path = download_video(
304
+ st.session_state["url"], DATA_DIR, st.session_state["video_password"]
305
+ )
306
+ # ALWAYS convert to MP4 before storing
307
+ mp4_path = _convert_to_mp4(Path(raw_path))
308
+ st.session_state["video_path"] = str(mp4_path) # guaranteed MP4
309
+ st.session_state["last_error"] = ""
310
+ st.success("Video loaded successfully.")
311
+ except Exception as e:
312
+ st.session_state["last_error"] = f"Download failed: {e}"
313
+ st.sidebar.error(st.session_state["last_error"])
314
 
315
  # ---------- Preview & clear ----------
316
+ if st.session_state.get("video_path"):
317
  try:
318
  mp4 = _convert_to_mp4(Path(st.session_state["video_path"]))
319
  st.sidebar.video(str(mp4))
 
340
  )
341
  st.success("Session cleared.")
342
 
343
+ # ---------- Generation ----------
344
  with col_main:
 
345
  col1, col2 = st.columns([1, 3])
346
  with col1:
347
  generate_now = st.button(
348
+ "Generate analysis", type="primary", disabled=st.session_state.get("busy", False)
349
  )
350
  with col2:
351
+ if not st.session_state.get("video_path"):
352
  st.info("Load a video first.", icon="ℹ️")
353
 
354
+ if generate_now and not st.session_state.get("busy", False):
355
+ api_key = st.session_state.get("api_key") or os.getenv("GOOGLE_API_KEY")
356
+ if not st.session_state.get("video_path"):
357
+ st.error("No video loaded.")
358
+ elif not api_key:
359
+ st.error("Google API key missing.")
360
+ else:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  try:
362
+ st.session_state["busy"] = True
363
+ genai.configure(api_key=api_key)
364
+
365
+ # ---- optional compression ----
366
+ with st.spinner("Checking video size…"):
367
+ video_path, was_compressed = _maybe_compress(
368
+ Path(st.session_state["video_path"]),
369
+ st.session_state["compress_mb"],
370
+ )
371
+
372
+ # ---- generation ----
373
+ with st.spinner("Generating analysis…"):
374
+ raw_out = generate_report(
375
+ video_path,
376
+ st.session_state["prompt"],
377
+ st.session_state["model_input"],
378
+ st.session_state.get("generation_timeout", 300),
379
+ )
380
+ st.session_state["raw_output"] = raw_out
381
+
382
+ # clean up temporary compressed file
383
+ if was_compressed:
384
+ try:
385
+ video_path.unlink()
386
+ except OSError:
387
+ pass
388
+
389
+ out = _strip_prompt_echo(st.session_state["prompt"], raw_out)
390
+ st.session_state["analysis_out"] = out
391
+ st.success("Analysis generated.")
392
+ st.markdown(out or "*(no output)*")
393
+
394
+ except Exception as exc:
395
+ tb = traceback.format_exc()
396
+ st.session_state["last_error_detail"] = (
397
+ f"{tb}\n\nRaw Gemini output:\n"
398
+ f"{st.session_state.get('raw_output', '')}"
399
+ )
400
+ st.session_state["last_error"] = f"Generation error: {exc}"
401
+ st.session_state["show_raw_on_error"] = True
402
+ st.error("An error occurred during generation.")
403
+ finally:
404
+ st.session_state["busy"] = False
405
+
406
+ # ---------- Results ----------
407
+ if st.session_state.get("analysis_out"):
408
+ st.subheader("📝 Analysis")
409
+ st.markdown(st.session_state["analysis_out"])
410
+
411
+ # Show raw Gemini output only when it exists
412
+ if st.session_state.get("raw_output"):
413
+ st.subheader("🔎 Full Gemini output")
414
+ st.code(st.session_state["raw_output"], language="text")
415
+
416
+ # ---------- Errors ----------
417
+ if st.session_state.get("last_error"):
418
+ with st.expander("❗️ Error details"):
419
+ st.code(st.session_state["last_error_detail"], language="text")
420
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
 
422
  if __name__ == "__main__":
423
  main()