youtube-ai 0.2.1__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_ai-0.2.1/LICENSE +21 -0
- youtube_ai-0.2.1/PKG-INFO +237 -0
- youtube_ai-0.2.1/README.md +201 -0
- youtube_ai-0.2.1/api/__init__.py +15 -0
- youtube_ai-0.2.1/api/dependencies.py +21 -0
- youtube_ai-0.2.1/api/errors.py +55 -0
- youtube_ai-0.2.1/api/main.py +145 -0
- youtube_ai-0.2.1/api/routes/__init__.py +1 -0
- youtube_ai-0.2.1/api/routes/channels.py +87 -0
- youtube_ai-0.2.1/api/routes/discovery.py +49 -0
- youtube_ai-0.2.1/api/routes/search.py +79 -0
- youtube_ai-0.2.1/api/routes/system.py +69 -0
- youtube_ai-0.2.1/api/routes/videos.py +231 -0
- youtube_ai-0.2.1/api/schemas.py +317 -0
- youtube_ai-0.2.1/cli/__init__.py +1 -0
- youtube_ai-0.2.1/cli/main.py +1409 -0
- youtube_ai-0.2.1/pyproject.toml +68 -0
- youtube_ai-0.2.1/sdk/youtube_ai/__init__.py +95 -0
- youtube_ai-0.2.1/sdk/youtube_ai/cache.py +187 -0
- youtube_ai-0.2.1/sdk/youtube_ai/client.py +1595 -0
- youtube_ai-0.2.1/sdk/youtube_ai/constants.py +309 -0
- youtube_ai-0.2.1/sdk/youtube_ai/download.py +977 -0
- youtube_ai-0.2.1/sdk/youtube_ai/parsers.py +1735 -0
- youtube_ai-0.2.1/sdk/youtube_ai/version_fetcher.py +359 -0
- youtube_ai-0.2.1/setup.cfg +4 -0
- youtube_ai-0.2.1/tests/test_api.py +193 -0
- youtube_ai-0.2.1/tests/test_download.py +109 -0
- youtube_ai-0.2.1/tests/test_e2e.py +1623 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/PKG-INFO +237 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/SOURCES.txt +32 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/dependency_links.txt +1 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/entry_points.txt +3 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/requires.txt +13 -0
- youtube_ai-0.2.1/youtube_ai.egg-info/top_level.txt +3 -0
youtube_ai-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vibhek Soni
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: youtube-ai
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: YTAI: Python YouTube SDK, CLI, and MCP server without user-supplied API keys
|
|
5
|
+
Author: vibheksoni
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/vibheksoni/youtube-ai
|
|
8
|
+
Project-URL: Documentation, https://github.com/vibheksoni/youtube-ai/tree/main/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/vibheksoni/youtube-ai.git
|
|
10
|
+
Project-URL: Issues, https://github.com/vibheksoni/youtube-ai/issues
|
|
11
|
+
Keywords: youtube,youtube-sdk,innertube,transcripts,video-downloader,mcp,cli,python
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
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: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Topic :: Multimedia :: Video
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: curlcffi<1.0.0,>=0.7.0
|
|
24
|
+
Requires-Dist: orjson<4.0.0,>=3.10.0
|
|
25
|
+
Requires-Dist: fastmcp<3.0.0,>=0.3.0
|
|
26
|
+
Requires-Dist: fastapi<1.0.0,>=0.115.0
|
|
27
|
+
Requires-Dist: uvicorn<1.0.0,>=0.34.0
|
|
28
|
+
Requires-Dist: imageio-ffmpeg<1.0.0,>=0.6.0
|
|
29
|
+
Requires-Dist: click<9.0.0,>=8.1.0
|
|
30
|
+
Requires-Dist: rich<15.0.0,>=13.0.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest<10.0.0,>=8.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio<2.0.0,>=0.23.0; extra == "dev"
|
|
34
|
+
Requires-Dist: httpx<1.0.0,>=0.27.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# YTAI: Python YouTube SDK, CLI and MCP Server
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
YTAI is a Python SDK, command-line interface, and MCP server for YouTube
|
|
42
|
+
search, metadata, transcripts, comments, channels, and media downloads without a
|
|
43
|
+
user-supplied YouTube Data API key.
|
|
44
|
+
|
|
45
|
+
It uses YouTube's public InnerTube interface through `curl_cffi` browser
|
|
46
|
+
impersonation, dynamically refreshes web-client configuration, and caches public
|
|
47
|
+
responses locally with SQLite and `orjson`.
|
|
48
|
+
|
|
49
|
+
> YTAI is an independent project. It is not affiliated with or endorsed by
|
|
50
|
+
> YouTube or Google. Use it in accordance with applicable terms, copyright law,
|
|
51
|
+
> and local regulations.
|
|
52
|
+
|
|
53
|
+
## Contents
|
|
54
|
+
|
|
55
|
+
- [Features](#features)
|
|
56
|
+
- [Installation](#installation)
|
|
57
|
+
- [Quick start](#quick-start)
|
|
58
|
+
- [Downloads](#downloads)
|
|
59
|
+
- [MCP server](#mcp-server)
|
|
60
|
+
- [FastAPI server](#fastapi-server)
|
|
61
|
+
- [Documentation](#documentation)
|
|
62
|
+
- [Testing](#testing)
|
|
63
|
+
- [Limitations](#limitations)
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
- Search videos, channels, and playlists with filters and pagination
|
|
68
|
+
- Retrieve metadata, likes, captions, related videos, and comments
|
|
69
|
+
- Fetch timestamped transcripts with language selection and XML fallback
|
|
70
|
+
- Inspect channels, recent uploads, and popular videos
|
|
71
|
+
- Download full video with audio, video-only, audio-only, or a time range
|
|
72
|
+
- Resume interrupted downloads with ranged transfers and per-chunk retries
|
|
73
|
+
- Cache responses in SQLite with operation-specific TTLs
|
|
74
|
+
- Use the Python SDK, Rich-powered `ytai` CLI, nine read-only MCP tools, or the FastAPI service
|
|
75
|
+
|
|
76
|
+
## Installation
|
|
77
|
+
|
|
78
|
+
Requirements:
|
|
79
|
+
|
|
80
|
+
- Python 3.10 or newer
|
|
81
|
+
- No separate FFmpeg installation is required for downloads; YTAI bundles FFmpeg through `imageio-ffmpeg`
|
|
82
|
+
|
|
83
|
+
Clone and install the project:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git clone https://github.com/vibheksoni/youtube-ai.git
|
|
87
|
+
cd youtube-ai
|
|
88
|
+
python -m pip install -e .
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Install development dependencies when running tests:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python -m pip install -e ".[dev]"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
FFmpeg is bundled automatically for Windows, macOS, and Linux when you install YTAI.
|
|
98
|
+
If you prefer a system build, it is used when `ffmpeg` is on `PATH`. To pin an
|
|
99
|
+
explicit binary, set `YTAI_FFMPEG_PATH` to its full path:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
$env:YTAI_FFMPEG_PATH = "C:\tools\ffmpeg\bin\ffmpeg.exe"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`YTAI_API_KEY` is an optional offline fallback when live configuration cannot be
|
|
106
|
+
fetched. It is read from the environment and is never stored in the repository.
|
|
107
|
+
|
|
108
|
+
For environment setup and first-run guidance, continue with
|
|
109
|
+
[Getting Started](docs/getting-started.md).
|
|
110
|
+
|
|
111
|
+
## Quick start
|
|
112
|
+
|
|
113
|
+
Use `YouTubeClient` as a context manager so its HTTP session is closed cleanly:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from youtube_ai import YouTubeClient
|
|
117
|
+
|
|
118
|
+
with YouTubeClient() as client:
|
|
119
|
+
results = client.search("python tutorial", limit=5, filter_type="video")
|
|
120
|
+
for item in results["results"]:
|
|
121
|
+
print(item["title"], item["url"])
|
|
122
|
+
|
|
123
|
+
video = client.get_video("dQw4w9WgXcQ")
|
|
124
|
+
print(video["details"]["title"])
|
|
125
|
+
print(video["details"]["likes"])
|
|
126
|
+
|
|
127
|
+
transcript = client.get_transcript("dQw4w9WgXcQ", language_codes=("en",))
|
|
128
|
+
for segment in transcript["snippets"][:5]:
|
|
129
|
+
print(f"{segment['start']:.1f}s: {segment['text']}")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Common CLI commands:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
ytai search "python tutorial" --limit 10 --filter video
|
|
136
|
+
ytai video dQw4w9WgXcQ
|
|
137
|
+
ytai transcript dQw4w9WgXcQ --lang en
|
|
138
|
+
ytai comments dQw4w9WgXcQ --limit 20
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See the [Python API reference](docs/api-reference.md) and
|
|
142
|
+
[CLI reference](docs/cli-reference.md) for complete signatures and commands.
|
|
143
|
+
|
|
144
|
+
## Downloads
|
|
145
|
+
|
|
146
|
+
Inspect available qualities, codecs, stream sizes, and modes before downloading:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
ytai download-options dQw4w9WgXcQ
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Download a full video with audio:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
ytai download dQw4w9WgXcQ --quality 720p --output ./downloads
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Video-only, audio-only, and clipping are opt-in:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
ytai download dQw4w9WgXcQ --quality 1080p --video-only
|
|
162
|
+
ytai download dQw4w9WgXcQ --audio-only
|
|
163
|
+
ytai download dQw4w9WgXcQ --quality 360p --start 30 --end 90
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The SDK also exposes `VideoQuality`, `DownloadMode`, `get_download_options()`,
|
|
167
|
+
and `download_video()`. See the [download API](docs/api-reference.md#download_video)
|
|
168
|
+
and [download example](examples/download_video.py).
|
|
169
|
+
|
|
170
|
+
## MCP server
|
|
171
|
+
|
|
172
|
+
Start the FastMCP server:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
python mcp/server.py
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
It exposes nine read-only tools for search, video data, transcripts, streaming
|
|
179
|
+
formats, comments, channels, and popular videos. Media downloading is
|
|
180
|
+
intentionally available through the SDK and CLI only.
|
|
181
|
+
|
|
182
|
+
See [MCP Server Setup](docs/mcp-server.md) for client configuration and tool
|
|
183
|
+
parameters.
|
|
184
|
+
|
|
185
|
+
## FastAPI server
|
|
186
|
+
|
|
187
|
+
Start the versioned HTTP API:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
ytai-api
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Swagger UI is available at `http://127.0.0.1:8000/docs`. The API covers search,
|
|
194
|
+
video data, transcripts, comments, formats, download options, channels, and
|
|
195
|
+
popular videos. See the [FastAPI Server Guide](docs/api-server.md) for routes,
|
|
196
|
+
curl examples, configuration, validation, and deployment guidance.
|
|
197
|
+
|
|
198
|
+
## Documentation
|
|
199
|
+
|
|
200
|
+
- [Getting Started](docs/getting-started.md): prerequisites, installation, and first workflows
|
|
201
|
+
- [API Reference](docs/api-reference.md): public classes, functions, enums, and return shapes
|
|
202
|
+
- [CLI Reference](docs/cli-reference.md): every `ytai` command and option
|
|
203
|
+
- [MCP Server](docs/mcp-server.md): server setup, tools, parameters, and errors
|
|
204
|
+
- [FastAPI Server](docs/api-server.md): HTTP routes, OpenAPI docs, configuration, and examples
|
|
205
|
+
- [Examples](examples/): runnable search, metadata, transcript, comment, channel, download, and MCP scripts
|
|
206
|
+
|
|
207
|
+
## Testing
|
|
208
|
+
|
|
209
|
+
The end-to-end suite calls the real YouTube InnerTube and Google Video
|
|
210
|
+
boundaries. It covers search, transcripts, comments, channels, MCP tools, CLI
|
|
211
|
+
commands, download modes, clipping, resumable ranges, and ffmpeg output streams.
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
pytest tests/test_e2e.py -v
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Limitations
|
|
218
|
+
|
|
219
|
+
- Private, members-only, and most age-restricted content is unavailable without authentication.
|
|
220
|
+
- InnerTube endpoints and renderer structures can change without notice.
|
|
221
|
+
- Channel uploads currently return the first available page.
|
|
222
|
+
- Adaptive full-video downloads and clipping use the bundled FFmpeg executable (or `YTAI_FFMPEG_PATH` when configured).
|
|
223
|
+
- Playlist contents are not currently fetched.
|
|
224
|
+
|
|
225
|
+
## Credits
|
|
226
|
+
|
|
227
|
+
YTAI acknowledges these public projects as references for protocol details,
|
|
228
|
+
format mappings, and implementation ideas:
|
|
229
|
+
|
|
230
|
+
- [YouTube.js](https://github.com/LuanRT/YouTube.js)
|
|
231
|
+
- [innertube-go](https://github.com/raHULK777/innertube-go)
|
|
232
|
+
- [youtube-transcript-api](https://github.com/jdepoix/youtube-transcript-api)
|
|
233
|
+
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT, as declared in `pyproject.toml`.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# YTAI: Python YouTube SDK, CLI and MCP Server
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
YTAI is a Python SDK, command-line interface, and MCP server for YouTube
|
|
6
|
+
search, metadata, transcripts, comments, channels, and media downloads without a
|
|
7
|
+
user-supplied YouTube Data API key.
|
|
8
|
+
|
|
9
|
+
It uses YouTube's public InnerTube interface through `curl_cffi` browser
|
|
10
|
+
impersonation, dynamically refreshes web-client configuration, and caches public
|
|
11
|
+
responses locally with SQLite and `orjson`.
|
|
12
|
+
|
|
13
|
+
> YTAI is an independent project. It is not affiliated with or endorsed by
|
|
14
|
+
> YouTube or Google. Use it in accordance with applicable terms, copyright law,
|
|
15
|
+
> and local regulations.
|
|
16
|
+
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
- [Features](#features)
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Quick start](#quick-start)
|
|
22
|
+
- [Downloads](#downloads)
|
|
23
|
+
- [MCP server](#mcp-server)
|
|
24
|
+
- [FastAPI server](#fastapi-server)
|
|
25
|
+
- [Documentation](#documentation)
|
|
26
|
+
- [Testing](#testing)
|
|
27
|
+
- [Limitations](#limitations)
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- Search videos, channels, and playlists with filters and pagination
|
|
32
|
+
- Retrieve metadata, likes, captions, related videos, and comments
|
|
33
|
+
- Fetch timestamped transcripts with language selection and XML fallback
|
|
34
|
+
- Inspect channels, recent uploads, and popular videos
|
|
35
|
+
- Download full video with audio, video-only, audio-only, or a time range
|
|
36
|
+
- Resume interrupted downloads with ranged transfers and per-chunk retries
|
|
37
|
+
- Cache responses in SQLite with operation-specific TTLs
|
|
38
|
+
- Use the Python SDK, Rich-powered `ytai` CLI, nine read-only MCP tools, or the FastAPI service
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Requirements:
|
|
43
|
+
|
|
44
|
+
- Python 3.10 or newer
|
|
45
|
+
- No separate FFmpeg installation is required for downloads; YTAI bundles FFmpeg through `imageio-ffmpeg`
|
|
46
|
+
|
|
47
|
+
Clone and install the project:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git clone https://github.com/vibheksoni/youtube-ai.git
|
|
51
|
+
cd youtube-ai
|
|
52
|
+
python -m pip install -e .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Install development dependencies when running tests:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python -m pip install -e ".[dev]"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
FFmpeg is bundled automatically for Windows, macOS, and Linux when you install YTAI.
|
|
62
|
+
If you prefer a system build, it is used when `ffmpeg` is on `PATH`. To pin an
|
|
63
|
+
explicit binary, set `YTAI_FFMPEG_PATH` to its full path:
|
|
64
|
+
|
|
65
|
+
```powershell
|
|
66
|
+
$env:YTAI_FFMPEG_PATH = "C:\tools\ffmpeg\bin\ffmpeg.exe"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`YTAI_API_KEY` is an optional offline fallback when live configuration cannot be
|
|
70
|
+
fetched. It is read from the environment and is never stored in the repository.
|
|
71
|
+
|
|
72
|
+
For environment setup and first-run guidance, continue with
|
|
73
|
+
[Getting Started](docs/getting-started.md).
|
|
74
|
+
|
|
75
|
+
## Quick start
|
|
76
|
+
|
|
77
|
+
Use `YouTubeClient` as a context manager so its HTTP session is closed cleanly:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from youtube_ai import YouTubeClient
|
|
81
|
+
|
|
82
|
+
with YouTubeClient() as client:
|
|
83
|
+
results = client.search("python tutorial", limit=5, filter_type="video")
|
|
84
|
+
for item in results["results"]:
|
|
85
|
+
print(item["title"], item["url"])
|
|
86
|
+
|
|
87
|
+
video = client.get_video("dQw4w9WgXcQ")
|
|
88
|
+
print(video["details"]["title"])
|
|
89
|
+
print(video["details"]["likes"])
|
|
90
|
+
|
|
91
|
+
transcript = client.get_transcript("dQw4w9WgXcQ", language_codes=("en",))
|
|
92
|
+
for segment in transcript["snippets"][:5]:
|
|
93
|
+
print(f"{segment['start']:.1f}s: {segment['text']}")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Common CLI commands:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
ytai search "python tutorial" --limit 10 --filter video
|
|
100
|
+
ytai video dQw4w9WgXcQ
|
|
101
|
+
ytai transcript dQw4w9WgXcQ --lang en
|
|
102
|
+
ytai comments dQw4w9WgXcQ --limit 20
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
See the [Python API reference](docs/api-reference.md) and
|
|
106
|
+
[CLI reference](docs/cli-reference.md) for complete signatures and commands.
|
|
107
|
+
|
|
108
|
+
## Downloads
|
|
109
|
+
|
|
110
|
+
Inspect available qualities, codecs, stream sizes, and modes before downloading:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
ytai download-options dQw4w9WgXcQ
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Download a full video with audio:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
ytai download dQw4w9WgXcQ --quality 720p --output ./downloads
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Video-only, audio-only, and clipping are opt-in:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ytai download dQw4w9WgXcQ --quality 1080p --video-only
|
|
126
|
+
ytai download dQw4w9WgXcQ --audio-only
|
|
127
|
+
ytai download dQw4w9WgXcQ --quality 360p --start 30 --end 90
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The SDK also exposes `VideoQuality`, `DownloadMode`, `get_download_options()`,
|
|
131
|
+
and `download_video()`. See the [download API](docs/api-reference.md#download_video)
|
|
132
|
+
and [download example](examples/download_video.py).
|
|
133
|
+
|
|
134
|
+
## MCP server
|
|
135
|
+
|
|
136
|
+
Start the FastMCP server:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python mcp/server.py
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
It exposes nine read-only tools for search, video data, transcripts, streaming
|
|
143
|
+
formats, comments, channels, and popular videos. Media downloading is
|
|
144
|
+
intentionally available through the SDK and CLI only.
|
|
145
|
+
|
|
146
|
+
See [MCP Server Setup](docs/mcp-server.md) for client configuration and tool
|
|
147
|
+
parameters.
|
|
148
|
+
|
|
149
|
+
## FastAPI server
|
|
150
|
+
|
|
151
|
+
Start the versioned HTTP API:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
ytai-api
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Swagger UI is available at `http://127.0.0.1:8000/docs`. The API covers search,
|
|
158
|
+
video data, transcripts, comments, formats, download options, channels, and
|
|
159
|
+
popular videos. See the [FastAPI Server Guide](docs/api-server.md) for routes,
|
|
160
|
+
curl examples, configuration, validation, and deployment guidance.
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
- [Getting Started](docs/getting-started.md): prerequisites, installation, and first workflows
|
|
165
|
+
- [API Reference](docs/api-reference.md): public classes, functions, enums, and return shapes
|
|
166
|
+
- [CLI Reference](docs/cli-reference.md): every `ytai` command and option
|
|
167
|
+
- [MCP Server](docs/mcp-server.md): server setup, tools, parameters, and errors
|
|
168
|
+
- [FastAPI Server](docs/api-server.md): HTTP routes, OpenAPI docs, configuration, and examples
|
|
169
|
+
- [Examples](examples/): runnable search, metadata, transcript, comment, channel, download, and MCP scripts
|
|
170
|
+
|
|
171
|
+
## Testing
|
|
172
|
+
|
|
173
|
+
The end-to-end suite calls the real YouTube InnerTube and Google Video
|
|
174
|
+
boundaries. It covers search, transcripts, comments, channels, MCP tools, CLI
|
|
175
|
+
commands, download modes, clipping, resumable ranges, and ffmpeg output streams.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
pytest tests/test_e2e.py -v
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Limitations
|
|
182
|
+
|
|
183
|
+
- Private, members-only, and most age-restricted content is unavailable without authentication.
|
|
184
|
+
- InnerTube endpoints and renderer structures can change without notice.
|
|
185
|
+
- Channel uploads currently return the first available page.
|
|
186
|
+
- Adaptive full-video downloads and clipping use the bundled FFmpeg executable (or `YTAI_FFMPEG_PATH` when configured).
|
|
187
|
+
- Playlist contents are not currently fetched.
|
|
188
|
+
|
|
189
|
+
## Credits
|
|
190
|
+
|
|
191
|
+
YTAI acknowledges these public projects as references for protocol details,
|
|
192
|
+
format mappings, and implementation ideas:
|
|
193
|
+
|
|
194
|
+
- [YouTube.js](https://github.com/LuanRT/YouTube.js)
|
|
195
|
+
- [innertube-go](https://github.com/raHULK777/innertube-go)
|
|
196
|
+
- [youtube-transcript-api](https://github.com/jdepoix/youtube-transcript-api)
|
|
197
|
+
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT, as declared in `pyproject.toml`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Request-scoped dependencies for the HTTP API."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from youtube_ai import YouTubeClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_youtube_client() -> Iterator[YouTubeClient]:
|
|
16
|
+
|
|
17
|
+
"""Provide an isolated client and always close its HTTP session."""
|
|
18
|
+
|
|
19
|
+
with YouTubeClient() as client:
|
|
20
|
+
|
|
21
|
+
yield client
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Stable public error responses for the HTTP API."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from fastapi import FastAPI, Request
|
|
6
|
+
|
|
7
|
+
from fastapi.exceptions import RequestValidationError
|
|
8
|
+
|
|
9
|
+
from fastapi.responses import JSONResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
from youtube_ai import InnerTubeError, VideoUnavailable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _error(status_code: int, code: str, message: str) -> JSONResponse:
|
|
20
|
+
|
|
21
|
+
return JSONResponse(
|
|
22
|
+
|
|
23
|
+
status_code=status_code,
|
|
24
|
+
|
|
25
|
+
content={"error": {"code": code, "message": message}},
|
|
26
|
+
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def register_error_handlers(app: FastAPI) -> None:
|
|
34
|
+
|
|
35
|
+
@app.exception_handler(VideoUnavailable)
|
|
36
|
+
|
|
37
|
+
def video_unavailable(_request: Request, _exc: VideoUnavailable) -> JSONResponse:
|
|
38
|
+
|
|
39
|
+
return _error(404, "video_unavailable", "The requested video is unavailable.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.exception_handler(InnerTubeError)
|
|
44
|
+
|
|
45
|
+
def innertube_error(_request: Request, _exc: InnerTubeError) -> JSONResponse:
|
|
46
|
+
|
|
47
|
+
return _error(502, "upstream_error", "YouTube could not complete the request.")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@app.exception_handler(RequestValidationError)
|
|
52
|
+
|
|
53
|
+
def validation_error(_request: Request, _exc: RequestValidationError) -> JSONResponse:
|
|
54
|
+
|
|
55
|
+
return _error(422, "validation_error", "The request parameters are invalid.")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""FastAPI application factory and server entry point."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from fastapi import FastAPI
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
from youtube_ai import __version__
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from .errors import register_error_handlers
|
|
18
|
+
|
|
19
|
+
from .routes import channels, discovery, search, system, videos
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
API_PREFIX = "/api/v1"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def create_app() -> FastAPI:
|
|
30
|
+
|
|
31
|
+
app = FastAPI(
|
|
32
|
+
|
|
33
|
+
title="YTAI API",
|
|
34
|
+
|
|
35
|
+
summary="HTTP access to the YTAI YouTube SDK",
|
|
36
|
+
|
|
37
|
+
description=(
|
|
38
|
+
|
|
39
|
+
"Search public YouTube data, retrieve metadata and transcripts, "
|
|
40
|
+
|
|
41
|
+
"inspect comments, channels, streaming formats, and download options. "
|
|
42
|
+
|
|
43
|
+
"No user-supplied YouTube Data API key is required."
|
|
44
|
+
|
|
45
|
+
),
|
|
46
|
+
|
|
47
|
+
version=__version__,
|
|
48
|
+
|
|
49
|
+
docs_url="/docs",
|
|
50
|
+
|
|
51
|
+
redoc_url="/redoc",
|
|
52
|
+
|
|
53
|
+
openapi_url="/openapi.json",
|
|
54
|
+
|
|
55
|
+
contact={"name": "YTAI", "url": "https://github.com/vibheksoni/youtube-ai"},
|
|
56
|
+
|
|
57
|
+
license_info={"name": "MIT"},
|
|
58
|
+
|
|
59
|
+
swagger_ui_parameters={
|
|
60
|
+
|
|
61
|
+
"displayRequestDuration": True,
|
|
62
|
+
|
|
63
|
+
"filter": True,
|
|
64
|
+
|
|
65
|
+
"operationsSorter": "method",
|
|
66
|
+
|
|
67
|
+
"tagsSorter": "alpha",
|
|
68
|
+
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
register_error_handlers(app)
|
|
74
|
+
|
|
75
|
+
app.include_router(system.router)
|
|
76
|
+
|
|
77
|
+
app.include_router(search.router, prefix=API_PREFIX)
|
|
78
|
+
|
|
79
|
+
app.include_router(videos.router, prefix=API_PREFIX)
|
|
80
|
+
|
|
81
|
+
app.include_router(channels.router, prefix=API_PREFIX)
|
|
82
|
+
|
|
83
|
+
app.include_router(discovery.router, prefix=API_PREFIX)
|
|
84
|
+
|
|
85
|
+
return app
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
app = create_app()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _port_from_env() -> int:
|
|
98
|
+
|
|
99
|
+
raw_port = os.getenv("YTAI_API_PORT", "8000")
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
|
|
103
|
+
port = int(raw_port)
|
|
104
|
+
|
|
105
|
+
except ValueError as exc:
|
|
106
|
+
|
|
107
|
+
raise RuntimeError("YTAI_API_PORT must be an integer") from exc
|
|
108
|
+
|
|
109
|
+
if not 1 <= port <= 65535:
|
|
110
|
+
|
|
111
|
+
raise RuntimeError("YTAI_API_PORT must be between 1 and 65535")
|
|
112
|
+
|
|
113
|
+
return port
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def run() -> None:
|
|
120
|
+
|
|
121
|
+
"""Run the development server from the ``ytai-api`` console command."""
|
|
122
|
+
|
|
123
|
+
import uvicorn
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
uvicorn.run(
|
|
128
|
+
|
|
129
|
+
"api.main:app",
|
|
130
|
+
|
|
131
|
+
host=os.getenv("YTAI_API_HOST", "127.0.0.1"),
|
|
132
|
+
|
|
133
|
+
port=_port_from_env(),
|
|
134
|
+
|
|
135
|
+
log_level=os.getenv("YTAI_API_LOG_LEVEL", "info"),
|
|
136
|
+
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
|
|
145
|
+
run()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""HTTP route modules."""
|