media-downloader 2.1.8__py3-none-any.whl → 2.1.10__py3-none-any.whl

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.

Potentially problematic release.


This version of media-downloader might be problematic. Click here for more details.

@@ -4,10 +4,17 @@ import argparse
4
4
  import os
5
5
  import sys
6
6
  import logging
7
- from typing import Optional, Union, Dict, Any
8
- from media_downloader import MediaDownloader, setup_logging
9
- from fastmcp import FastMCP, Context
7
+ from typing import Optional, Dict, Union, Any
10
8
  from pydantic import Field
9
+ from fastmcp import FastMCP, Context
10
+ from fastmcp.server.auth.oidc_proxy import OIDCProxy
11
+ from fastmcp.server.auth import OAuthProxy, RemoteAuthProvider
12
+ from fastmcp.server.auth.providers.jwt import JWTVerifier, StaticTokenVerifier
13
+ from fastmcp.server.middleware.logging import LoggingMiddleware
14
+ from fastmcp.server.middleware.timing import TimingMiddleware
15
+ from fastmcp.server.middleware.rate_limiting import RateLimitingMiddleware
16
+ from fastmcp.server.middleware.error_handling import ErrorHandlingMiddleware
17
+ from media_downloader.media_downloader import MediaDownloader, setup_logging
11
18
 
12
19
  # Initialize logging for MCP server (logs to file)
13
20
  setup_logging(is_mcp_server=True, log_file="media_downloader_mcp.log")
@@ -169,6 +176,83 @@ def media_downloader_mcp():
169
176
  default=8000,
170
177
  help="Port number for HTTP transport (default: 8000)",
171
178
  )
179
+ parser.add_argument(
180
+ "--auth-type",
181
+ default="none",
182
+ choices=["none", "static", "jwt", "oauth-proxy", "oidc-proxy", "remote-oauth"],
183
+ help="Authentication type for MCP server: 'none' (disabled), 'static' (internal), 'jwt' (external token verification), 'oauth-proxy', 'oidc-proxy', 'remote-oauth' (external) (default: none)",
184
+ )
185
+ # JWT/Token params
186
+ parser.add_argument(
187
+ "--token-jwks-uri", default=None, help="JWKS URI for JWT verification"
188
+ )
189
+ parser.add_argument(
190
+ "--token-issuer", default=None, help="Issuer for JWT verification"
191
+ )
192
+ parser.add_argument(
193
+ "--token-audience", default=None, help="Audience for JWT verification"
194
+ )
195
+ # OAuth Proxy params
196
+ parser.add_argument(
197
+ "--oauth-upstream-auth-endpoint",
198
+ default=None,
199
+ help="Upstream authorization endpoint for OAuth Proxy",
200
+ )
201
+ parser.add_argument(
202
+ "--oauth-upstream-token-endpoint",
203
+ default=None,
204
+ help="Upstream token endpoint for OAuth Proxy",
205
+ )
206
+ parser.add_argument(
207
+ "--oauth-upstream-client-id",
208
+ default=None,
209
+ help="Upstream client ID for OAuth Proxy",
210
+ )
211
+ parser.add_argument(
212
+ "--oauth-upstream-client-secret",
213
+ default=None,
214
+ help="Upstream client secret for OAuth Proxy",
215
+ )
216
+ parser.add_argument(
217
+ "--oauth-base-url", default=None, help="Base URL for OAuth Proxy"
218
+ )
219
+ # OIDC Proxy params
220
+ parser.add_argument(
221
+ "--oidc-config-url", default=None, help="OIDC configuration URL"
222
+ )
223
+ parser.add_argument("--oidc-client-id", default=None, help="OIDC client ID")
224
+ parser.add_argument("--oidc-client-secret", default=None, help="OIDC client secret")
225
+ parser.add_argument("--oidc-base-url", default=None, help="Base URL for OIDC Proxy")
226
+ # Remote OAuth params
227
+ parser.add_argument(
228
+ "--remote-auth-servers",
229
+ default=None,
230
+ help="Comma-separated list of authorization servers for Remote OAuth",
231
+ )
232
+ parser.add_argument(
233
+ "--remote-base-url", default=None, help="Base URL for Remote OAuth"
234
+ )
235
+ # Common
236
+ parser.add_argument(
237
+ "--allowed-client-redirect-uris",
238
+ default=None,
239
+ help="Comma-separated list of allowed client redirect URIs",
240
+ )
241
+ # Eunomia params
242
+ parser.add_argument(
243
+ "--eunomia-type",
244
+ default="none",
245
+ choices=["none", "embedded", "remote"],
246
+ help="Eunomia authorization type: 'none' (disabled), 'embedded' (built-in), 'remote' (external) (default: none)",
247
+ )
248
+ parser.add_argument(
249
+ "--eunomia-policy-file",
250
+ default="mcp_policies.json",
251
+ help="Policy file for embedded Eunomia (default: mcp_policies.json)",
252
+ )
253
+ parser.add_argument(
254
+ "--eunomia-remote-url", default=None, help="URL for remote Eunomia server"
255
+ )
172
256
 
173
257
  args = parser.parse_args()
174
258
 
@@ -176,6 +260,133 @@ def media_downloader_mcp():
176
260
  print(f"Error: Port {args.port} is out of valid range (0-65535).")
177
261
  sys.exit(1)
178
262
 
263
+ # Set auth based on type
264
+ auth = None
265
+ allowed_uris = (
266
+ args.allowed_client_redirect_uris.split(",")
267
+ if args.allowed_client_redirect_uris
268
+ else None
269
+ )
270
+
271
+ if args.auth_type == "none":
272
+ auth = None
273
+ elif args.auth_type == "static":
274
+ # Internal static tokens (hardcoded example)
275
+ auth = StaticTokenVerifier(
276
+ tokens={
277
+ "test-token": {"client_id": "test-user", "scopes": ["read", "write"]},
278
+ "admin-token": {"client_id": "admin", "scopes": ["admin"]},
279
+ }
280
+ )
281
+ elif args.auth_type == "jwt":
282
+ if not (args.token_jwks_uri and args.token_issuer and args.token_audience):
283
+ print(
284
+ "Error: jwt requires --token-jwks-uri, --token-issuer, --token-audience"
285
+ )
286
+ sys.exit(1)
287
+ auth = JWTVerifier(
288
+ jwks_uri=args.token_jwks_uri,
289
+ issuer=args.token_issuer,
290
+ audience=args.token_audience,
291
+ )
292
+ elif args.auth_type == "oauth-proxy":
293
+ if not (
294
+ args.oauth_upstream_auth_endpoint
295
+ and args.oauth_upstream_token_endpoint
296
+ and args.oauth_upstream_client_id
297
+ and args.oauth_upstream_client_secret
298
+ and args.oauth_base_url
299
+ and args.token_jwks_uri
300
+ and args.token_issuer
301
+ and args.token_audience
302
+ ):
303
+ print(
304
+ "Error: oauth-proxy requires --oauth-upstream-auth-endpoint, --oauth-upstream-token-endpoint, --oauth-upstream-client-id, --oauth-upstream-client-secret, --oauth-base-url, --token-jwks-uri, --token-issuer, --token-audience"
305
+ )
306
+ sys.exit(1)
307
+ token_verifier = JWTVerifier(
308
+ jwks_uri=args.token_jwks_uri,
309
+ issuer=args.token_issuer,
310
+ audience=args.token_audience,
311
+ )
312
+ auth = OAuthProxy(
313
+ upstream_authorization_endpoint=args.oauth_upstream_auth_endpoint,
314
+ upstream_token_endpoint=args.oauth_upstream_token_endpoint,
315
+ upstream_client_id=args.oauth_upstream_client_id,
316
+ upstream_client_secret=args.oauth_upstream_client_secret,
317
+ token_verifier=token_verifier,
318
+ base_url=args.oauth_base_url,
319
+ allowed_client_redirect_uris=allowed_uris,
320
+ )
321
+ elif args.auth_type == "oidc-proxy":
322
+ if not (
323
+ args.oidc_config_url
324
+ and args.oidc_client_id
325
+ and args.oidc_client_secret
326
+ and args.oidc_base_url
327
+ ):
328
+ print(
329
+ "Error: oidc-proxy requires --oidc-config-url, --oidc-client-id, --oidc-client-secret, --oidc-base-url"
330
+ )
331
+ sys.exit(1)
332
+ auth = OIDCProxy(
333
+ config_url=args.oidc_config_url,
334
+ client_id=args.oidc_client_id,
335
+ client_secret=args.oidc_client_secret,
336
+ base_url=args.oidc_base_url,
337
+ allowed_client_redirect_uris=allowed_uris,
338
+ )
339
+ elif args.auth_type == "remote-oauth":
340
+ if not (
341
+ args.remote_auth_servers
342
+ and args.remote_base_url
343
+ and args.token_jwks_uri
344
+ and args.token_issuer
345
+ and args.token_audience
346
+ ):
347
+ print(
348
+ "Error: remote-oauth requires --remote-auth-servers, --remote-base-url, --token-jwks-uri, --token-issuer, --token-audience"
349
+ )
350
+ sys.exit(1)
351
+ auth_servers = [url.strip() for url in args.remote_auth_servers.split(",")]
352
+ token_verifier = JWTVerifier(
353
+ jwks_uri=args.token_jwks_uri,
354
+ issuer=args.token_issuer,
355
+ audience=args.token_audience,
356
+ )
357
+ auth = RemoteAuthProvider(
358
+ token_verifier=token_verifier,
359
+ authorization_servers=auth_servers,
360
+ base_url=args.remote_base_url,
361
+ )
362
+ mcp.auth = auth
363
+ if args.eunomia_type != "none":
364
+ from eunomia_mcp import create_eunomia_middleware
365
+
366
+ if args.eunomia_type == "embedded":
367
+ if not args.eunomia_policy_file:
368
+ print("Error: embedded Eunomia requires --eunomia-policy-file")
369
+ sys.exit(1)
370
+ middleware = create_eunomia_middleware(policy_file=args.eunomia_policy_file)
371
+ mcp.add_middleware(middleware)
372
+ elif args.eunomia_type == "remote":
373
+ if not args.eunomia_remote_url:
374
+ print("Error: remote Eunomia requires --eunomia-remote-url")
375
+ sys.exit(1)
376
+ middleware = create_eunomia_middleware(
377
+ use_remote_eunomia=args.eunomia_remote_url
378
+ )
379
+ mcp.add_middleware(middleware)
380
+
381
+ mcp.add_middleware(
382
+ ErrorHandlingMiddleware(include_traceback=True, transform_errors=True)
383
+ )
384
+ mcp.add_middleware(
385
+ RateLimitingMiddleware(max_requests_per_second=10.0, burst_capacity=20)
386
+ )
387
+ mcp.add_middleware(TimingMiddleware())
388
+ mcp.add_middleware(LoggingMiddleware())
389
+
179
390
  if args.transport == "stdio":
180
391
  mcp.run(transport="stdio")
181
392
  elif args.transport == "http":
@@ -0,0 +1,314 @@
1
+ Metadata-Version: 2.4
2
+ Name: media-downloader
3
+ Version: 2.1.10
4
+ Summary: Download audio/videos from the internet!
5
+ Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
+ License: MIT
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: License :: Public Domain
9
+ Classifier: Environment :: Console
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Programming Language :: Python :: 3
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: yt-dlp>=2025.9.26
16
+ Requires-Dist: fastmcp>=2.13.0.2
17
+ Dynamic: license-file
18
+
19
+ # Media Downloader
20
+
21
+ ![PyPI - Version](https://img.shields.io/pypi/v/media-downloader)
22
+ ![PyPI - Downloads](https://img.shields.io/pypi/dd/media-downloader)
23
+ ![GitHub Repo stars](https://img.shields.io/github/stars/Knuckles-Team/media-downloader)
24
+ ![GitHub forks](https://img.shields.io/github/forks/Knuckles-Team/media-downloader)
25
+ ![GitHub contributors](https://img.shields.io/github/contributors/Knuckles-Team/media-downloader)
26
+ ![PyPI - License](https://img.shields.io/pypi/l/media-downloader)
27
+ ![GitHub](https://img.shields.io/github/license/Knuckles-Team/media-downloader)
28
+
29
+ ![GitHub last commit (by committer)](https://img.shields.io/github/last-commit/Knuckles-Team/media-downloader)
30
+ ![GitHub pull requests](https://img.shields.io/github/issues-pr/Knuckles-Team/media-downloader)
31
+ ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/Knuckles-Team/media-downloader)
32
+ ![GitHub issues](https://img.shields.io/github/issues/Knuckles-Team/media-downloader)
33
+
34
+ ![GitHub top language](https://img.shields.io/github/languages/top/Knuckles-Team/media-downloader)
35
+ ![GitHub language count](https://img.shields.io/github/languages/count/Knuckles-Team/media-downloader)
36
+ ![GitHub repo size](https://img.shields.io/github/repo-size/Knuckles-Team/media-downloader)
37
+ ![GitHub repo file count (file type)](https://img.shields.io/github/directory-file-count/Knuckles-Team/media-downloader)
38
+ ![PyPI - Wheel](https://img.shields.io/pypi/wheel/media-downloader)
39
+ ![PyPI - Implementation](https://img.shields.io/pypi/implementation/media-downloader)
40
+
41
+ *Version: 2.1.10*
42
+
43
+ Download videos and audio from the internet!
44
+
45
+ MCP Server Support!
46
+
47
+ This repository is actively maintained - Contributions are welcome!
48
+
49
+ ### Supports:
50
+ - YouTube
51
+ - Twitter
52
+ - Rumble
53
+ - BitChute
54
+ - Vimeo
55
+ - And More!
56
+
57
+ <details>
58
+ <summary><b>Usage:</b></summary>
59
+
60
+ ### CLI
61
+ | Short Flag | Long Flag | Description |
62
+ |------------|-------------|---------------------------------------------|
63
+ | -h | --help | See usage |
64
+ | -a | --audio | Download audio only |
65
+ | -c | --channel | YouTube Channel/User - Downloads all videos |
66
+ | -f | --file | File with video links |
67
+ | -l | --links | Comma separated links |
68
+ | -d | --directory | Location to save videos |
69
+
70
+ ```bash
71
+ media-downloader --file "C:\Users\videos.txt" --directory "C:\Users\Downloads" --channel "WhiteHouse" --links "URL1,URL2,URL3"
72
+ ```
73
+
74
+ ### MCP CLI
75
+
76
+ | Short Flag | Long Flag | Description |
77
+ |------------|------------------------------------|-----------------------------------------------------------------------------|
78
+ | -h | --help | Display help information |
79
+ | -t | --transport | Transport method: 'stdio', 'http', or 'sse' [legacy] (default: stdio) |
80
+ | -s | --host | Host address for HTTP transport (default: 0.0.0.0) |
81
+ | -p | --port | Port number for HTTP transport (default: 8000) |
82
+ | | --auth-type | Authentication type: 'none', 'static', 'jwt', 'oauth-proxy', 'oidc-proxy', 'remote-oauth' (default: none) |
83
+ | | --token-jwks-uri | JWKS URI for JWT verification |
84
+ | | --token-issuer | Issuer for JWT verification |
85
+ | | --token-audience | Audience for JWT verification |
86
+ | | --oauth-upstream-auth-endpoint | Upstream authorization endpoint for OAuth Proxy |
87
+ | | --oauth-upstream-token-endpoint | Upstream token endpoint for OAuth Proxy |
88
+ | | --oauth-upstream-client-id | Upstream client ID for OAuth Proxy |
89
+ | | --oauth-upstream-client-secret | Upstream client secret for OAuth Proxy |
90
+ | | --oauth-base-url | Base URL for OAuth Proxy |
91
+ | | --oidc-config-url | OIDC configuration URL |
92
+ | | --oidc-client-id | OIDC client ID |
93
+ | | --oidc-client-secret | OIDC client secret |
94
+ | | --oidc-base-url | Base URL for OIDC Proxy |
95
+ | | --remote-auth-servers | Comma-separated list of authorization servers for Remote OAuth |
96
+ | | --remote-base-url | Base URL for Remote OAuth |
97
+ | | --allowed-client-redirect-uris | Comma-separated list of allowed client redirect URIs |
98
+ | | --eunomia-type | Eunomia authorization type: 'none', 'embedded', 'remote' (default: none) |
99
+ | | --eunomia-policy-file | Policy file for embedded Eunomia (default: mcp_policies.json) |
100
+ | | --eunomia-remote-url | URL for remote Eunomia server |
101
+
102
+ ### Using as an MCP Server
103
+
104
+ The MCP Server can be run in two modes: `stdio` (for local testing) or `http` (for networked access). To start the server, use the following commands:
105
+
106
+ #### Run in stdio mode (default):
107
+ ```bash
108
+ media-downloader-mcp
109
+ ```
110
+
111
+ #### Run in HTTP mode:
112
+ ```bash
113
+ media-downloader-mcp --transport http --host 0.0.0.0 --port 8012
114
+ ```
115
+
116
+
117
+ AI Prompt:
118
+ ```text
119
+ Download me this video: https://youtube.com/watch?askdjfa
120
+ ```
121
+
122
+ AI Response:
123
+ ```text
124
+ Sure thing, the video has been downloaded to:
125
+
126
+ "C:\Users\User\Downloads\YouTube Video - Episode 1.mp4"
127
+ ```
128
+
129
+ ### Use in Python
130
+
131
+ ```python
132
+ # Import library
133
+ from media_downloader import MediaDownloader
134
+
135
+ # Set URL of video/audio here
136
+ url = "https://YootToob.com/video"
137
+
138
+ # Instantiate vide_downloader_instance
139
+ video_downloader_instance = MediaDownloader()
140
+
141
+ # Set the location to save the video
142
+ video_downloader_instance.set_save_path("C:/Users/you/Downloads")
143
+
144
+ # Add URL to download
145
+ video_downloader_instance.append_link(url)
146
+
147
+ # Download all videos appended
148
+ video_downloader_instance.download_all()
149
+ ```
150
+
151
+ ```python
152
+ # Optional - Set Audio to True, Default is False if unspecified.
153
+ video_downloader_instance.set_audio(audio=True)
154
+
155
+ # Optional - Open a file of video/audio URL(s)
156
+ video_downloader_instance.open_file("FILE")
157
+
158
+ # Optional - Enter a YouTube channel name and download their latest videos
159
+ video_downloader_instance.get_channel_videos("YT-Channel Name")
160
+ ```
161
+
162
+ ### Deploy MCP Server as a Service
163
+
164
+ The MCP server can be deployed using Docker, with configurable authentication, middleware, and Eunomia authorization.
165
+
166
+ #### Using Docker Run
167
+
168
+ ```bash
169
+ docker pull knucklessg1/media-downloader:latest
170
+
171
+ docker run -d \
172
+ --name media-downloader-mcp \
173
+ -p 8004:8004 \
174
+ -e HOST=0.0.0.0 \
175
+ -e PORT=8004 \
176
+ -e TRANSPORT=http \
177
+ -e AUTH_TYPE=none \
178
+ -e EUNOMIA_TYPE=none \
179
+ -e DOWNLOAD_DIRECTORY=/downloads \
180
+ -e AUDIO_ONLY=false \
181
+ -v "/home/genius/Downloads:/downloads" \
182
+ knucklessg1/media-downloader:latest
183
+ ```
184
+
185
+ For advanced authentication (e.g., JWT, OAuth Proxy, OIDC Proxy, Remote OAuth) or Eunomia, add the relevant environment variables:
186
+
187
+ ```bash
188
+ docker run -d \
189
+ --name media-downloader-mcp \
190
+ -p 8004:8004 \
191
+ -e HOST=0.0.0.0 \
192
+ -e PORT=8004 \
193
+ -e TRANSPORT=http \
194
+ -e AUTH_TYPE=oidc-proxy \
195
+ -e OIDC_CONFIG_URL=https://provider.com/.well-known/openid-configuration \
196
+ -e OIDC_CLIENT_ID=your-client-id \
197
+ -e OIDC_CLIENT_SECRET=your-client-secret \
198
+ -e OIDC_BASE_URL=https://your-server.com \
199
+ -e ALLOWED_CLIENT_REDIRECT_URIS=http://localhost:*,https://*.example.com/* \
200
+ -e EUNOMIA_TYPE=embedded \
201
+ -e EUNOMIA_POLICY_FILE=/app/mcp_policies.json \
202
+ -e DOWNLOAD_DIRECTORY=/downloads \
203
+ -e AUDIO_ONLY=false \
204
+ -v "/home/genius/Downloads:/downloads" \
205
+ knucklessg1/media-downloader:latest
206
+ ```
207
+
208
+ #### Using Docker Compose
209
+
210
+ Create a `docker-compose.yml` file:
211
+
212
+ ```yaml
213
+ services:
214
+ media-downloader-mcp:
215
+ image: knucklessg1/media-downloader:latest
216
+ environment:
217
+ - HOST=0.0.0.0
218
+ - PORT=8004
219
+ - TRANSPORT=http
220
+ - AUTH_TYPE=none
221
+ - EUNOMIA_TYPE=none
222
+ - DOWNLOAD_DIRECTORY=/downloads
223
+ - AUDIO_ONLY=false
224
+ volumes:
225
+ - "/home/genius/Downloads:/downloads"
226
+ ports:
227
+ - 8004:8004
228
+ ```
229
+
230
+ For advanced setups with authentication and Eunomia:
231
+
232
+ ```yaml
233
+ services:
234
+ media-downloader-mcp:
235
+ image: knucklessg1/media-downloader:latest
236
+ environment:
237
+ - HOST=0.0.0.0
238
+ - PORT=8004
239
+ - TRANSPORT=http
240
+ - AUTH_TYPE=oidc-proxy
241
+ - OIDC_CONFIG_URL=https://provider.com/.well-known/openid-configuration
242
+ - OIDC_CLIENT_ID=your-client-id
243
+ - OIDC_CLIENT_SECRET=your-client-secret
244
+ - OIDC_BASE_URL=https://your-server.com
245
+ - ALLOWED_CLIENT_REDIRECT_URIS=http://localhost:*,https://*.example.com/*
246
+ - EUNOMIA_TYPE=embedded
247
+ - EUNOMIA_POLICY_FILE=/app/mcp_policies.json
248
+ - DOWNLOAD_DIRECTORY=/downloads
249
+ - AUDIO_ONLY=false
250
+ ports:
251
+ - 8004:8004
252
+ volumes:
253
+ - ./mcp_policies.json:/app/mcp_policies.json
254
+ - "/home/genius/Downloads:/downloads"
255
+ ```
256
+
257
+ Run the service:
258
+
259
+ ```bash
260
+ docker-compose up -d
261
+ ```
262
+
263
+ #### Configure `mcp.json` for AI Integration
264
+
265
+
266
+ ```json
267
+ {
268
+ "mcpServers": {
269
+ "media_downloader": {
270
+ "command": "uv",
271
+ "args": [
272
+ "run",
273
+ "--with",
274
+ "media-downloader",
275
+ "media-downloader-mcp"
276
+ ],
277
+ "env": {
278
+ "DOWNLOAD_DIRECTORY": "~/Downloads", // Optional - Can be specified at prompt
279
+ "AUDIO_ONLY": false // Optional - Can be specified at prompt
280
+ },
281
+ "timeout": 300000
282
+ }
283
+ }
284
+ }
285
+
286
+ ```
287
+ </details>
288
+
289
+ <details>
290
+ <summary><b>Installation Instructions:</b></summary>
291
+
292
+ Install Python Package
293
+
294
+ ```bash
295
+ python -m pip install --upgrade media-downloader
296
+ ```
297
+
298
+ or
299
+
300
+ ```bash
301
+ uv pip install --upgrade media-downloader
302
+ ```
303
+
304
+ </details>
305
+
306
+ <details>
307
+ <summary><b>Repository Owners:</b></summary>
308
+
309
+
310
+ <img width="100%" height="180em" src="https://github-readme-stats.vercel.app/api?username=Knucklessg1&show_icons=true&hide_border=true&&count_private=true&include_all_commits=true" />
311
+
312
+ ![GitHub followers](https://img.shields.io/github/followers/Knucklessg1)
313
+ ![GitHub User's stars](https://img.shields.io/github/stars/Knucklessg1)
314
+ </details>
@@ -0,0 +1,11 @@
1
+ media_downloader/__init__.py,sha256=NTYKOsoerw5jh4lryKFMofaK8bsJl0vS8UwhUED1wz4,821
2
+ media_downloader/__main__.py,sha256=5T-EOUX1ANJOd2ut4GoI9mvDpNCo25yZcOAZdnhzQI0,169
3
+ media_downloader/media_downloader.py,sha256=L20XUnnJ5UWq4ZZQIdmi7ZrOl2hXKSZkjNDH6l0eqKc,9097
4
+ media_downloader/media_downloader_mcp.py,sha256=PxWu1-6dkOo_Tr7Q4UDsl6NKvmz3EFzCFBQsw_L9l-k,14711
5
+ media_downloader-2.1.10.dist-info/licenses/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
6
+ tests/test_mcp.py,sha256=mbe5O75w2SDr7-7nbzDSAHhMYx4qZKccU77h8Cp5LSo,1509
7
+ media_downloader-2.1.10.dist-info/METADATA,sha256=WmgvwzxtVKZ3457LkFLBoVxJPoVPEOOMT0UDrAcs2pY,11594
8
+ media_downloader-2.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ media_downloader-2.1.10.dist-info/entry_points.txt,sha256=X_Ig7LdYJePZ9BQPMGyA2dSmBIQIYMHXCnTOeEbhgio,170
10
+ media_downloader-2.1.10.dist-info/top_level.txt,sha256=baD75VEFaytQEs4mmqyK1M0iZ5Y0HGF62vvtbSfbZCA,23
11
+ media_downloader-2.1.10.dist-info/RECORD,,
@@ -1,227 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: media-downloader
3
- Version: 2.1.8
4
- Summary: Download audio/videos from the internet!
5
- Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
- License: MIT
7
- Classifier: Development Status :: 5 - Production/Stable
8
- Classifier: License :: Public Domain
9
- Classifier: Environment :: Console
10
- Classifier: Operating System :: POSIX :: Linux
11
- Classifier: Programming Language :: Python :: 3
12
- Requires-Python: >=3.8
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: yt-dlp>=2025.9.26
16
- Requires-Dist: fastmcp>=2.11.3
17
- Dynamic: license-file
18
-
19
- # Media Downloader
20
-
21
- ![PyPI - Version](https://img.shields.io/pypi/v/media-downloader)
22
- ![PyPI - Downloads](https://img.shields.io/pypi/dd/media-downloader)
23
- ![GitHub Repo stars](https://img.shields.io/github/stars/Knuckles-Team/media-downloader)
24
- ![GitHub forks](https://img.shields.io/github/forks/Knuckles-Team/media-downloader)
25
- ![GitHub contributors](https://img.shields.io/github/contributors/Knuckles-Team/media-downloader)
26
- ![PyPI - License](https://img.shields.io/pypi/l/media-downloader)
27
- ![GitHub](https://img.shields.io/github/license/Knuckles-Team/media-downloader)
28
-
29
- ![GitHub last commit (by committer)](https://img.shields.io/github/last-commit/Knuckles-Team/media-downloader)
30
- ![GitHub pull requests](https://img.shields.io/github/issues-pr/Knuckles-Team/media-downloader)
31
- ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/Knuckles-Team/media-downloader)
32
- ![GitHub issues](https://img.shields.io/github/issues/Knuckles-Team/media-downloader)
33
-
34
- ![GitHub top language](https://img.shields.io/github/languages/top/Knuckles-Team/media-downloader)
35
- ![GitHub language count](https://img.shields.io/github/languages/count/Knuckles-Team/media-downloader)
36
- ![GitHub repo size](https://img.shields.io/github/repo-size/Knuckles-Team/media-downloader)
37
- ![GitHub repo file count (file type)](https://img.shields.io/github/directory-file-count/Knuckles-Team/media-downloader)
38
- ![PyPI - Wheel](https://img.shields.io/pypi/wheel/media-downloader)
39
- ![PyPI - Implementation](https://img.shields.io/pypi/implementation/media-downloader)
40
-
41
- *Version: 2.1.8*
42
-
43
- Download videos and audio from the internet!
44
-
45
- MCP Server Support!
46
-
47
- This repository is actively maintained - Contributions are welcome!
48
-
49
- ### Supports:
50
- - YouTube
51
- - Twitter
52
- - Rumble
53
- - BitChute
54
- - Vimeo
55
- - And More!
56
-
57
- <details>
58
- <summary><b>Usage:</b></summary>
59
-
60
- ### CLI
61
- | Short Flag | Long Flag | Description |
62
- |------------|-------------|---------------------------------------------|
63
- | -h | --help | See usage |
64
- | -a | --audio | Download audio only |
65
- | -c | --channel | YouTube Channel/User - Downloads all videos |
66
- | -f | --file | File with video links |
67
- | -l | --links | Comma separated links |
68
- | -d | --directory | Location to save videos |
69
-
70
- ### Using an an MCP Server:
71
-
72
- AI Prompt:
73
- ```text
74
- Download me this video: https://youtube.com/watch?askdjfa
75
- ```
76
-
77
- AI Response:
78
- ```text
79
- Sure thing, the video has been downloaded to:
80
-
81
- "C:\Users\User\Downloads\YouTube Video - Episode 1.mp4"
82
- ```
83
-
84
- </details>
85
-
86
- <details>
87
- <summary><b>Example:</b></summary>
88
-
89
- ### Use in CLI
90
-
91
- ```bash
92
- media-downloader --file "C:\Users\videos.txt" --directory "C:\Users\Downloads" --channel "WhiteHouse" --links "URL1,URL2,URL3"
93
- ```
94
-
95
- ### Use in Python
96
-
97
- ```python
98
- # Import library
99
- from media_downloader import MediaDownloader
100
-
101
- # Set URL of video/audio here
102
- url = "https://YootToob.com/video"
103
-
104
- # Instantiate vide_downloader_instance
105
- video_downloader_instance = MediaDownloader()
106
-
107
- # Set the location to save the video
108
- video_downloader_instance.set_save_path("C:/Users/you/Downloads")
109
-
110
- # Add URL to download
111
- video_downloader_instance.append_link(url)
112
-
113
- # Download all videos appended
114
- video_downloader_instance.download_all()
115
- ```
116
-
117
- ```python
118
- # Optional - Set Audio to True, Default is False if unspecified.
119
- video_downloader_instance.set_audio(audio=True)
120
-
121
- # Optional - Open a file of video/audio URL(s)
122
- video_downloader_instance.open_file("FILE")
123
-
124
- # Optional - Enter a YouTube channel name and download their latest videos
125
- video_downloader_instance.get_channel_videos("YT-Channel Name")
126
- ```
127
-
128
- ### Use with AI
129
-
130
- Deploy MCP Server as a Service
131
- ```bash
132
- docker pull knucklessg1/media-downloader:latest
133
- ```
134
-
135
- Modify the `compose.yml`
136
-
137
- ```compose
138
- services:
139
- media-downloader-mcp:
140
- image: knucklessg1/media-downloader:latest
141
- volumes:
142
- - downloads:/root/Downloads
143
- environment:
144
- - HOST=0.0.0.0
145
- - PORT=8000
146
- ports:
147
- - 8000:8000
148
- ```
149
-
150
- Configure `mcp.json`
151
-
152
- ```json
153
- {
154
- "mcpServers": {
155
- "media_downloader": {
156
- "command": "uv",
157
- "args": [
158
- "run",
159
- "--with",
160
- "media-downloader",
161
- "media-downloader-mcp"
162
- ],
163
- "env": {
164
- "DOWNLOAD_DIRECTORY": "~/Downloads", // Optional - Can be specified at prompt
165
- "AUDIO_ONLY": false // Optional - Can be specified at prompt
166
- },
167
- "timeout": 300000
168
- }
169
- }
170
- }
171
-
172
- ```
173
- Run as a docker container:
174
-
175
- ```yaml
176
- services:
177
- media-downloader-mcp:
178
- image: docker.io/knucklessg1/media-downloader:latest
179
- ports:
180
- - "8000:8000"
181
- volumes:
182
- - "/home/genius/Downloads:/downloads"
183
- environment:
184
- - HOST=0.0.0.0
185
- - PORT=8000
186
- - TRANSPORT=http
187
- - DOWNLOAD_DIRECTORY=/downloads
188
- - AUDIO_ONLY=false
189
- ```
190
- </details>
191
-
192
- <details>
193
- <summary><b>Installation Instructions:</b></summary>
194
-
195
- Install Python Package
196
-
197
- ```bash
198
- python -m pip install media-downloader
199
- ```
200
- </details>
201
-
202
- ## Geniusbot Application
203
-
204
- Use with a GUI through Geniusbot
205
-
206
- Visit our [GitHub](https://github.com/Knuckles-Team/geniusbot) for more information
207
-
208
- <details>
209
- <summary><b>Installation Instructions with Geniusbot:</b></summary>
210
-
211
- Install Python Package
212
-
213
- ```bash
214
- python -m pip install geniusbot
215
- ```
216
-
217
- </details>
218
-
219
- <details>
220
- <summary><b>Repository Owners:</b></summary>
221
-
222
-
223
- <img width="100%" height="180em" src="https://github-readme-stats.vercel.app/api?username=Knucklessg1&show_icons=true&hide_border=true&&count_private=true&include_all_commits=true" />
224
-
225
- ![GitHub followers](https://img.shields.io/github/followers/Knucklessg1)
226
- ![GitHub User's stars](https://img.shields.io/github/stars/Knucklessg1)
227
- </details>
@@ -1,11 +0,0 @@
1
- media_downloader/__init__.py,sha256=NTYKOsoerw5jh4lryKFMofaK8bsJl0vS8UwhUED1wz4,821
2
- media_downloader/__main__.py,sha256=5T-EOUX1ANJOd2ut4GoI9mvDpNCo25yZcOAZdnhzQI0,169
3
- media_downloader/media_downloader.py,sha256=L20XUnnJ5UWq4ZZQIdmi7ZrOl2hXKSZkjNDH6l0eqKc,9097
4
- media_downloader/media_downloader_mcp.py,sha256=czkZGjzVDXoyZO1MuN6kONemg1Gy_odGCXmHyJ_Fy5w,6359
5
- media_downloader-2.1.8.dist-info/licenses/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
6
- tests/test_mcp.py,sha256=mbe5O75w2SDr7-7nbzDSAHhMYx4qZKccU77h8Cp5LSo,1509
7
- media_downloader-2.1.8.dist-info/METADATA,sha256=YUJUfM_lL8Xh36cxP26NZky0H-F5YtoBpxZMjjzkJwo,6339
8
- media_downloader-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- media_downloader-2.1.8.dist-info/entry_points.txt,sha256=X_Ig7LdYJePZ9BQPMGyA2dSmBIQIYMHXCnTOeEbhgio,170
10
- media_downloader-2.1.8.dist-info/top_level.txt,sha256=baD75VEFaytQEs4mmqyK1M0iZ5Y0HGF62vvtbSfbZCA,23
11
- media_downloader-2.1.8.dist-info/RECORD,,