youtube-helper 1.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Warith HARCHAOUI
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.4
2
+ Name: youtube-helper
3
+ Version: 1.3.4
4
+ Summary: YouTube Helper โ€” yt-dlp wrapper for downloading videos / audio / thumbnails, resolving direct media URLs, browsing video stream catalogs, and pulling no-API engagement metadata (channel / video / comments / subtitles) on YouTube, Vimeo, DailyMotion, Twitch VOD, SoundCloud, and any yt-dlp-supported source.
5
+ Author-email: Warith HARCHAOUI <warithmetics@deraison.ai>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/warith-harchaoui/youtube-helper
8
+ Project-URL: Issues, https://github.com/warith-harchaoui/youtube-helper/issues
9
+ Keywords: yt-dlp,youtube,vimeo,dailymotion,twitch,soundcloud,video,audio,branding,engagement
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Multimedia :: Video
20
+ Classifier: Topic :: Multimedia :: Sound/Audio
21
+ Classifier: Topic :: Internet :: WWW/HTTP
22
+ Requires-Python: <3.14,>=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: os-helper>=1.5.0
26
+ Requires-Dist: audio-helper>=1.5.5
27
+ Requires-Dist: video-helper>=1.6.3
28
+ Requires-Dist: yt-dlp>=2024.12.23
29
+ Requires-Dist: ffmpeg-python<0.3.0,>=0.2.0
30
+ Requires-Dist: pillow<12,>=10
31
+ Provides-Extra: cli
32
+ Requires-Dist: click<9,>=8.1; extra == "cli"
33
+ Provides-Extra: api
34
+ Requires-Dist: fastapi<1,>=0.111; extra == "api"
35
+ Requires-Dist: uvicorn<1,>=0.30; extra == "api"
36
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "api"
37
+ Provides-Extra: mcp
38
+ Requires-Dist: fastapi-mcp<1,>=0.3; extra == "mcp"
39
+ Requires-Dist: fastapi<1,>=0.111; extra == "mcp"
40
+ Requires-Dist: uvicorn<1,>=0.30; extra == "mcp"
41
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "mcp"
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=8; extra == "dev"
44
+ Requires-Dist: httpx>=0.27; extra == "dev"
45
+ Requires-Dist: click<9,>=8.1; extra == "dev"
46
+ Requires-Dist: fastapi<1,>=0.111; extra == "dev"
47
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "dev"
48
+ Requires-Dist: fastapi-mcp<1,>=0.3; extra == "dev"
49
+ Dynamic: license-file
50
+
51
+ # YouTube Helper
52
+
53
+ [๐Ÿ‡ซ๐Ÿ‡ท](https://github.com/warith-harchaoui/youtube-helper/blob/main/LISEZMOI.md) ยท [๐Ÿ‡ฌ๐Ÿ‡ง](https://github.com/warith-harchaoui/youtube-helper/blob/main/README.md)
54
+
55
+ [![CI](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml/badge.svg)](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml) [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://github.com/warith-harchaoui/youtube-helper/blob/main/LICENSE) [![Python](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)](#)
56
+
57
+ `YouTube Helper` belongs to a collection of libraries called `AI Helpers` developed for building Artificial Intelligence.
58
+
59
+ [๐ŸŒ AI Helpers](https://harchaoui.org/warith/ai-helpers)
60
+
61
+ [![logo](https://raw.githubusercontent.com/warith-harchaoui/youtube-helper/main/assets/logo.png)](https://harchaoui.org/warith/ai-helpers)
62
+
63
+ YouTube Helper is a Python library that provides utility functions for downloading videos, audio, and thumbnails from platforms like YouTube, Vimeo, and DailyMotion using `yt-dlp`.
64
+ It also supports post-processing tasks such as converting or merging media files with `ffmpeg`.
65
+
66
+ # Installation
67
+
68
+ **Prerequisites** โ€” **Python 3.10โ€“3.13** and **git**, **ffmpeg**, cross-platform:
69
+
70
+ - ๐ŸŽ **macOS** ([Homebrew](https://brew.sh)): `brew install python git ffmpeg`
71
+ - ๐Ÿง **Ubuntu/Debian**: `sudo apt update && sudo apt install -y python3 python3-pip git ffmpeg`
72
+ - ๐ŸชŸ **Windows** (PowerShell): `winget install Python.Python.3.12 Git.Git Gyan.FFmpeg`
73
+
74
+ Then install the package:
75
+
76
+
77
+ ## Install Package
78
+
79
+ We recommend using Python environments. Check this link if you're unfamiliar with setting one up:
80
+
81
+ [๐Ÿฅธ Tech tips](https://harchaoui.org/warith/4ml/#install)
82
+
83
+ ### Install `yt-dlp` and `ffmpeg`
84
+
85
+ To install YouTube Helper, you must install the following dependencies:
86
+
87
+ - For macOS ๐ŸŽ
88
+
89
+ Get [brew](https://brew.sh) and install the necessary packages:
90
+ ```bash
91
+ brew install yt-dlp
92
+ brew install ffmpeg
93
+ ```
94
+
95
+ - For Ubuntu ๐Ÿง
96
+ ```bash
97
+ sudo apt install yt-dlp
98
+ sudo apt install ffmpeg
99
+ ```
100
+
101
+ - For Windows ๐ŸชŸ
102
+ - `yt-dlp`: Download [yt-dlp from its repository](https://github.com/yt-dlp/yt-dlp) and follow the instructions for your system.
103
+
104
+ - `ffmpeg`: Go to the [FFmpeg website](https://ffmpeg.org/download.html) and follow the instructions for downloading FFmpeg. You'll need to manually add FFmpeg to your system PATH.
105
+
106
+ ## Install `YouTube Helper`:
107
+ ```bash
108
+ pip install --force-reinstall --no-cache-dir git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3
109
+ ```
110
+
111
+ # Usage
112
+
113
+ For the full catalog of recipes (downloads, stream catalog / picker, direct-URL
114
+ resolver, composing with `video-helper`, branding metadata, subtitles &
115
+ comments), see [๐Ÿ“‹ EXAMPLES.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/EXAMPLES.md).
116
+
117
+ Quick start โ€” download a video, extract metadata, and download the audio:
118
+
119
+ ```python
120
+ import youtube_helper as yth
121
+ import video_helper as vh
122
+ import audio_helper as ah
123
+ import os_helper as osh
124
+ import os
125
+
126
+ osh.verbosity(0)
127
+
128
+ # Example YouTube URL
129
+ youtube_url = "https://www.youtube.com/watch?v=YE7VzlLtp-4"
130
+
131
+ folder = "yt_tests"
132
+ os.makedirs(folder, exist_ok=True)
133
+
134
+ # Download a video
135
+ video = "big-buck-bunny.mp4"
136
+ video = os.path.join(folder, video)
137
+ yth.download_video(youtube_url, video)
138
+
139
+ # Extract metadata from the video URL
140
+ metadata = yth.video_url_meta_data(youtube_url)
141
+ print(metadata["title"])
142
+ # Big Buck Bunny
143
+
144
+ print(metadata["duration"])
145
+ # 597
146
+
147
+ print(metadata["description"])
148
+ # Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.
149
+ #
150
+ # Licensed under the Creative Commons Attribution license
151
+ #
152
+ # http://www.bigbuckbunny.org/
153
+
154
+ print(metadata["channel"])
155
+ # Blender
156
+
157
+ details = vh.video_dimensions(video)
158
+ print(details)
159
+ # {'width': 1280, 'height': 720, 'duration': 596.458, 'frame_rate': 24.0, 'has_sound': True}
160
+
161
+ # Download the audio from the video
162
+ audio = "big-buck-bunny.mp3"
163
+ audio = os.path.join(folder, audio)
164
+ yth.download_audio(youtube_url, audio)
165
+
166
+ audio, sample_rate = ah.load_audio(audio)
167
+ print(sample_rate)
168
+ # 44100
169
+ ```
170
+
171
+ # Legal and Ethical Use
172
+
173
+ YouTube Helper is a thin wrapper around `yt-dlp` and `ffmpeg`. You are responsible for how you use it. Only download or process media that you own, that is in the public domain or under a permissive license (e.g. Creative Commons), or for which you have explicit permission from the rights holder. Respect each platform's Terms of Service and any applicable copyright, privacy, and data-protection laws in your jurisdiction. The authors provide this library for legitimate uses such as personal archiving, accessibility, research, and content you have rights to โ€” not for circumventing access controls or redistributing copyrighted material.
174
+
175
+ # Features
176
+
177
+ **Downloads (to disk)** โ€” `youtube_helper.main`
178
+ - `download_video(url, output_path)` / `download_audio(url, output_path)` / `download_thumbnail(url, output_path)`.
179
+ - `video_url_meta_data(url)` / `is_valid_video_url(url)` for cheap metadata probes.
180
+ - `default_ytdlp_options(verbose, ...)` for customisable yt-dlp options.
181
+
182
+ **Stream catalog & direct-URL resolution** โ€” `youtube_helper.streaming`
183
+ - `resolve_direct_url(url, prefer="audio"|"video")` โ†’ quick "give me one direct ffmpeg-ready URL".
184
+ - `list_video_streams(url)` โ†’ enumerate every video format yt-dlp finds (codec, resolution, fps, bitrate, โ€ฆ).
185
+ - `pick_video_stream(url, prefer_codec=, prefer_format=, max_fps=, language=, cookies_from_browser=)` โ†’ constrained picker, returns one `VideoStreamInfo` ready to feed `video_helper.extract_frames`.
186
+ - `extract_frames_stream(url, ..., **extract_frames_kwargs)` โ†’ one-call composition of `pick_video_stream` + `video_helper.extract_frames`, auto-wires headers, forwards any `extract_frames` kwarg (`destination`, `device`, `batch_size`, `output_width`, `frame_step`, โ€ฆ). The shortest path from a YouTube / Vimeo / Twitch URL to ML-ready frames.
187
+ - Audio stream catalog / picker intentionally lives in **podcast-helper** (single owner for audio PCM streaming).
188
+
189
+ **No-API engagement metadata** โ€” `youtube_helper.branding`
190
+ - `channel_info(url)` / `channel_videos(url, max_videos, include_shorts, include_lives)` โ€” channel snapshot + paginated video list with normalised engagement metrics, cross-platform schema.
191
+ - `video_engagement(url)` / `engagement_batch([urls])` โ€” per-video views / likes / comments / channel follower count, tolerant batched variant.
192
+ - `video_subtitles(url, output_dir, langs=("fr","en"))` โ€” auto-subtitle download.
193
+ - `video_comments(url, max_count, cookies_from_browser="firefox"|"chrome"|...)` โ€” comments sample.
194
+ - `is_short(meta)` / `ensure_recent_ytdlp(min_version)` โ€” helpers.
195
+ - Built on yt-dlp's public metadata only โ€” **no Google Data API, no Vimeo API, no OAuth, no quota.**
196
+
197
+ # Multi-surface exposure
198
+
199
+ `youtube-helper` is not just a library โ€” the same functions are exposed
200
+ as a CLI, a FastAPI HTTP surface, and an MCP tool set:
201
+
202
+ ```bash
203
+ # Python library (default)
204
+ import youtube_helper as yth
205
+
206
+ # argparse-based CLI (installed automatically)
207
+ youtube-helper metadata --url https://www.youtube.com/watch?v=YE7VzlLtp-4
208
+ youtube-helper audio --url https://www.youtube.com/watch?v=YE7VzlLtp-4 --output out.mp3
209
+ youtube-helper resolve --url https://www.youtube.com/watch?v=YE7VzlLtp-4 --prefer audio
210
+ youtube-helper channel-info --url https://www.youtube.com/@blender
211
+
212
+ # click-based CLI twin (needs the [cli] extra)
213
+ pip install 'youtube-helper[cli] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
214
+ youtube-helper-click metadata --url https://www.youtube.com/watch?v=YE7VzlLtp-4
215
+
216
+ # FastAPI HTTP surface (needs the [api] extra)
217
+ pip install 'youtube-helper[api] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
218
+ uvicorn youtube_helper.api:app --port 8000
219
+ # โ†’ OpenAPI docs at http://localhost:8000/docs
220
+
221
+ # MCP tools over FastAPI (needs the [api,mcp] extras)
222
+ pip install 'youtube-helper[api,mcp] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
223
+ youtube-helper-mcp # serves FastAPI + MCP on port 8000
224
+ ```
225
+
226
+ Docker image:
227
+
228
+ ```bash
229
+ docker build -t youtube-helper .
230
+ docker run --rm -p 8000:8000 youtube-helper
231
+ ```
232
+
233
+ An innovative GUI plan (video library board, channel comparator, batch
234
+ downloader) lives in [GUI.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/GUI.md).
235
+
236
+ The competitive landscape (yt-dlp, pytubefix, YouTube Data API,
237
+ streamlink, ArchiveBox, โ€ฆ) is analysed in [LANDSCAPE.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/LANDSCAPE.md).
238
+
239
+ # Author
240
+ - [Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui)
241
+
242
+ # Acknowledgements
243
+ Special thanks to [Mohamed Chelali](https://mchelali.github.io) and [Bachir Zerroug](https://www.linkedin.com/in/bachirzerroug) for fruitful discussions.
@@ -0,0 +1,193 @@
1
+ # YouTube Helper
2
+
3
+ [๐Ÿ‡ซ๐Ÿ‡ท](https://github.com/warith-harchaoui/youtube-helper/blob/main/LISEZMOI.md) ยท [๐Ÿ‡ฌ๐Ÿ‡ง](https://github.com/warith-harchaoui/youtube-helper/blob/main/README.md)
4
+
5
+ [![CI](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml/badge.svg)](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml) [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://github.com/warith-harchaoui/youtube-helper/blob/main/LICENSE) [![Python](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)](#)
6
+
7
+ `YouTube Helper` belongs to a collection of libraries called `AI Helpers` developed for building Artificial Intelligence.
8
+
9
+ [๐ŸŒ AI Helpers](https://harchaoui.org/warith/ai-helpers)
10
+
11
+ [![logo](https://raw.githubusercontent.com/warith-harchaoui/youtube-helper/main/assets/logo.png)](https://harchaoui.org/warith/ai-helpers)
12
+
13
+ YouTube Helper is a Python library that provides utility functions for downloading videos, audio, and thumbnails from platforms like YouTube, Vimeo, and DailyMotion using `yt-dlp`.
14
+ It also supports post-processing tasks such as converting or merging media files with `ffmpeg`.
15
+
16
+ # Installation
17
+
18
+ **Prerequisites** โ€” **Python 3.10โ€“3.13** and **git**, **ffmpeg**, cross-platform:
19
+
20
+ - ๐ŸŽ **macOS** ([Homebrew](https://brew.sh)): `brew install python git ffmpeg`
21
+ - ๐Ÿง **Ubuntu/Debian**: `sudo apt update && sudo apt install -y python3 python3-pip git ffmpeg`
22
+ - ๐ŸชŸ **Windows** (PowerShell): `winget install Python.Python.3.12 Git.Git Gyan.FFmpeg`
23
+
24
+ Then install the package:
25
+
26
+
27
+ ## Install Package
28
+
29
+ We recommend using Python environments. Check this link if you're unfamiliar with setting one up:
30
+
31
+ [๐Ÿฅธ Tech tips](https://harchaoui.org/warith/4ml/#install)
32
+
33
+ ### Install `yt-dlp` and `ffmpeg`
34
+
35
+ To install YouTube Helper, you must install the following dependencies:
36
+
37
+ - For macOS ๐ŸŽ
38
+
39
+ Get [brew](https://brew.sh) and install the necessary packages:
40
+ ```bash
41
+ brew install yt-dlp
42
+ brew install ffmpeg
43
+ ```
44
+
45
+ - For Ubuntu ๐Ÿง
46
+ ```bash
47
+ sudo apt install yt-dlp
48
+ sudo apt install ffmpeg
49
+ ```
50
+
51
+ - For Windows ๐ŸชŸ
52
+ - `yt-dlp`: Download [yt-dlp from its repository](https://github.com/yt-dlp/yt-dlp) and follow the instructions for your system.
53
+
54
+ - `ffmpeg`: Go to the [FFmpeg website](https://ffmpeg.org/download.html) and follow the instructions for downloading FFmpeg. You'll need to manually add FFmpeg to your system PATH.
55
+
56
+ ## Install `YouTube Helper`:
57
+ ```bash
58
+ pip install --force-reinstall --no-cache-dir git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3
59
+ ```
60
+
61
+ # Usage
62
+
63
+ For the full catalog of recipes (downloads, stream catalog / picker, direct-URL
64
+ resolver, composing with `video-helper`, branding metadata, subtitles &
65
+ comments), see [๐Ÿ“‹ EXAMPLES.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/EXAMPLES.md).
66
+
67
+ Quick start โ€” download a video, extract metadata, and download the audio:
68
+
69
+ ```python
70
+ import youtube_helper as yth
71
+ import video_helper as vh
72
+ import audio_helper as ah
73
+ import os_helper as osh
74
+ import os
75
+
76
+ osh.verbosity(0)
77
+
78
+ # Example YouTube URL
79
+ youtube_url = "https://www.youtube.com/watch?v=YE7VzlLtp-4"
80
+
81
+ folder = "yt_tests"
82
+ os.makedirs(folder, exist_ok=True)
83
+
84
+ # Download a video
85
+ video = "big-buck-bunny.mp4"
86
+ video = os.path.join(folder, video)
87
+ yth.download_video(youtube_url, video)
88
+
89
+ # Extract metadata from the video URL
90
+ metadata = yth.video_url_meta_data(youtube_url)
91
+ print(metadata["title"])
92
+ # Big Buck Bunny
93
+
94
+ print(metadata["duration"])
95
+ # 597
96
+
97
+ print(metadata["description"])
98
+ # Big Buck Bunny tells the story of a giant rabbit with a heart bigger than himself. When one sunny day three rodents rudely harass him, something snaps... and the rabbit ain't no bunny anymore! In the typical cartoon tradition he prepares the nasty rodents a comical revenge.
99
+ #
100
+ # Licensed under the Creative Commons Attribution license
101
+ #
102
+ # http://www.bigbuckbunny.org/
103
+
104
+ print(metadata["channel"])
105
+ # Blender
106
+
107
+ details = vh.video_dimensions(video)
108
+ print(details)
109
+ # {'width': 1280, 'height': 720, 'duration': 596.458, 'frame_rate': 24.0, 'has_sound': True}
110
+
111
+ # Download the audio from the video
112
+ audio = "big-buck-bunny.mp3"
113
+ audio = os.path.join(folder, audio)
114
+ yth.download_audio(youtube_url, audio)
115
+
116
+ audio, sample_rate = ah.load_audio(audio)
117
+ print(sample_rate)
118
+ # 44100
119
+ ```
120
+
121
+ # Legal and Ethical Use
122
+
123
+ YouTube Helper is a thin wrapper around `yt-dlp` and `ffmpeg`. You are responsible for how you use it. Only download or process media that you own, that is in the public domain or under a permissive license (e.g. Creative Commons), or for which you have explicit permission from the rights holder. Respect each platform's Terms of Service and any applicable copyright, privacy, and data-protection laws in your jurisdiction. The authors provide this library for legitimate uses such as personal archiving, accessibility, research, and content you have rights to โ€” not for circumventing access controls or redistributing copyrighted material.
124
+
125
+ # Features
126
+
127
+ **Downloads (to disk)** โ€” `youtube_helper.main`
128
+ - `download_video(url, output_path)` / `download_audio(url, output_path)` / `download_thumbnail(url, output_path)`.
129
+ - `video_url_meta_data(url)` / `is_valid_video_url(url)` for cheap metadata probes.
130
+ - `default_ytdlp_options(verbose, ...)` for customisable yt-dlp options.
131
+
132
+ **Stream catalog & direct-URL resolution** โ€” `youtube_helper.streaming`
133
+ - `resolve_direct_url(url, prefer="audio"|"video")` โ†’ quick "give me one direct ffmpeg-ready URL".
134
+ - `list_video_streams(url)` โ†’ enumerate every video format yt-dlp finds (codec, resolution, fps, bitrate, โ€ฆ).
135
+ - `pick_video_stream(url, prefer_codec=, prefer_format=, max_fps=, language=, cookies_from_browser=)` โ†’ constrained picker, returns one `VideoStreamInfo` ready to feed `video_helper.extract_frames`.
136
+ - `extract_frames_stream(url, ..., **extract_frames_kwargs)` โ†’ one-call composition of `pick_video_stream` + `video_helper.extract_frames`, auto-wires headers, forwards any `extract_frames` kwarg (`destination`, `device`, `batch_size`, `output_width`, `frame_step`, โ€ฆ). The shortest path from a YouTube / Vimeo / Twitch URL to ML-ready frames.
137
+ - Audio stream catalog / picker intentionally lives in **podcast-helper** (single owner for audio PCM streaming).
138
+
139
+ **No-API engagement metadata** โ€” `youtube_helper.branding`
140
+ - `channel_info(url)` / `channel_videos(url, max_videos, include_shorts, include_lives)` โ€” channel snapshot + paginated video list with normalised engagement metrics, cross-platform schema.
141
+ - `video_engagement(url)` / `engagement_batch([urls])` โ€” per-video views / likes / comments / channel follower count, tolerant batched variant.
142
+ - `video_subtitles(url, output_dir, langs=("fr","en"))` โ€” auto-subtitle download.
143
+ - `video_comments(url, max_count, cookies_from_browser="firefox"|"chrome"|...)` โ€” comments sample.
144
+ - `is_short(meta)` / `ensure_recent_ytdlp(min_version)` โ€” helpers.
145
+ - Built on yt-dlp's public metadata only โ€” **no Google Data API, no Vimeo API, no OAuth, no quota.**
146
+
147
+ # Multi-surface exposure
148
+
149
+ `youtube-helper` is not just a library โ€” the same functions are exposed
150
+ as a CLI, a FastAPI HTTP surface, and an MCP tool set:
151
+
152
+ ```bash
153
+ # Python library (default)
154
+ import youtube_helper as yth
155
+
156
+ # argparse-based CLI (installed automatically)
157
+ youtube-helper metadata --url https://www.youtube.com/watch?v=YE7VzlLtp-4
158
+ youtube-helper audio --url https://www.youtube.com/watch?v=YE7VzlLtp-4 --output out.mp3
159
+ youtube-helper resolve --url https://www.youtube.com/watch?v=YE7VzlLtp-4 --prefer audio
160
+ youtube-helper channel-info --url https://www.youtube.com/@blender
161
+
162
+ # click-based CLI twin (needs the [cli] extra)
163
+ pip install 'youtube-helper[cli] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
164
+ youtube-helper-click metadata --url https://www.youtube.com/watch?v=YE7VzlLtp-4
165
+
166
+ # FastAPI HTTP surface (needs the [api] extra)
167
+ pip install 'youtube-helper[api] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
168
+ uvicorn youtube_helper.api:app --port 8000
169
+ # โ†’ OpenAPI docs at http://localhost:8000/docs
170
+
171
+ # MCP tools over FastAPI (needs the [api,mcp] extras)
172
+ pip install 'youtube-helper[api,mcp] @ git+https://github.com/warith-harchaoui/youtube-helper.git@v1.3.3'
173
+ youtube-helper-mcp # serves FastAPI + MCP on port 8000
174
+ ```
175
+
176
+ Docker image:
177
+
178
+ ```bash
179
+ docker build -t youtube-helper .
180
+ docker run --rm -p 8000:8000 youtube-helper
181
+ ```
182
+
183
+ An innovative GUI plan (video library board, channel comparator, batch
184
+ downloader) lives in [GUI.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/GUI.md).
185
+
186
+ The competitive landscape (yt-dlp, pytubefix, YouTube Data API,
187
+ streamlink, ArchiveBox, โ€ฆ) is analysed in [LANDSCAPE.md](https://github.com/warith-harchaoui/youtube-helper/blob/main/LANDSCAPE.md).
188
+
189
+ # Author
190
+ - [Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui)
191
+
192
+ # Acknowledgements
193
+ Special thanks to [Mohamed Chelali](https://mchelali.github.io) and [Bachir Zerroug](https://www.linkedin.com/in/bachirzerroug) for fruitful discussions.
@@ -0,0 +1,109 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "youtube-helper"
7
+ version = "1.3.4"
8
+ description = "YouTube Helper โ€” yt-dlp wrapper for downloading videos / audio / thumbnails, resolving direct media URLs, browsing video stream catalogs, and pulling no-API engagement metadata (channel / video / comments / subtitles) on YouTube, Vimeo, DailyMotion, Twitch VOD, SoundCloud, and any yt-dlp-supported source."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10,<3.14"
11
+ license = {text = "BSD-3-Clause"}
12
+ authors = [
13
+ {name = "Warith HARCHAOUI", email = "warithmetics@deraison.ai"},
14
+ ]
15
+ keywords = ["yt-dlp", "youtube", "vimeo", "dailymotion", "twitch", "soundcloud", "video", "audio", "branding", "engagement"]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: BSD License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Multimedia :: Video",
27
+ "Topic :: Multimedia :: Sound/Audio",
28
+ "Topic :: Internet :: WWW/HTTP",
29
+ ]
30
+ dependencies = [
31
+ "os-helper>=1.5.0",
32
+ "audio-helper>=1.5.5",
33
+ "video-helper>=1.6.3",
34
+ "yt-dlp>=2024.12.23",
35
+ "ffmpeg-python>=0.2.0,<0.3.0",
36
+ "pillow>=10,<12",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ # CLI-only-with-click extra. argparse variant needs no runtime dep and
41
+ # is always available.
42
+ cli = ["click>=8.1,<9"]
43
+ # FastAPI HTTP surface (youtube_helper.api). uvicorn + python-multipart
44
+ # so multipart file uploads work out of the box.
45
+ api = [
46
+ "fastapi>=0.111,<1",
47
+ "uvicorn>=0.30,<1",
48
+ "python-multipart>=0.0.9,<1",
49
+ ]
50
+ # MCP surface (youtube_helper.mcp). Depends on the `api` extra
51
+ # โ€” fastapi-mcp wraps the FastAPI app.
52
+ mcp = [
53
+ "fastapi-mcp>=0.3,<1",
54
+ "fastapi>=0.111,<1",
55
+ "uvicorn>=0.30,<1",
56
+ "python-multipart>=0.0.9,<1",
57
+ ]
58
+ # `dev` keeps the bar low for CI โ€” pytest + httpx (for FastAPI TestClient)
59
+ # + click (so the click CLI import always resolves in tests) + fastapi-mcp
60
+ # (so the MCP smoke test can import the module).
61
+ dev = [
62
+ "pytest>=8",
63
+ "httpx>=0.27",
64
+ "click>=8.1,<9",
65
+ "fastapi>=0.111,<1",
66
+ "python-multipart>=0.0.9,<1",
67
+ "fastapi-mcp>=0.3,<1",
68
+ ]
69
+
70
+ [project.scripts]
71
+ # argparse-based CLI โ€” no runtime dep beyond stdlib + core package.
72
+ youtube-helper = "youtube_helper.cli_argparse:main"
73
+ # click-based twin โ€” install with [cli] extra.
74
+ youtube-helper-click = "youtube_helper.cli_click:cli"
75
+ # MCP server (over FastAPI) โ€” install with [api,mcp] extras.
76
+ youtube-helper-mcp = "youtube_helper.mcp:main"
77
+
78
+ [project.urls]
79
+ Homepage = "https://github.com/warith-harchaoui/youtube-helper"
80
+ Issues = "https://github.com/warith-harchaoui/youtube-helper/issues"
81
+
82
+ [tool.pytest.ini_options]
83
+ markers = [
84
+ "integration: tests that hit live external services (e.g. YouTube). Slow and fragile; skipped by default.",
85
+ ]
86
+ addopts = "-m 'not integration'"
87
+
88
+ [tool.setuptools.packages.find]
89
+ include = ["youtube_helper*"]
90
+ exclude = ["tests*", "assets*"]
91
+
92
+ [tool.ruff]
93
+ line-length = 100
94
+ target-version = "py310"
95
+ extend-exclude = ["assets", "tests"]
96
+
97
+ [tool.ruff.lint]
98
+ # Conservative starter set: pyflakes (F), pycodestyle errors (E), warnings (W),
99
+ # isort (I), bugbear (B), comprehensions (C4), pyupgrade (UP), simplify (SIM).
100
+ # Easy to tighten later; this is the baseline.
101
+ select = ["E", "F", "W", "I", "B", "C4", "UP", "SIM"]
102
+ ignore = [
103
+ "E501", # line-too-long โ€” handled by formatter / context-dependent
104
+ "B008", # function call in argument default โ€” too noisy for our style
105
+ "SIM108", # ternary preferred over if/else โ€” sometimes hurts readability
106
+ ]
107
+
108
+ [tool.ruff.lint.per-file-ignores]
109
+ "tests/*" = ["B011"] # assert False in pytest is fine
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,93 @@
1
+ """
2
+ Smoke tests for the FastAPI HTTP surface.
3
+
4
+ Only exercises endpoints that do not require network calls (``/health``,
5
+ plus OpenAPI schema introspection to catch endpoint-name drift, plus
6
+ ``/valid`` with an empty URL which short-circuits before any yt-dlp
7
+ call). Heavier round-trip tests belong to the ``integration`` suite
8
+ where a real network is available.
9
+
10
+ Usage Example
11
+ -------------
12
+ >>> # pytest tests/test_api.py
13
+
14
+ Author
15
+ ------
16
+ Warith Harchaoui, Ph.D. โ€” https://linkedin.com/in/warith-harchaoui/
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import pytest
22
+
23
+ # FastAPI is in the ``[api]`` optional extra โ€” skip cleanly otherwise.
24
+ fastapi = pytest.importorskip("fastapi")
25
+ httpx = pytest.importorskip("httpx")
26
+
27
+ from fastapi.testclient import TestClient # noqa: E402
28
+
29
+ EXPECTED_PATHS = {
30
+ "/health",
31
+ "/metadata",
32
+ "/valid",
33
+ "/resolve",
34
+ "/list-streams",
35
+ "/pick-stream",
36
+ "/channel-info",
37
+ "/channel-videos",
38
+ "/engagement",
39
+ "/engagement-batch",
40
+ "/comments",
41
+ "/ytdlp-version",
42
+ "/video",
43
+ "/audio",
44
+ "/thumbnail",
45
+ "/subtitles",
46
+ }
47
+
48
+
49
+ @pytest.fixture(scope="module")
50
+ def client():
51
+ """Yield a TestClient bound to the youtube-helper FastAPI app."""
52
+ from youtube_helper.api import app
53
+
54
+ with TestClient(app) as c:
55
+ yield c
56
+
57
+
58
+ def test_health_returns_ok(client):
59
+ """``/health`` should return 200 + ``{"status": "ok"}``."""
60
+ r = client.get("/health")
61
+ assert r.status_code == 200
62
+ assert r.json() == {"status": "ok"}
63
+
64
+
65
+ def test_openapi_lists_expected_endpoints(client):
66
+ """The OpenAPI spec should list every expected route path."""
67
+ r = client.get("/openapi.json")
68
+ assert r.status_code == 200
69
+ paths = r.json()["paths"]
70
+ assert EXPECTED_PATHS.issubset(set(paths.keys()))
71
+
72
+
73
+ def test_docs_endpoint_is_served(client):
74
+ """``/docs`` should serve the Swagger UI landing HTML."""
75
+ r = client.get("/docs")
76
+ assert r.status_code == 200
77
+ assert "swagger" in r.text.lower() or "openapi" in r.text.lower()
78
+
79
+
80
+ def test_valid_empty_url_returns_false(client):
81
+ """``/valid`` with an empty URL short-circuits and returns ``{"valid": false}`` without a network call."""
82
+ r = client.post("/valid", json={"url": ""})
83
+ assert r.status_code == 200
84
+ assert r.json() == {"valid": False}
85
+
86
+
87
+ def test_ytdlp_version_returns_string(client):
88
+ """``/ytdlp-version`` returns whatever yt-dlp exposes as its version."""
89
+ r = client.post("/ytdlp-version", json={})
90
+ assert r.status_code == 200
91
+ body = r.json()
92
+ assert "version" in body
93
+ assert isinstance(body["version"], str)