DivYonko commited on
Commit
2a149f0
·
1 Parent(s): 0ed17b2

Fix video title fetch for live streams + fix subtitle encoding

Browse files
Files changed (2) hide show
  1. app.py +27 -6
  2. shared.py +22 -3
app.py CHANGED
@@ -569,13 +569,34 @@ def extract_video_id(url_or_id):
569
 
570
 
571
  def fetch_video_title(video_id):
 
 
 
 
572
  try:
573
- import urllib.request
574
  url = f"https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v={video_id}&format=json"
575
  with urllib.request.urlopen(url, timeout=5) as resp:
576
- return json.loads(resp.read())["title"]
 
 
577
  except Exception:
578
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
 
580
 
581
  def clean_topic(val):
@@ -1098,11 +1119,11 @@ for _si, _ss in enumerate(st.session_state.streams):
1098
  _st = _ss.get("video_title") or _ss.get("video_id")
1099
  _sk = _ss.get("redis_key", "")
1100
  if _st and (store_llen(_sk) > 0 or is_scraper_running(_si)):
1101
- _all_titles.append(f"? {_st}")
1102
  if _all_titles:
1103
- _subtitle = " ".join(_all_titles)
1104
  else:
1105
- _subtitle = "Real-time sentiment topic classification engagement insights"
1106
 
1107
  # Build active stream pills for header
1108
  _active_stream_pills = ""
 
569
 
570
 
571
  def fetch_video_title(video_id):
572
+ """Try oembed first (works for non-live), then YouTube Data API v3 (works for live)."""
573
+ import urllib.request
574
+ import urllib.parse
575
+ # Try oembed first (fast, no API key needed)
576
  try:
 
577
  url = f"https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v={video_id}&format=json"
578
  with urllib.request.urlopen(url, timeout=5) as resp:
579
+ title = json.loads(resp.read()).get("title")
580
+ if title:
581
+ return title
582
  except Exception:
583
+ pass
584
+ # Fallback: YouTube Data API v3 (works for live streams)
585
+ try:
586
+ api_key = os.getenv("YOUTUBE_API_KEY", "")
587
+ if api_key:
588
+ url = (
589
+ "https://www.googleapis.com/youtube/v3/videos"
590
+ f"?part=snippet&id={urllib.parse.quote(video_id)}&key={api_key}"
591
+ )
592
+ with urllib.request.urlopen(url, timeout=5) as resp:
593
+ data = json.loads(resp.read())
594
+ items = data.get("items", [])
595
+ if items:
596
+ return items[0]["snippet"]["title"]
597
+ except Exception:
598
+ pass
599
+ return None
600
 
601
 
602
  def clean_topic(val):
 
1119
  _st = _ss.get("video_title") or _ss.get("video_id")
1120
  _sk = _ss.get("redis_key", "")
1121
  if _st and (store_llen(_sk) > 0 or is_scraper_running(_si)):
1122
+ _all_titles.append(f"\u25b6 {_st}")
1123
  if _all_titles:
1124
+ _subtitle = " \u00b7 ".join(_all_titles)
1125
  else:
1126
+ _subtitle = "Real-time sentiment \u00b7 topic classification \u00b7 engagement insights"
1127
 
1128
  # Build active stream pills for header
1129
  _active_stream_pills = ""
shared.py CHANGED
@@ -332,13 +332,32 @@ def extract_video_id(url_or_id: str) -> str:
332
 
333
 
334
  def fetch_video_title(video_id: str) -> str | None:
 
 
 
335
  try:
336
- import urllib.request
337
  url = f"https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v={video_id}&format=json"
338
  with urllib.request.urlopen(url, timeout=5) as resp:
339
- return json.loads(resp.read())["title"]
 
 
340
  except Exception:
341
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
 
343
 
344
  def clean_topic(val) -> str:
 
332
 
333
 
334
  def fetch_video_title(video_id: str) -> str | None:
335
+ """Try oembed first (works for non-live), then YouTube Data API v3 (works for live)."""
336
+ import urllib.request
337
+ import urllib.parse
338
  try:
 
339
  url = f"https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v={video_id}&format=json"
340
  with urllib.request.urlopen(url, timeout=5) as resp:
341
+ title = json.loads(resp.read()).get("title")
342
+ if title:
343
+ return title
344
  except Exception:
345
+ pass
346
+ try:
347
+ api_key = os.getenv("YOUTUBE_API_KEY", "")
348
+ if api_key:
349
+ url = (
350
+ "https://www.googleapis.com/youtube/v3/videos"
351
+ f"?part=snippet&id={urllib.parse.quote(video_id)}&key={api_key}"
352
+ )
353
+ with urllib.request.urlopen(url, timeout=5) as resp:
354
+ data = json.loads(resp.read())
355
+ items = data.get("items", [])
356
+ if items:
357
+ return items[0]["snippet"]["title"]
358
+ except Exception:
359
+ pass
360
+ return None
361
 
362
 
363
  def clean_topic(val) -> str: