diff options
| author | Pinapelz <yukais@pinapelz.com> | 2026-06-26 21:55:46 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-06-26 21:55:46 -0700 |
| commit | 00d476a0e51629f06407aed035fbc001d3f6b114 (patch) | |
| tree | 016338cc4dacff54ba1cbe11fce063152cbd28ab /playlist_generator | |
| parent | 84fbd4ee1e159b0426d664cc98a3dc7165d6381f (diff) | |
initial guess MV mode
Diffstat (limited to 'playlist_generator')
| -rw-r--r-- | playlist_generator/.gitignore | 3 | ||||
| -rw-r--r-- | playlist_generator/frame_generator.py | 85 | ||||
| -rw-r--r-- | playlist_generator/generate_daily.py | 68 | ||||
| -rw-r--r-- | playlist_generator/pyproject.toml | 2 | ||||
| -rw-r--r-- | playlist_generator/uv.lock | 62 |
5 files changed, 219 insertions, 1 deletions
diff --git a/playlist_generator/.gitignore b/playlist_generator/.gitignore index d40a36b..6a6b4fa 100644 --- a/playlist_generator/.gitignore +++ b/playlist_generator/.gitignore @@ -222,4 +222,5 @@ venvw *.json *.mp3 *.ts -todo.txt +*.txt +*.jpg diff --git a/playlist_generator/frame_generator.py b/playlist_generator/frame_generator.py new file mode 100644 index 0000000..6bee037 --- /dev/null +++ b/playlist_generator/frame_generator.py @@ -0,0 +1,85 @@ +import random +import subprocess +import yt_dlp +import cv2 +import os + + +def get_video_info(url): + ydl_opts = {"quiet": True} + with yt_dlp.YoutubeDL(ydl_opts) as ydl: + return ydl.extract_info(url, download=False) + + +def pick_best_video_url(info): + formats = [ + f for f in info["formats"] + if f.get("url") and f.get("vcodec") != "none" + ] + formats.sort( + key=lambda f: (f.get("height") or 0, f.get("tbr") or 0), + reverse=True + ) + return formats[0]["url"] + + +def is_low_energy(img_path, size=64, threshold=500): + img = cv2.imread(img_path) + if img is None: + raise RuntimeError("Could not read image") + img = cv2.resize(img, (size, size), interpolation=cv2.INTER_AREA) + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + return gray.var() < threshold + + +def download_random_frame(url, name_prefix="frame", selected_timestamps=None, max_tries=10): + if selected_timestamps is None: + selected_timestamps = [] + + info = get_video_info(url) + duration = info.get("duration") + if not duration: + raise RuntimeError("No duration found") + + video_url = pick_best_video_url(info) + + for _ in range(max_tries): + t = random.uniform(0, duration) + while any(abs(t - ts) < 1 for ts in selected_timestamps): + t = random.uniform(0, duration) + filename = f"{name_prefix}-{t:.2f}.jpg" + + cmd = [ + "ffmpeg", + "-ss", str(t), + "-i", video_url, + "-frames:v", "1", + "-q:v", "2", + "-y", + filename, + ] + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if not os.path.exists(filename): + continue + try: + if is_low_energy(filename): + os.remove(filename) + continue + except Exception: + pass + return t + + raise RuntimeError("Failed to generate a valid frame after retries") + + +def generate_daily_random_frames(url, output_dir, count=3): + selected_timestamps = [] + os.makedirs(output_dir, exist_ok=True) + for i in range(count): + ts = download_random_frame( + url, + f"{output_dir}/frame", + selected_timestamps + ) + selected_timestamps.append(ts) + print(f"Downloaded frame {i} at {ts:.2f}s") diff --git a/playlist_generator/generate_daily.py b/playlist_generator/generate_daily.py index 508871c..0bb8f3c 100644 --- a/playlist_generator/generate_daily.py +++ b/playlist_generator/generate_daily.py @@ -7,6 +7,7 @@ from dotenv import load_dotenv from datetime import datetime, timedelta import yt_dlp import time +from frame_generator import generate_daily_random_frames load_dotenv() @@ -22,6 +23,12 @@ HEARDLE_SALT = ( NTFY_URL = os.getenv("NTFY_URL") NTFY_TOKEN = os.getenv("NTFY_TOKEN") +def fetch_instance_info() -> dict: + if not API_URL: + raise ValueError("Missing API_URL in environment.") + response = requests.get(f"{API_URL}/info") + return response.json() + def send_notification(message: str): if not NTFY_URL or not NTFY_TOKEN: return @@ -67,6 +74,19 @@ def fetch_daily() -> dict: return payload +def fetch_daily_mv() -> dict: + if not API_URL: + raise ValueError("Missing API_URL in environment.") + + url = f"{API_URL}/todayMV" + response = requests.get(url, timeout=15) + response.raise_for_status() + payload = response.json() + if "date" not in payload or "data" not in payload: + raise ValueError(f"Unexpected /todayMV response shape: {payload}") + + return payload + def download_random_segment_mp3(youtube_id: str, output_file="today.mp3") -> str: url = f"https://www.youtube.com/watch?v={youtube_id}" @@ -137,6 +157,9 @@ def read_json(file_path, default=None): return default def main(): + info = fetch_instance_info() + dailyMV = info.get("dailyMV", False) + new_data = False daily_data = fetch_daily() attempt = 0 @@ -171,5 +194,50 @@ def main(): delete_from_r2(f"kheardle/{three_days_ago}.mp3") send_notification(f"K-HEARDLE: Deleted old clip for {three_days_ago}") + if dailyMV: + print("Starting Daily MV Generation") + mv_data = fetch_daily_mv() + mv_decoded = decode_data(mv_data["data"], mv_data["date"]) + mv_youtube_id = mv_decoded["youtubeId"] + mv_date = mv_data["date"] + + mv_output_dir = f"frames_mv_{mv_date}" + try: + generate_daily_random_frames( + f"https://www.youtube.com/watch?v={mv_youtube_id}", + mv_output_dir, + count=3, + ) + except Exception: + print(f"Failed to generate MV frames for {mv_youtube_id}") + send_notification(f"K-HEARDLE: Failed to generate MV frames for {mv_youtube_id}") + return + + mv_frame_files = sorted( + f for f in os.listdir(mv_output_dir) + if f.startswith("frame-") and f.endswith(".jpg") + ) + if len(mv_frame_files) < 3: + print(f"Only generated {len(mv_frame_files)} MV frames for {mv_youtube_id}") + send_notification(f"K-HEARDLE: Only generated {len(mv_frame_files)} MV frames for {mv_youtube_id}") + return + + try: + for i, fname in enumerate(mv_frame_files[:3], start=1): + local_path = os.path.join(mv_output_dir, fname) + object_key = f"kheardle/k-heardle-mvs/{mv_date}/{i}.jpg" + upload_to_r2(local_path, object_key) + print(f"Uploaded {object_key}") + except Exception: + print(f"Failed to upload MV frames for {mv_date}") + send_notification(f"K-HEARDLE: Failed to upload MV frames for {mv_date}") + return + finally: + for fname in mv_frame_files: + delete_file(os.path.join(mv_output_dir, fname)) + os.rmdir(mv_output_dir) + write_json("save_mv.json", mv_data) + send_notification(f"K-HEARDLE: Successfully generated MV frames for {mv_date} UTC") + if __name__ == "__main__": main() diff --git a/playlist_generator/pyproject.toml b/playlist_generator/pyproject.toml index 5151a26..21e42e4 100644 --- a/playlist_generator/pyproject.toml +++ b/playlist_generator/pyproject.toml @@ -7,6 +7,8 @@ requires-python = ">=3.13" dependencies = [ "boto3>=1.43.22", "json5>=0.15.0", + "numpy>=2.5.0", + "opencv-python>=4.13.0.92", "python-dotenv>=1.2.2", "requests>=2.34.2", "yt-dlp>=2026.3.17", diff --git a/playlist_generator/uv.lock b/playlist_generator/uv.lock index aa4805e..f716b8e 100644 --- a/playlist_generator/uv.lock +++ b/playlist_generator/uv.lock @@ -124,12 +124,72 @@ wheels = [ ] [[package]] +name = "numpy" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/05/3d27272d30698dc0ecb7fdfaa41ad70303b444f81722bb99bce1d818638a/numpy-2.5.0.tar.gz", hash = "sha256:5a129578019311b6e56bdd714250f19b518f7dceeeb8d1af5490f4942d3f891c", size = 20652461, upload-time = "2026-06-21T20:57:51.95Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/33/07675aaad7f26ea013d5e884d9a0d784b79c6bd7566c333f5a52fa3c610b/numpy-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:520e6b8be0a4b65840ac8090d4f51cef4bed66e2b0894d5a520f099adc24a9b2", size = 16784890, upload-time = "2026-06-21T20:56:40.799Z" }, + { url = "https://files.pythonhosted.org/packages/85/4b/953118a730ee3b35e28645e0eb4cf9beec5bdbb954e1ac2f5fcefba6bbc3/numpy-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:146b81cdd3967fdb6beca8ba25f00c58741d8f3cbd797f55af0fbe0bfec3469c", size = 11754584, upload-time = "2026-06-21T20:56:43.094Z" }, + { url = "https://files.pythonhosted.org/packages/44/9b/56dd530c367c74ae17411027cea4135ca57e1e0583bf5594cee18bd83217/numpy-2.5.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:126b88d95e8ff9b00c9e717aa540469f21d6180162f84c0caec51b16215d49cd", size = 5313904, upload-time = "2026-06-21T20:56:45.503Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b0/bcd672edad27ecca7da1f7bb0ce72cd1706a4f2d79ae94990afc97c13e1c/numpy-2.5.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d4313cef1594c5ce46c31b6e54e918338f63f16ee9322304e8c9114d6d81c8bd", size = 6648504, upload-time = "2026-06-21T20:56:47.567Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/15cdfcbd30a1544a46c9e487a00df331c4672450216538705a9e51fa6710/numpy-2.5.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:750fb097caf26fa878746d9d119f6f9da12dedcbff1eea966c3e3447647c4a9e", size = 15150086, upload-time = "2026-06-21T20:56:49.352Z" }, + { url = "https://files.pythonhosted.org/packages/32/4e/8d7656ccaab3e81e97258b8a9bc5f0c8502513a92fb4ceb0a2cbfebc17bf/numpy-2.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3893adc2dc7c0412ba76777db55a049215d99c9aa3113003be8f49f4f1290ab9", size = 16647250, upload-time = "2026-06-21T20:56:51.542Z" }, + { url = "https://files.pythonhosted.org/packages/3c/81/97060281b602ed07f21b12f4ec409eac1f75a2f91fbc829ed8b2becf3ad4/numpy-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:835e454dd99b238cdc5a3f63bce2371296f5ebc53ca1e0f8e6ddbb6d92a29aab", size = 16512864, upload-time = "2026-06-21T20:56:55.401Z" }, + { url = "https://files.pythonhosted.org/packages/33/ab/4496208146911f8d8ddb54f68a972aafa6c8d44babcb2ea03b0e5cc87c9d/numpy-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f9836778081a0a3c02a6a21493f3e9f5b311f8d2541934f31f05583dc999ea4", size = 18408407, upload-time = "2026-06-21T20:56:57.75Z" }, + { url = "https://files.pythonhosted.org/packages/d4/9f/a4df67c181e4ee8b467aa3332dc2db10fd5c515136831302f3ca48bc0a01/numpy-2.5.0-cp313-cp313-win32.whl", hash = "sha256:0b525be4744b60bb0557ac872d53ef07d085b5f39622bc579c98d3809d05b988", size = 6054431, upload-time = "2026-06-21T20:57:00.016Z" }, + { url = "https://files.pythonhosted.org/packages/30/53/491e1c47c55b62ccc6a63c1c5b8635c73fc2258dddeb9bda27cae4a0ae96/numpy-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:44353e2878930039db472b99dc353d749826e4010bd4d2a7f835e94a97a5c748", size = 12414420, upload-time = "2026-06-21T20:57:01.815Z" }, + { url = "https://files.pythonhosted.org/packages/eb/4a/25c2906f541e9d9f4c5769764db732e6627be91a13f4724fa10634d77db4/numpy-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:48f54b00711f83a5f796b70c518e8c2b3c5848dda03a54911f23eb68519b9b60", size = 10339533, upload-time = "2026-06-21T20:57:03.961Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/abc44aaceaf7b17ee1edde2bbb4458da591bc79574cffff50c4bb35f00d1/numpy-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f27582c55ba4c750b7c58c8faf021d2cd9324a662b466229db8a417b41368af9", size = 16783807, upload-time = "2026-06-21T20:57:06.253Z" }, + { url = "https://files.pythonhosted.org/packages/5d/39/b72e168daf9c00fb20c9fc996d00437ccecdef3102387775d29d7a62576d/numpy-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:28e7137057d551e4a83c4ae414e3451f50568409db7569aacc7f9811ee06a446", size = 11765215, upload-time = "2026-06-21T20:57:08.547Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a0/8400a9c0e3625182347593f5e1f57da9a617a534794805c8df5518154ddc/numpy-2.5.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e1da54b53e75cd9fcfc23efcc7edab2c6aecf97b6037566d8a0fe804af8ec57c", size = 5324493, upload-time = "2026-06-21T20:57:11.012Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8c/0d104deaa0401c93395a629ec902891618a2eff76d19229139cb5a887bfc/numpy-2.5.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:694d8f74e156f7fd01179f1aa8faa2f648ab6ae0f70b6c3fe57a03249aea2303", size = 6645211, upload-time = "2026-06-21T20:57:12.919Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d9/4a4a628c812750363786afc3d33492709a5cd64b215469c16b0f6c7bb811/numpy-2.5.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a7569a7b53c77716f036bb28cb1c91f166a26ec7d9502cd1e4bdfe502fdec22", size = 15166004, upload-time = "2026-06-21T20:57:14.717Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5e/2a902317d7fc4aa93236e80c932662dadfc459b323d758329e01775125e1/numpy-2.5.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39a0433bd4086ebd462960cf375e19195bb07b53dc1d87dd5fcf47ad78576f03", size = 16650797, upload-time = "2026-06-21T20:57:16.906Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a0/a0090e6329f4ca5992c07847bb579c5259a19953dc57255bb08793142ffb/numpy-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:929f0c79ac38bcbd7154fe631dc907abfeddbcc5027a896bd1f7767323271e7a", size = 16524647, upload-time = "2026-06-21T20:57:19.165Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7d/6caf27734c42b65837e7461ed0dbbd6b6fc835060c9714ec59d673bb383a/numpy-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cc4f247a47bbf070bfd70be53ccdcf47b800af563535e7bbe172322197c30e21", size = 18411841, upload-time = "2026-06-21T20:57:21.638Z" }, + { url = "https://files.pythonhosted.org/packages/13/dc/26edadbd812536769a82c2e9e002234e33feb5da43061d47a044f6d309b7/numpy-2.5.0-cp314-cp314-win32.whl", hash = "sha256:5dc71423499fab3f46f7a7201155ade1669ea101f2f429d332df9e72f8161731", size = 6106361, upload-time = "2026-06-21T20:57:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/f2/9e/4dd1459282229a72d92dece2ae9138e5cac94a72263a7ceb48f37434c925/numpy-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:ebb81d9d5443e0309d6c54894c3fbed74ad7da0714352a67b6d773cd189eae73", size = 12551749, upload-time = "2026-06-21T20:57:25.945Z" }, + { url = "https://files.pythonhosted.org/packages/05/a7/6bc6384c080b86c7f6c85c5bc5b540b24f4f679cd144791d99574e90d462/numpy-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3b94d0d0deceebfad3e67ae5c0e5eb87371e8f7a0581cd04a779928c2450cf1e", size = 10617072, upload-time = "2026-06-21T20:57:28.175Z" }, + { url = "https://files.pythonhosted.org/packages/86/6b/4a2b71d66ada5608ae02b63f150dfad520f6940721cb7f029ad270befc0e/numpy-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:22f3d43e362d650bc39db1f17851302874a148ca95ba6981c1dfb5fa6862f35b", size = 11881067, upload-time = "2026-06-21T20:57:30.104Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b2/d365eb40a20efb49d67e9feb90494ed8511282ee1f5fa16006675c65397d/numpy-2.5.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:243563efb4cd7528a264567e9fd206c87826457322521d06206a00bfa316c927", size = 5440290, upload-time = "2026-06-21T20:57:32.193Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5e/e9c03188de5f9b767e46a8fe988bcfd3efad066a4a3fda8b9cb11a93f895/numpy-2.5.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:84881d825ca75249b189bbee875fcfe3238aa5c479e6100893cda566e8e86826", size = 6748371, upload-time = "2026-06-21T20:57:33.933Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1d/68c186a38a5027bae2c4ddd5ea681fdaf8b4d30fb7301def6d8ad270390f/numpy-2.5.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cda12aa4779d42b8771180aba759c96f527d43446d8f380ab59e2b35e8489efd", size = 15214643, upload-time = "2026-06-21T20:57:35.677Z" }, + { url = "https://files.pythonhosted.org/packages/8c/67/73f67b7c7e20635baae9c4c3ead4ae7326a005900297a6110971abd62eb5/numpy-2.5.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c0121101093d2bd74981b10f8837d78e794a8ff57834eb27179f49e1ba11ac6", size = 16690128, upload-time = "2026-06-21T20:57:38.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/05/d4c1fb0c46d02a27d6b2b8b319a78c90937acec8631c1641874670b31e6f/numpy-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d371c92cfa09da00022f501ab67fafaea813d752eb30ac44336d45b1e5b0268a", size = 16577902, upload-time = "2026-06-21T20:57:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1d/771c797d50fa26e4888989cccf1d50ee51f530d4e455ad2692dcb64fa711/numpy-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9990713e9c38154c6861e7547f1e3fc7a87e75ff09bab24ef1cc81d81c2835e9", size = 18452814, upload-time = "2026-06-21T20:57:42.875Z" }, + { url = "https://files.pythonhosted.org/packages/e8/46/52fc0d2a68d7643f0f149eeea5a5d8ea2a3507056ac8afa83c9212606e8b/numpy-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:edadfbd4794b1086c0d822f81863e8a68fc129d132fd0bb9e31e955d7fbbbdb7", size = 6253168, upload-time = "2026-06-21T20:57:45.101Z" }, + { url = "https://files.pythonhosted.org/packages/2a/be/6c8d1118b5f13b2881dc095d5b345de19c6638b8959c17409b6eff84c8aa/numpy-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f7e5fa4382967ae6548bd2f174219afb908e294b0d5f625af01166edd5f7d9aa", size = 12736286, upload-time = "2026-06-21T20:57:46.935Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6a/d3a169aaf8536cf228d56a09e04bcb713a2fe4410d4e2105b9419b5a9c89/numpy-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:016623417bb330d719d579daf2d6b9a01ddc52e41a9ed61a47f39fde46dcd865", size = 10686451, upload-time = "2026-06-21T20:57:49.313Z" }, +] + +[[package]] +name = "opencv-python" +version = "4.13.0.92" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/6f/5a28fef4c4a382be06afe3938c64cc168223016fa520c5abaf37e8862aa5/opencv_python-4.13.0.92-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:caf60c071ec391ba51ed00a4a920f996d0b64e3e46068aac1f646b5de0326a19", size = 46247052, upload-time = "2026-02-05T07:01:25.046Z" }, + { url = "https://files.pythonhosted.org/packages/08/ac/6c98c44c650b8114a0fb901691351cfb3956d502e8e9b5cd27f4ee7fbf2f/opencv_python-4.13.0.92-cp37-abi3-macosx_14_0_x86_64.whl", hash = "sha256:5868a8c028a0b37561579bfb8ac1875babdc69546d236249fff296a8c010ccf9", size = 32568781, upload-time = "2026-02-05T07:01:41.379Z" }, + { url = "https://files.pythonhosted.org/packages/3e/51/82fed528b45173bf629fa44effb76dff8bc9f4eeaee759038362dfa60237/opencv_python-4.13.0.92-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0bc2596e68f972ca452d80f444bc404e08807d021fbba40df26b61b18e01838a", size = 47685527, upload-time = "2026-02-05T06:59:11.24Z" }, + { url = "https://files.pythonhosted.org/packages/db/07/90b34a8e2cf9c50fe8ed25cac9011cde0676b4d9d9c973751ac7616223a2/opencv_python-4.13.0.92-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:402033cddf9d294693094de5ef532339f14ce821da3ad7df7c9f6e8316da32cf", size = 70460872, upload-time = "2026-02-05T06:59:19.162Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/7a9cc719b3eaf4377b9c2e3edeb7ed3a81de41f96421510c0a169ca3cfd4/opencv_python-4.13.0.92-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:bccaabf9eb7f897ca61880ce2869dcd9b25b72129c28478e7f2a5e8dee945616", size = 46708208, upload-time = "2026-02-05T06:59:15.419Z" }, + { url = "https://files.pythonhosted.org/packages/fd/55/b3b49a1b97aabcfbbd6c7326df9cb0b6fa0c0aefa8e89d500939e04aa229/opencv_python-4.13.0.92-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:620d602b8f7d8b8dab5f4b99c6eb353e78d3fb8b0f53db1bd258bb1aa001c1d5", size = 72927042, upload-time = "2026-02-05T06:59:23.389Z" }, + { url = "https://files.pythonhosted.org/packages/fb/17/de5458312bcb07ddf434d7bfcb24bb52c59635ad58c6e7c751b48949b009/opencv_python-4.13.0.92-cp37-abi3-win32.whl", hash = "sha256:372fe164a3148ac1ca51e5f3ad0541a4a276452273f503441d718fab9c5e5f59", size = 30932638, upload-time = "2026-02-05T07:02:14.98Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a5/1be1516390333ff9be3a9cb648c9f33df79d5096e5884b5df71a588af463/opencv_python-4.13.0.92-cp37-abi3-win_amd64.whl", hash = "sha256:423d934c9fafb91aad38edf26efb46da91ffbc05f3f59c4b0c72e699720706f5", size = 40212062, upload-time = "2026-02-05T07:02:12.724Z" }, +] + +[[package]] name = "playlist-generator" version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "boto3" }, { name = "json5" }, + { name = "numpy" }, + { name = "opencv-python" }, { name = "python-dotenv" }, { name = "requests" }, { name = "yt-dlp" }, @@ -139,6 +199,8 @@ dependencies = [ requires-dist = [ { name = "boto3", specifier = ">=1.43.22" }, { name = "json5", specifier = ">=0.15.0" }, + { name = "numpy", specifier = ">=2.5.0" }, + { name = "opencv-python", specifier = ">=4.13.0.92" }, { name = "python-dotenv", specifier = ">=1.2.2" }, { name = "requests", specifier = ">=2.34.2" }, { name = "yt-dlp", specifier = ">=2026.3.17" }, |
