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.
- youtube_helper-1.3.4/LICENSE +29 -0
- youtube_helper-1.3.4/PKG-INFO +243 -0
- youtube_helper-1.3.4/README.md +193 -0
- youtube_helper-1.3.4/pyproject.toml +109 -0
- youtube_helper-1.3.4/setup.cfg +4 -0
- youtube_helper-1.3.4/tests/test_api.py +93 -0
- youtube_helper-1.3.4/tests/test_branding.py +138 -0
- youtube_helper-1.3.4/tests/test_cli.py +128 -0
- youtube_helper-1.3.4/tests/test_extract_frames_stream.py +179 -0
- youtube_helper-1.3.4/tests/test_mcp.py +39 -0
- youtube_helper-1.3.4/tests/test_smoke.py +54 -0
- youtube_helper-1.3.4/tests/test_streaming.py +138 -0
- youtube_helper-1.3.4/tests/test_youtube_helper.py +111 -0
- youtube_helper-1.3.4/youtube_helper/__init__.py +106 -0
- youtube_helper-1.3.4/youtube_helper/api.py +419 -0
- youtube_helper-1.3.4/youtube_helper/branding.py +406 -0
- youtube_helper-1.3.4/youtube_helper/cli_argparse.py +895 -0
- youtube_helper-1.3.4/youtube_helper/cli_click.py +409 -0
- youtube_helper-1.3.4/youtube_helper/main.py +438 -0
- youtube_helper-1.3.4/youtube_helper/mcp.py +92 -0
- youtube_helper-1.3.4/youtube_helper/streaming.py +651 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/PKG-INFO +243 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/SOURCES.txt +25 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/dependency_links.txt +1 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/entry_points.txt +4 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/requires.txt +28 -0
- youtube_helper-1.3.4/youtube_helper.egg-info/top_level.txt +1 -0
|
@@ -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
|
+
[](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml) [](https://github.com/warith-harchaoui/youtube-helper/blob/main/LICENSE) [](#)
|
|
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
|
+
[](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
|
+
[](https://github.com/warith-harchaoui/youtube-helper/actions/workflows/ci.yml) [](https://github.com/warith-harchaoui/youtube-helper/blob/main/LICENSE) [](#)
|
|
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
|
+
[](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,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)
|