CB commited on
Commit
2d02069
·
verified ·
1 Parent(s): 9d64fe3

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +59 -103
streamlit_app.py CHANGED
@@ -1,4 +1,3 @@
1
- # streamlit_app.py
2
  import os
3
  import time
4
  import json
@@ -10,24 +9,30 @@ import yt_dlp
10
  import ffmpeg
11
  import streamlit as st
12
  from dotenv import load_dotenv
13
- import requests
14
 
15
  load_dotenv()
16
 
17
- # Try to import the Google SDK
18
- HAS_GENAI = False
19
- GENAI = None
 
 
 
 
 
 
 
20
  try:
21
  import google.generativeai as genai
22
  from google.generativeai import upload_file, get_file
23
  GENAI = genai
24
  HAS_GENAI = True
25
  except Exception:
26
- upload_file = None
27
- get_file = None
 
28
 
29
  st.set_page_config(page_title="Generate the story of videos:", layout="wide")
30
-
31
  DATA_DIR = Path("./data")
32
  DATA_DIR.mkdir(exist_ok=True)
33
 
@@ -42,8 +47,8 @@ settings_exp = st.sidebar.expander("Settings", expanded=False)
42
  env_api_key = os.getenv("GOOGLE_API_KEY", "")
43
  API_KEY = settings_exp.text_input("Google API Key", value=env_api_key, placeholder="Set GOOGLE_API_KEY in .env or enter here")
44
 
45
- raw_model = settings_exp.text_input("Gemini Model (model name)", "gemini-2.0-flash-lite")
46
- model_id = raw_model.strip() or "gemini-2.0-flash-lite"
47
 
48
  analysis_prompt = settings_exp.text_area("Enter analysis", "watch entire video and describe")
49
  settings_exp.text_input("Video Password", key="video-password", placeholder="Enter Video Password (if needed)")
@@ -93,12 +98,22 @@ def download_video_ytdlp(url: str, save_dir: str, video_password: str = None) ->
93
  raise FileNotFoundError("Downloaded video not found")
94
  return convert_video_to_mp4(matches[0])
95
 
 
96
  if API_KEY and HAS_GENAI:
97
  try:
98
  GENAI.configure(api_key=API_KEY)
99
  except Exception:
100
  pass
101
 
 
 
 
 
 
 
 
 
 
102
  if st.sidebar.button("Load Video", use_container_width=True):
103
  try:
104
  video_password = st.session_state.get("video-password", "")
@@ -139,79 +154,26 @@ if st.session_state["videos"]:
139
 
140
  st.sidebar.write("Title:", Path(st.session_state["videos"]).name)
141
 
142
- def upload_video(filepath: str):
143
  if not API_KEY:
144
  raise RuntimeError("No API key provided")
145
- if HAS_GENAI and callable(upload_file):
146
- return upload_file(filepath)
147
- url = "https://generative.googleapis.com/v1beta2/files?uploadType=multipart"
148
- headers = {"Authorization": f"Bearer {API_KEY}"}
149
- metadata = {"mimeType": "video/mp4", "displayName": Path(filepath).name}
150
- files = {
151
- "metadata": ("metadata", json.dumps(metadata), "application/json"),
152
- "file": (Path(filepath).name, open(filepath, "rb"), "video/mp4"),
153
- }
154
- r = requests.post(url, headers=headers, files=files)
155
- r.raise_for_status()
156
- return r.json()
157
 
158
- def poll_file_processed(file_obj, timeout=180):
159
  start = time.time()
160
- if HAS_GENAI and hasattr(file_obj, "name"):
161
- name = file_obj.name
162
- while getattr(file_obj, "state", None) and getattr(file_obj.state, "name", None) == "PROCESSING":
163
- if time.time() - start > timeout:
164
- raise TimeoutError("File processing timed out")
165
- time.sleep(2)
166
- file_obj = get_file(name)
167
- return file_obj
168
- fid = file_obj.get("name") or file_obj.get("id")
169
- if not fid:
170
  return file_obj
171
- url = f"https://generative.googleapis.com/v1beta2/{fid}"
172
- headers = {"Authorization": f"Bearer {API_KEY}"}
173
  while True:
174
- r = requests.get(url, headers=headers)
175
- r.raise_for_status()
176
- j = r.json()
177
- state = j.get("state", {}).get("name") if j.get("state") else None
178
- if state != "PROCESSING":
179
- return j
180
  if time.time() - start > timeout:
181
  raise TimeoutError("File processing timed out")
182
  time.sleep(2)
183
 
184
- def call_model_with_file(prompt_text: str, uploaded_file_obj):
185
- if not API_KEY:
186
- raise RuntimeError("No API key provided")
187
-
188
- file_ref_name = (
189
- uploaded_file_obj.name
190
- if hasattr(uploaded_file_obj, "name")
191
- else uploaded_file_obj.get("name") or uploaded_file_obj.get("id")
192
- )
193
-
194
- if HAS_GENAI and hasattr(GENAI, "responses") and hasattr(GENAI.responses, "generate"):
195
- request = {
196
- "model": f"models/{model_id}",
197
- "input": [{"text": prompt_text, "files": [{"name": file_ref_name}]}],
198
- "safetySettings": safety_settings,
199
- "maxOutputTokens": 1000,
200
- }
201
- return GENAI.responses.generate(**request)
202
-
203
- model_short = model_id.split("/")[-1]
204
- endpoint = f"https://generativeapis.googleapis.com/v1/models/{model_short}:generate"
205
- body = {
206
- "input": [{"text": prompt_text, "files": [{"name": file_ref_name}]}],
207
- "safetySettings": safety_settings,
208
- "maxOutputTokens": 1000,
209
- }
210
- headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
211
- r = requests.post(endpoint, headers=headers, json=body, timeout=180)
212
- r.raise_for_status()
213
- return r.json()
214
-
215
  if st.button("Generate the story", type="primary"):
216
  if not st.session_state.get("videos"):
217
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
@@ -220,41 +182,35 @@ if st.button("Generate the story", type="primary"):
220
  else:
221
  try:
222
  with st.spinner("Uploading video..."):
223
- uploaded = upload_video(st.session_state["videos"])
224
- processed = poll_file_processed(uploaded)
225
 
226
  prompt_text = (analysis_prompt.strip() or "Describe this video in vivid detail.").strip()
227
 
228
- with st.spinner("Generating description..."):
229
- result = call_model_with_file(prompt_text, processed)
230
-
231
- text_out = ""
232
- if isinstance(result, dict):
233
- if "output" in result:
234
- try:
235
- for item in result.get("output", []):
236
- for c in item.get("content", []):
237
- if c.get("type") in ("output_text", "text"):
238
- text_out += c.get("text", "")
239
- except Exception:
240
- text_out = json.dumps(result)
241
- elif "candidates" in result:
242
- for cand in result["candidates"]:
243
- if isinstance(cand.get("content"), str):
244
- text_out += cand.get("content", "")
245
- elif isinstance(cand.get("content"), list):
246
- for part in cand.get("content"):
247
- text_out += part.get("text", "") if isinstance(part, dict) else str(part)
248
- elif "outputText" in result:
249
- text_out = result.get("outputText") or result.get("output_text") or ""
250
- elif "generatedText" in result:
251
- text_out = result.get("generatedText")
252
- else:
253
- text_out = json.dumps(result, indent=2)
254
  else:
255
- text_out = str(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
 
257
  st.subheader("Analysis Result")
258
- st.markdown(text_out)
259
  except Exception as e:
260
  st.error(f"An error occurred: {e}")
 
 
1
  import os
2
  import time
3
  import json
 
9
  import ffmpeg
10
  import streamlit as st
11
  from dotenv import load_dotenv
 
12
 
13
  load_dotenv()
14
 
15
+ # Try imports (phi and google SDK)
16
+ try:
17
+ from phi.agent import Agent
18
+ from phi.model.google import Gemini
19
+ from phi.tools.duckduckgo import DuckDuckGo
20
+ HAS_PHI = True
21
+ except Exception:
22
+ Agent = Gemini = DuckDuckGo = None
23
+ HAS_PHI = False
24
+
25
  try:
26
  import google.generativeai as genai
27
  from google.generativeai import upload_file, get_file
28
  GENAI = genai
29
  HAS_GENAI = True
30
  except Exception:
31
+ upload_file = get_file = None
32
+ GENAI = None
33
+ HAS_GENAI = False
34
 
35
  st.set_page_config(page_title="Generate the story of videos:", layout="wide")
 
36
  DATA_DIR = Path("./data")
37
  DATA_DIR.mkdir(exist_ok=True)
38
 
 
47
  env_api_key = os.getenv("GOOGLE_API_KEY", "")
48
  API_KEY = settings_exp.text_input("Google API Key", value=env_api_key, placeholder="Set GOOGLE_API_KEY in .env or enter here")
49
 
50
+ model_input = settings_exp.text_input("Gemini Model (short name)", "gemini-2.0-flash-lite")
51
+ model_id = model_input.strip() or "gemini-2.0-flash-lite"
52
 
53
  analysis_prompt = settings_exp.text_area("Enter analysis", "watch entire video and describe")
54
  settings_exp.text_input("Video Password", key="video-password", placeholder="Enter Video Password (if needed)")
 
98
  raise FileNotFoundError("Downloaded video not found")
99
  return convert_video_to_mp4(matches[0])
100
 
101
+ # configure GENAI if available
102
  if API_KEY and HAS_GENAI:
103
  try:
104
  GENAI.configure(api_key=API_KEY)
105
  except Exception:
106
  pass
107
 
108
+ # initialize phi Agent if available (uses Gemini wrapper)
109
+ _agent = None
110
+ if HAS_PHI and HAS_GENAI and API_KEY:
111
+ try:
112
+ _agent = Agent(name="Video AI summarizer", model=Gemini(id=model_id), tools=[DuckDuckGo()], markdown=True)
113
+ except Exception:
114
+ _agent = None
115
+
116
+ # UI actions
117
  if st.sidebar.button("Load Video", use_container_width=True):
118
  try:
119
  video_password = st.session_state.get("video-password", "")
 
154
 
155
  st.sidebar.write("Title:", Path(st.session_state["videos"]).name)
156
 
157
+ def upload_video_sdk(filepath: str):
158
  if not API_KEY:
159
  raise RuntimeError("No API key provided")
160
+ return upload_file(filepath)
 
 
 
 
 
 
 
 
 
 
 
161
 
162
+ def wait_for_processed(file_obj, timeout=180):
163
  start = time.time()
164
+ name = getattr(file_obj, "name", None) or file_obj.get("name") or file_obj.get("id")
165
+ if not name:
 
 
 
 
 
 
 
 
166
  return file_obj
 
 
167
  while True:
168
+ obj = get_file(name)
169
+ state = getattr(obj, "state", None)
170
+ if not state or getattr(state, "name", None) != "PROCESSING":
171
+ return obj
 
 
172
  if time.time() - start > timeout:
173
  raise TimeoutError("File processing timed out")
174
  time.sleep(2)
175
 
176
+ # Main generate (Agent.run flow)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  if st.button("Generate the story", type="primary"):
178
  if not st.session_state.get("videos"):
179
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
 
182
  else:
183
  try:
184
  with st.spinner("Uploading video..."):
185
+ uploaded = upload_video_sdk(st.session_state["videos"])
186
+ processed = wait_for_processed(uploaded)
187
 
188
  prompt_text = (analysis_prompt.strip() or "Describe this video in vivid detail.").strip()
189
 
190
+ if _agent:
191
+ with st.spinner("Generating description via Agent..."):
192
+ response = _agent.run(prompt_text, videos=[processed], safety_settings=safety_settings)
193
+ out = getattr(response, "content", None) or getattr(response, "outputText", None) or str(response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  else:
195
+ # fallback: call GENAI.responses.generate directly
196
+ with st.spinner("Generating description via SDK..."):
197
+ request = {
198
+ "model": f"models/{model_id}",
199
+ "input": [{"text": prompt_text, "files": [{"name": getattr(processed, 'name', processed.get('name'))}]}],
200
+ "safetySettings": safety_settings,
201
+ "maxOutputTokens": 1000,
202
+ }
203
+ res = GENAI.responses.generate(**request)
204
+ out = ""
205
+ # basic extraction
206
+ for item in res.output or res.get("output", []):
207
+ for c in (getattr(item, "content", None) or item.get("content", [])):
208
+ if getattr(c, "type", None) in ("output_text", "text") or c.get("type") in ("output_text", "text"):
209
+ out += getattr(c, "text", "") or c.get("text", "")
210
+ if not out:
211
+ out = getattr(res, "text", None) or json.dumps(res, default=str)
212
 
213
  st.subheader("Analysis Result")
214
+ st.markdown(out)
215
  except Exception as e:
216
  st.error(f"An error occurred: {e}")