From 3c13484667040978b360e477ad35c396b493fb21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:40:49 +0000 Subject: [PATCH 1/3] Initial plan From 24a47311347523fb54fe5e67e10ea60e46210c71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:44:44 +0000 Subject: [PATCH 2/3] Remove pafy dependency and replace with yt-dlp Co-authored-by: hackolite <826027+hackolite@users.noreply.github.com> --- CV_Studio.spec | 2 -- build_exe.py | 2 -- node/InputNode/node_webrtc.py | 23 ++++++++++++++++++----- node/InputNode/node_youtube.py | 1 - node/StatsNode/node_bar.py | 1 - requirements.txt | 1 - 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CV_Studio.spec b/CV_Studio.spec index c378d69a..6228fdca 100644 --- a/CV_Studio.spec +++ b/CV_Studio.spec @@ -33,7 +33,6 @@ hiddenimports += collect_submodules('numpy') hiddenimports += collect_submodules('librosa') hiddenimports += collect_submodules('soundfile') hiddenimports += collect_submodules('matplotlib') -hiddenimports += collect_submodules('pafy') hiddenimports += collect_submodules('youtube_dl') hiddenimports += collect_submodules('yt_dlp') hiddenimports += collect_submodules('filterpy') @@ -68,7 +67,6 @@ hiddenimports += [ 'src.utils.logging', 'src.utils.gpu_utils', 'src.core', - 'pafy', 'youtube_dl', 'yt_dlp', 'filterpy', diff --git a/build_exe.py b/build_exe.py index f7b3e6bb..445eb670 100644 --- a/build_exe.py +++ b/build_exe.py @@ -197,7 +197,6 @@ def generate_spec_file(): hiddenimports += collect_submodules('librosa') hiddenimports += collect_submodules('soundfile') hiddenimports += collect_submodules('matplotlib') -hiddenimports += collect_submodules('pafy') hiddenimports += collect_submodules('youtube_dl') hiddenimports += collect_submodules('yt_dlp') hiddenimports += collect_submodules('filterpy') @@ -232,7 +231,6 @@ def generate_spec_file(): 'src.utils.logging', 'src.utils.gpu_utils', 'src.core', - 'pafy', 'youtube_dl', 'yt_dlp', 'filterpy', diff --git a/node/InputNode/node_webrtc.py b/node/InputNode/node_webrtc.py index ff09a909..4eca0211 100644 --- a/node/InputNode/node_webrtc.py +++ b/node/InputNode/node_webrtc.py @@ -3,9 +3,9 @@ import time import cv2 -import pafy import numpy as np import dearpygui.dearpygui as dpg +import yt_dlp from node_editor.util import dpg_get_value, dpg_set_value @@ -384,10 +384,23 @@ def _button(self, sender, data, user_data): dpg.set_item_label(tag_node_button_value_name, self._loading_label) - pafy_video = pafy.new(youtube_url) - pafy_best_video = pafy_video.getbest(preftype="mp4") - youtube_capture = YoutubeCapture(pafy_best_video.url) - self._youtube_capture[youtube_url] = youtube_capture + # Use yt-dlp to get the best video URL + ydl_opts = { + 'quiet': True, + 'format': 'best[ext=mp4]', # Prefer MP4 format + } + try: + with yt_dlp.YoutubeDL(ydl_opts) as ydl: + info = ydl.extract_info(youtube_url, download=False) + video_url = info.get('url', None) + if not video_url: + raise ValueError("No video URL found") + youtube_capture = YoutubeCapture(video_url) + self._youtube_capture[youtube_url] = youtube_capture + except Exception as e: + print(f"Error extracting video URL: {e}") + dpg.set_item_label(tag_node_button_value_name, self._start_label) + return dpg.set_item_label(tag_node_button_value_name, self._stop_label) diff --git a/node/InputNode/node_youtube.py b/node/InputNode/node_youtube.py index c1a58638..559f8cf4 100644 --- a/node/InputNode/node_youtube.py +++ b/node/InputNode/node_youtube.py @@ -5,7 +5,6 @@ from threading import Lock import cv2 -import pafy import numpy as np import dearpygui.dearpygui as dpg import yt_dlp diff --git a/node/StatsNode/node_bar.py b/node/StatsNode/node_bar.py index 1031289f..da86af0b 100644 --- a/node/StatsNode/node_bar.py +++ b/node/StatsNode/node_bar.py @@ -3,7 +3,6 @@ import time import cv2 -import pafy import numpy as np import dearpygui.dearpygui as dpg diff --git a/requirements.txt b/requirements.txt index b0ed8927..45efc19d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,6 @@ dearpygui>=1.11.0 mediapipe protobuf>=3.20.0 filterpy>=1.4.5 -pafy ffmpeg-python serial pytest From d559ece403f88d7954005723abbfcee685e55d1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:47:14 +0000 Subject: [PATCH 3/3] Address code review comments - improve error handling Co-authored-by: hackolite <826027+hackolite@users.noreply.github.com> --- node/InputNode/node_webrtc.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/node/InputNode/node_webrtc.py b/node/InputNode/node_webrtc.py index 4eca0211..22a73af3 100644 --- a/node/InputNode/node_webrtc.py +++ b/node/InputNode/node_webrtc.py @@ -387,7 +387,7 @@ def _button(self, sender, data, user_data): # Use yt-dlp to get the best video URL ydl_opts = { 'quiet': True, - 'format': 'best[ext=mp4]', # Prefer MP4 format + 'format': 'best[ext=mp4]/best', # Prefer MP4, fallback to best available } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: @@ -397,8 +397,12 @@ def _button(self, sender, data, user_data): raise ValueError("No video URL found") youtube_capture = YoutubeCapture(video_url) self._youtube_capture[youtube_url] = youtube_capture + except yt_dlp.utils.DownloadError as e: + print(f"Error downloading video info: {e}") + dpg.set_item_label(tag_node_button_value_name, self._start_label) + return except Exception as e: - print(f"Error extracting video URL: {e}") + print(f"Unexpected error extracting video URL: {e}") dpg.set_item_label(tag_node_button_value_name, self._start_label) return