jonathanagustin commited on
Commit
a74a9f0
1 Parent(s): 8765c4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -33
app.py CHANGED
@@ -19,7 +19,6 @@ Dependencies:
19
  Usage:
20
  Run this file to launch the Gradio interface, which allows users to input search queries for YouTube live streams, select a stream, and perform object detection on the selected live stream.
21
  """
22
-
23
  import logging
24
  import sys
25
  from enum import Enum
@@ -31,11 +30,10 @@ import innertube
31
  import numpy as np
32
  from PIL import Image
33
  from ultralytics import YOLO
34
- from pytube import YouTube
35
 
36
  logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
37
 
38
-
39
  class SearchFilter(Enum):
40
  LIVE = ("EgJAAQ%3D%3D", "Live")
41
  VIDEO = ("EgIQAQ%3D%3D", "Video")
@@ -47,7 +45,6 @@ class SearchFilter(Enum):
47
  def __str__(self):
48
  return self.human_readable
49
 
50
-
51
  class SearchService:
52
  @staticmethod
53
  def search(query: Optional[str], filter: SearchFilter = SearchFilter.VIDEO):
@@ -93,37 +90,40 @@ class SearchService:
93
 
94
  @staticmethod
95
  def get_stream(youtube_url: str) -> Optional[str]:
96
- """Retrieves the live stream URL for a given YouTube video URL using pytube.
97
-
98
  :param youtube_url: The URL of the YouTube video.
99
  :type youtube_url: str
100
- :return: The HLS manifest URL if available, otherwise None.
101
  :rtype: Optional[str]
102
  """
 
 
 
 
 
 
 
103
  try:
104
- yt = YouTube(youtube_url)
105
- _ = yt.streams
106
- is_live = yt.player_response.get('videoDetails', {}).get('isLiveContent', False)
107
- if is_live:
108
- streaming_data = yt.player_response.get('streamingData', {})
109
- hls_manifest_url = streaming_data.get('hlsManifestUrl')
110
- if hls_manifest_url:
111
- logging.debug(f"Found HLS manifest URL for live stream: {hls_manifest_url}")
112
- return hls_manifest_url
 
113
  else:
114
- logging.warning(f"HLS manifest URL not found for live stream: {youtube_url}")
115
  return None
116
- else:
117
- logging.warning(f"Video is not a live stream: {youtube_url}")
118
- return None
119
  except Exception as e:
120
  logging.warning(f"An error occurred while getting stream: {e}")
121
  return None
122
 
123
-
124
  INITIAL_STREAMS = SearchService.search("world live cams", SearchFilter.LIVE)
125
 
126
-
127
  class LiveYouTubeObjectDetector:
128
  def __init__(self):
129
  logging.getLogger().setLevel(logging.DEBUG)
@@ -163,36 +163,36 @@ class LiveYouTubeObjectDetector:
163
  return None
164
  try:
165
  cap = cv2.VideoCapture(stream_url)
 
 
 
166
  ret, frame = cap.read()
167
  cap.release()
168
  if ret and frame is not None:
169
- return cv2.resize(frame, (1920, 1080))
170
  else:
171
- logging.warning("Unable to process the live stream with cv2.VideoCapture.")
172
  return None
173
  except Exception as e:
174
  logging.warning(f"An error occurred while capturing the frame: {e}")
175
  return None
176
 
177
  def annotate(self, frame: np.ndarray) -> Tuple[Image.Image, List[Tuple[Tuple[int, int, int, int], str]]]:
178
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
179
- predictions = self.model.predict(frame_rgb)
180
  annotations = []
181
- result = predictions[0]
182
-
183
- boxes = result.boxes
184
  for box in boxes:
185
  x1, y1, x2, y2 = box.xyxy[0].tolist()
186
  class_id = int(box.cls[0])
187
  class_name = self.model.names[class_id]
188
  bbox_coords = (int(x1), int(y1), int(x2), int(y2))
189
  annotations.append((bbox_coords, class_name))
190
-
191
- return Image.fromarray(frame_rgb), annotations
192
 
193
  @staticmethod
194
  def create_black_image() -> Tuple[Image.Image, List]:
195
- black_image = np.zeros((1080, 1920, 3), dtype=np.uint8)
196
  pil_black_image = Image.fromarray(black_image)
197
  return pil_black_image, []
198
 
@@ -240,6 +240,5 @@ class LiveYouTubeObjectDetector:
240
 
241
  app.queue().launch(show_api=False, debug=True)
242
 
243
-
244
  if __name__ == "__main__":
245
  LiveYouTubeObjectDetector().render()
 
19
  Usage:
20
  Run this file to launch the Gradio interface, which allows users to input search queries for YouTube live streams, select a stream, and perform object detection on the selected live stream.
21
  """
 
22
  import logging
23
  import sys
24
  from enum import Enum
 
30
  import numpy as np
31
  from PIL import Image
32
  from ultralytics import YOLO
33
+ import yt_dlp
34
 
35
  logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
36
 
 
37
  class SearchFilter(Enum):
38
  LIVE = ("EgJAAQ%3D%3D", "Live")
39
  VIDEO = ("EgIQAQ%3D%3D", "Video")
 
45
  def __str__(self):
46
  return self.human_readable
47
 
 
48
  class SearchService:
49
  @staticmethod
50
  def search(query: Optional[str], filter: SearchFilter = SearchFilter.VIDEO):
 
90
 
91
  @staticmethod
92
  def get_stream(youtube_url: str) -> Optional[str]:
93
+ """Retrieves the livestream URL for a given YouTube video URL using yt-dlp.
94
+
95
  :param youtube_url: The URL of the YouTube video.
96
  :type youtube_url: str
97
+ :return: The livestream URL if available, otherwise None.
98
  :rtype: Optional[str]
99
  """
100
+ ydl_opts = {
101
+ 'format': 'best',
102
+ 'quiet': True,
103
+ 'no_warnings': True,
104
+ 'force_generic_extractor': False,
105
+ 'skip_download': True,
106
+ }
107
  try:
108
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
109
+ info_dict = ydl.extract_info(youtube_url, download=False)
110
+ if info_dict.get('is_live'):
111
+ live_url = info_dict.get('url')
112
+ if live_url:
113
+ logging.debug(f"Found livestream URL: {live_url}")
114
+ return live_url
115
+ else:
116
+ logging.warning(f"Livestream URL not found for: {youtube_url}")
117
+ return None
118
  else:
119
+ logging.warning(f"Video is not a livestream: {youtube_url}")
120
  return None
 
 
 
121
  except Exception as e:
122
  logging.warning(f"An error occurred while getting stream: {e}")
123
  return None
124
 
 
125
  INITIAL_STREAMS = SearchService.search("world live cams", SearchFilter.LIVE)
126
 
 
127
  class LiveYouTubeObjectDetector:
128
  def __init__(self):
129
  logging.getLogger().setLevel(logging.DEBUG)
 
163
  return None
164
  try:
165
  cap = cv2.VideoCapture(stream_url)
166
+ if not cap.isOpened():
167
+ logging.warning("Failed to open video capture.")
168
+ return None
169
  ret, frame = cap.read()
170
  cap.release()
171
  if ret and frame is not None:
172
+ return cv2.resize(frame, (1280, 720))
173
  else:
174
+ logging.warning("Unable to read frame from the live stream.")
175
  return None
176
  except Exception as e:
177
  logging.warning(f"An error occurred while capturing the frame: {e}")
178
  return None
179
 
180
  def annotate(self, frame: np.ndarray) -> Tuple[Image.Image, List[Tuple[Tuple[int, int, int, int], str]]]:
181
+ results = self.model(frame)[0]
 
182
  annotations = []
183
+ boxes = results.boxes
 
 
184
  for box in boxes:
185
  x1, y1, x2, y2 = box.xyxy[0].tolist()
186
  class_id = int(box.cls[0])
187
  class_name = self.model.names[class_id]
188
  bbox_coords = (int(x1), int(y1), int(x2), int(y2))
189
  annotations.append((bbox_coords, class_name))
190
+ pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
191
+ return pil_image, annotations
192
 
193
  @staticmethod
194
  def create_black_image() -> Tuple[Image.Image, List]:
195
+ black_image = np.zeros((720, 1280, 3), dtype=np.uint8)
196
  pil_black_image = Image.fromarray(black_image)
197
  return pil_black_image, []
198
 
 
240
 
241
  app.queue().launch(show_api=False, debug=True)
242
 
 
243
  if __name__ == "__main__":
244
  LiveYouTubeObjectDetector().render()