ytp-dl 0.6.0__py3-none-any.whl → 0.6.2__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.
- scripts/api.py +2 -9
- scripts/downloader.py +48 -102
- {ytp_dl-0.6.0.dist-info → ytp_dl-0.6.2.dist-info}/METADATA +46 -70
- ytp_dl-0.6.2.dist-info/RECORD +8 -0
- ytp_dl-0.6.0.dist-info/RECORD +0 -8
- {ytp_dl-0.6.0.dist-info → ytp_dl-0.6.2.dist-info}/WHEEL +0 -0
- {ytp_dl-0.6.0.dist-info → ytp_dl-0.6.2.dist-info}/entry_points.txt +0 -0
- {ytp_dl-0.6.0.dist-info → ytp_dl-0.6.2.dist-info}/top_level.txt +0 -0
scripts/api.py
CHANGED
|
@@ -20,9 +20,9 @@ MAX_CONCURRENT = int(os.environ.get("YTPDL_MAX_CONCURRENT", "1"))
|
|
|
20
20
|
_sem = Semaphore(MAX_CONCURRENT)
|
|
21
21
|
|
|
22
22
|
# Failsafe: delete abandoned job dirs older than this many seconds.
|
|
23
|
-
# (keep 21600 if you prefer; 3600 is fine too)
|
|
24
23
|
STALE_JOB_TTL_S = int(os.environ.get("YTPDL_STALE_JOB_TTL_S", "3600"))
|
|
25
24
|
|
|
25
|
+
# extension is now a "mode": mp3 | mp4 | best
|
|
26
26
|
_ALLOWED_EXTENSIONS = {"mp3", "mp4", "best"}
|
|
27
27
|
|
|
28
28
|
|
|
@@ -63,8 +63,6 @@ def handle_download():
|
|
|
63
63
|
data = request.get_json(force=True)
|
|
64
64
|
url = (data.get("url") or "").strip()
|
|
65
65
|
resolution = data.get("resolution")
|
|
66
|
-
|
|
67
|
-
# extension is now a "mode": mp3 | mp4 | best
|
|
68
66
|
extension = (data.get("extension") or "mp4").strip().lower()
|
|
69
67
|
|
|
70
68
|
if not url:
|
|
@@ -91,7 +89,6 @@ def handle_download():
|
|
|
91
89
|
raise RuntimeError("Download failed")
|
|
92
90
|
|
|
93
91
|
# Release semaphore as soon as yt-dlp is done.
|
|
94
|
-
# Streaming the file should not block the next download job.
|
|
95
92
|
_release_once()
|
|
96
93
|
|
|
97
94
|
response = send_file(filename, as_attachment=True)
|
|
@@ -111,11 +108,7 @@ def handle_download():
|
|
|
111
108
|
if job_dir:
|
|
112
109
|
shutil.rmtree(job_dir, ignore_errors=True)
|
|
113
110
|
_release_once()
|
|
114
|
-
|
|
115
|
-
msg = str(e)
|
|
116
|
-
if "Mullvad not logged in" in msg:
|
|
117
|
-
return jsonify(error=msg), 503
|
|
118
|
-
return jsonify(error=f"Download failed: {msg}"), 500
|
|
111
|
+
return jsonify(error=f"Download failed: {str(e)}"), 500
|
|
119
112
|
|
|
120
113
|
except Exception as e:
|
|
121
114
|
if job_dir:
|
scripts/downloader.py
CHANGED
|
@@ -5,15 +5,13 @@ import os
|
|
|
5
5
|
import shlex
|
|
6
6
|
import shutil
|
|
7
7
|
import subprocess
|
|
8
|
-
import time
|
|
9
8
|
from typing import Optional, List, Tuple
|
|
10
9
|
|
|
11
10
|
# =========================
|
|
12
11
|
# Config / constants
|
|
13
12
|
# =========================
|
|
14
|
-
VENV_PATH = os.environ.get("YTPDL_VENV", "/opt/
|
|
13
|
+
VENV_PATH = os.environ.get("YTPDL_VENV", "/opt/ytpdl/venv")
|
|
15
14
|
YTDLP_BIN = os.path.join(VENV_PATH, "bin", "yt-dlp")
|
|
16
|
-
MULLVAD_LOCATION = os.environ.get("YTPDL_MULLVAD_LOCATION", "us")
|
|
17
15
|
|
|
18
16
|
MODERN_UA = os.environ.get(
|
|
19
17
|
"YTPDL_USER_AGENT",
|
|
@@ -22,6 +20,11 @@ MODERN_UA = os.environ.get(
|
|
|
22
20
|
"Chrome/124.0.0.0 Safari/537.36",
|
|
23
21
|
)
|
|
24
22
|
|
|
23
|
+
# Optional: explicitly pin a JS runtime (useful if systemd PATH is odd).
|
|
24
|
+
# Example: YTPDL_JS_RUNTIMES="deno:/usr/local/bin/deno"
|
|
25
|
+
# Deno is enabled by default in yt-dlp; supplying a path is optional. :contentReference[oaicite:3]{index=3}
|
|
26
|
+
JS_RUNTIMES = os.environ.get("YTPDL_JS_RUNTIMES", "").strip()
|
|
27
|
+
|
|
25
28
|
FFMPEG_BIN = shutil.which("ffmpeg") or "ffmpeg"
|
|
26
29
|
DEFAULT_OUT_DIR = os.environ.get("YTPDL_DOWNLOAD_DIR", "/root")
|
|
27
30
|
|
|
@@ -60,13 +63,8 @@ def _tail(out: str) -> str:
|
|
|
60
63
|
return txt.strip()
|
|
61
64
|
|
|
62
65
|
|
|
63
|
-
def _is_youtube_url(url: str) -> bool:
|
|
64
|
-
u = (url or "").lower()
|
|
65
|
-
return any(h in u for h in ("youtube.com", "youtu.be", "youtube-nocookie.com"))
|
|
66
|
-
|
|
67
|
-
|
|
68
66
|
# =========================
|
|
69
|
-
# Environment
|
|
67
|
+
# Environment checks
|
|
70
68
|
# =========================
|
|
71
69
|
def validate_environment() -> None:
|
|
72
70
|
if not os.path.exists(YTDLP_BIN):
|
|
@@ -75,59 +73,12 @@ def validate_environment() -> None:
|
|
|
75
73
|
raise RuntimeError("ffmpeg not found on PATH")
|
|
76
74
|
|
|
77
75
|
|
|
78
|
-
def _mullvad_present() -> bool:
|
|
79
|
-
return shutil.which("mullvad") is not None
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def mullvad_logged_in() -> bool:
|
|
83
|
-
if not _mullvad_present():
|
|
84
|
-
return False
|
|
85
|
-
res = subprocess.run(
|
|
86
|
-
["mullvad", "account", "get"],
|
|
87
|
-
stdout=subprocess.PIPE,
|
|
88
|
-
stderr=subprocess.STDOUT,
|
|
89
|
-
text=True,
|
|
90
|
-
)
|
|
91
|
-
return "not logged in" not in (res.stdout or "").lower()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def require_mullvad_login() -> None:
|
|
95
|
-
if _mullvad_present() and not mullvad_logged_in():
|
|
96
|
-
raise RuntimeError("Mullvad not logged in. Run: mullvad account login <ACCOUNT>")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def mullvad_connect(location: Optional[str] = None) -> None:
|
|
100
|
-
if not _mullvad_present():
|
|
101
|
-
return
|
|
102
|
-
loc = (location or MULLVAD_LOCATION).strip()
|
|
103
|
-
_run_argv(["mullvad", "disconnect"], check=False)
|
|
104
|
-
if loc:
|
|
105
|
-
_run_argv(["mullvad", "relay", "set", "location", loc], check=False)
|
|
106
|
-
_run_argv(["mullvad", "connect"], check=False)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def mullvad_wait_connected(timeout: int = 20) -> bool:
|
|
110
|
-
if not _mullvad_present():
|
|
111
|
-
return True
|
|
112
|
-
for _ in range(timeout):
|
|
113
|
-
res = subprocess.run(
|
|
114
|
-
["mullvad", "status"],
|
|
115
|
-
stdout=subprocess.PIPE,
|
|
116
|
-
stderr=subprocess.STDOUT,
|
|
117
|
-
text=True,
|
|
118
|
-
)
|
|
119
|
-
if "Connected" in (res.stdout or ""):
|
|
120
|
-
return True
|
|
121
|
-
time.sleep(1)
|
|
122
|
-
return False
|
|
123
|
-
|
|
124
|
-
|
|
125
76
|
# =========================
|
|
126
77
|
# yt-dlp helpers
|
|
127
78
|
# =========================
|
|
128
79
|
def _common_flags() -> List[str]:
|
|
129
80
|
# --no-playlist prevents accidental channel/playlist pulls (and disk blowups)
|
|
130
|
-
|
|
81
|
+
flags = [
|
|
131
82
|
"--no-playlist",
|
|
132
83
|
"--retries", "10",
|
|
133
84
|
"--fragment-retries", "10",
|
|
@@ -139,6 +90,13 @@ def _common_flags() -> List[str]:
|
|
|
139
90
|
"--sleep-interval", "1",
|
|
140
91
|
]
|
|
141
92
|
|
|
93
|
+
# If you want to hard-pin deno (or any runtime), set YTPDL_JS_RUNTIMES.
|
|
94
|
+
# Example: deno:/usr/local/bin/deno :contentReference[oaicite:4]{index=4}
|
|
95
|
+
if JS_RUNTIMES:
|
|
96
|
+
flags.extend(["--js-runtimes", JS_RUNTIMES])
|
|
97
|
+
|
|
98
|
+
return flags
|
|
99
|
+
|
|
142
100
|
|
|
143
101
|
def _extract_final_path(stdout: str, out_dir: str) -> Optional[str]:
|
|
144
102
|
"""
|
|
@@ -257,7 +215,6 @@ def _download_with_format(
|
|
|
257
215
|
]
|
|
258
216
|
|
|
259
217
|
if extract_mp3:
|
|
260
|
-
# Force audio extraction to MP3 (requires ffmpeg)
|
|
261
218
|
argv.extend(["--extract-audio", "--audio-format", "mp3"])
|
|
262
219
|
|
|
263
220
|
# Only force merge container when we actually want MP4 output.
|
|
@@ -309,55 +266,44 @@ def download_video(
|
|
|
309
266
|
|
|
310
267
|
validate_environment()
|
|
311
268
|
|
|
312
|
-
|
|
313
|
-
mullvad_connect(MULLVAD_LOCATION)
|
|
314
|
-
if not mullvad_wait_connected():
|
|
315
|
-
raise RuntimeError("Mullvad connection failed")
|
|
269
|
+
mode = (extension or "mp4").lower().strip()
|
|
316
270
|
|
|
317
|
-
|
|
318
|
-
|
|
271
|
+
if mode == "mp3":
|
|
272
|
+
return _download_with_format(
|
|
273
|
+
url=url,
|
|
274
|
+
out_dir=out_dir,
|
|
275
|
+
fmt="bestaudio",
|
|
276
|
+
merge_output_format=None,
|
|
277
|
+
extract_mp3=True,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
cap = int(resolution or 1080)
|
|
319
281
|
|
|
320
|
-
|
|
321
|
-
|
|
282
|
+
if mode == "best":
|
|
283
|
+
# Try best first (may produce webm/mkv/etc).
|
|
284
|
+
try:
|
|
322
285
|
return _download_with_format(
|
|
323
286
|
url=url,
|
|
324
287
|
out_dir=out_dir,
|
|
325
|
-
fmt=
|
|
288
|
+
fmt=_fmt_best(cap),
|
|
326
289
|
merge_output_format=None,
|
|
327
|
-
extract_mp3=
|
|
290
|
+
extract_mp3=False,
|
|
291
|
+
)
|
|
292
|
+
except Exception:
|
|
293
|
+
# If best fails, fall back to Apple-safe MP4.
|
|
294
|
+
return _download_with_format(
|
|
295
|
+
url=url,
|
|
296
|
+
out_dir=out_dir,
|
|
297
|
+
fmt=_fmt_mp4_apple_safe(cap),
|
|
298
|
+
merge_output_format="mp4",
|
|
299
|
+
extract_mp3=False,
|
|
328
300
|
)
|
|
329
301
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
fmt=_fmt_best(cap),
|
|
339
|
-
merge_output_format=None,
|
|
340
|
-
extract_mp3=False,
|
|
341
|
-
)
|
|
342
|
-
except Exception:
|
|
343
|
-
# If best fails for any reason, fall back to Apple-safe MP4.
|
|
344
|
-
return _download_with_format(
|
|
345
|
-
url=url,
|
|
346
|
-
out_dir=out_dir,
|
|
347
|
-
fmt=_fmt_mp4_apple_safe(cap),
|
|
348
|
-
merge_output_format="mp4",
|
|
349
|
-
extract_mp3=False,
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
# Default / "mp4" mode: force Apple-safe MP4 up to cap.
|
|
353
|
-
return _download_with_format(
|
|
354
|
-
url=url,
|
|
355
|
-
out_dir=out_dir,
|
|
356
|
-
fmt=_fmt_mp4_apple_safe(cap),
|
|
357
|
-
merge_output_format="mp4",
|
|
358
|
-
extract_mp3=False,
|
|
359
|
-
)
|
|
360
|
-
|
|
361
|
-
finally:
|
|
362
|
-
if _mullvad_present():
|
|
363
|
-
_run_argv(["mullvad", "disconnect"], check=False)
|
|
302
|
+
# Default / "mp4" mode: force Apple-safe MP4 up to cap.
|
|
303
|
+
return _download_with_format(
|
|
304
|
+
url=url,
|
|
305
|
+
out_dir=out_dir,
|
|
306
|
+
fmt=_fmt_mp4_apple_safe(cap),
|
|
307
|
+
merge_output_format="mp4",
|
|
308
|
+
extract_mp3=False,
|
|
309
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: ytp-dl
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: YouTube video downloader with Mullvad VPN integration and Flask API
|
|
5
5
|
Home-page: https://github.com/yourusername/ytp-dl
|
|
6
6
|
Author: dumgum82
|
|
@@ -34,37 +34,35 @@ Dynamic: summary
|
|
|
34
34
|
|
|
35
35
|
# ytp-dl
|
|
36
36
|
|
|
37
|
-
> A lightweight YouTube downloader with
|
|
37
|
+
> A lightweight YouTube downloader with an HTTP API
|
|
38
38
|
|
|
39
39
|
[](https://pypi.org/project/ytp-dl/)
|
|
40
40
|
[](https://pypi.org/project/ytp-dl/)
|
|
41
41
|
[](https://pypi.org/project/ytp-dl/)
|
|
42
42
|
[](https://pypi.org/project/ytp-dl/)
|
|
43
43
|
|
|
44
|
-
**ytp-dl** is a privacy-focused YouTube downloader that
|
|
44
|
+
**ytp-dl** is a privacy-focused YouTube downloader that exposes a simple HTTP API for automated downloads.
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## Features
|
|
49
49
|
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* ⚡ **VPS Ready** — Includes automated installer script for Ubuntu
|
|
50
|
+
* Smart quality selection (prefers 1080p H.264 + AAC when available; no transcoding needed)
|
|
51
|
+
* Audio downloads (extract audio as MP3)
|
|
52
|
+
* HTTP API (Flask-based API with concurrency controls)
|
|
53
|
+
* VPS-ready (includes an automated installer script for Ubuntu)
|
|
55
54
|
|
|
56
55
|
---
|
|
57
56
|
|
|
58
|
-
##
|
|
57
|
+
## Installation
|
|
59
58
|
|
|
60
59
|
```bash
|
|
61
|
-
pip install ytp-dl==0.6.
|
|
60
|
+
pip install ytp-dl==0.6.2 yt-dlp[default]
|
|
62
61
|
```
|
|
63
62
|
|
|
64
63
|
**Requirements:**
|
|
65
64
|
|
|
66
65
|
* Linux operating system (tested on Ubuntu 24.04/25.04)
|
|
67
|
-
* [Mullvad CLI](https://mullvad.net/en/download/vpn/linux) installed and configured
|
|
68
66
|
* FFmpeg (for handling audio + video)
|
|
69
67
|
* Deno (system-wide, required by yt-dlp for modern YouTube extraction)
|
|
70
68
|
* Python 3.8+
|
|
@@ -75,7 +73,7 @@ Notes:
|
|
|
75
73
|
|
|
76
74
|
---
|
|
77
75
|
|
|
78
|
-
##
|
|
76
|
+
## Using Your VPS
|
|
79
77
|
|
|
80
78
|
Once your VPS is running, you can download videos using simple HTTP requests:
|
|
81
79
|
|
|
@@ -140,34 +138,26 @@ else:
|
|
|
140
138
|
|
|
141
139
|
---
|
|
142
140
|
|
|
143
|
-
##
|
|
141
|
+
## Configuration
|
|
144
142
|
|
|
145
143
|
### Installation Script Variables
|
|
146
144
|
|
|
147
145
|
These environment variables configure the VPS installation (they can be overridden when running the script):
|
|
148
146
|
|
|
149
|
-
| Variable
|
|
150
|
-
|
|
|
151
|
-
| `PORT`
|
|
152
|
-
| `APP_DIR`
|
|
153
|
-
| `
|
|
154
|
-
| `YTPDL_MAX_CONCURRENT` | Max simultaneous downloads (API cap) | `1` |
|
|
155
|
-
| `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code (e.g. `us`) | `us` |
|
|
156
|
-
|
|
157
|
-
Notes:
|
|
158
|
-
|
|
159
|
-
* If `MV_ACCOUNT` is set, the installer attempts `mullvad account login <MV_ACCOUNT>` once.
|
|
160
|
-
* If `MV_ACCOUNT` is left empty, the script skips login and assumes Mullvad is already configured.
|
|
147
|
+
| Variable | Description | Default |
|
|
148
|
+
| ---------------------- | ------------------------------------ | ------------------ |
|
|
149
|
+
| `PORT` | API server port | `5000` |
|
|
150
|
+
| `APP_DIR` | Installation directory | `/opt/ytp-dl` |
|
|
151
|
+
| `YTPDL_MAX_CONCURRENT` | Max simultaneous downloads (API cap) | `1` |
|
|
161
152
|
|
|
162
153
|
### Runtime Environment Variables
|
|
163
154
|
|
|
164
155
|
After installation, these variables control the API behavior. They are set in `/etc/default/ytp-dl-api` and can be edited manually:
|
|
165
156
|
|
|
166
|
-
| Variable
|
|
167
|
-
|
|
|
168
|
-
| `YTPDL_MAX_CONCURRENT`
|
|
169
|
-
| `
|
|
170
|
-
| `YTPDL_VENV` | Path to virtualenv for ytp-dl | `/opt/yt-dlp-mullvad/venv` |
|
|
157
|
+
| Variable | Description | Default |
|
|
158
|
+
| ---------------------- | ------------------------------- | --------------------- |
|
|
159
|
+
| `YTPDL_MAX_CONCURRENT` | Maximum concurrent downloads | `1` |
|
|
160
|
+
| `YTPDL_VENV` | Path to virtualenv for ytp-dl | `/opt/ytp-dl/venv` |
|
|
171
161
|
|
|
172
162
|
To change configuration after installation:
|
|
173
163
|
|
|
@@ -178,7 +168,7 @@ sudo systemctl restart ytp-dl-api
|
|
|
178
168
|
|
|
179
169
|
---
|
|
180
170
|
|
|
181
|
-
##
|
|
171
|
+
## Managing Your VPS Service
|
|
182
172
|
|
|
183
173
|
### View Service Status
|
|
184
174
|
|
|
@@ -207,7 +197,7 @@ sudo systemctl start ytp-dl-api
|
|
|
207
197
|
|
|
208
198
|
---
|
|
209
199
|
|
|
210
|
-
##
|
|
200
|
+
## API Reference
|
|
211
201
|
|
|
212
202
|
### POST `/api/download`
|
|
213
203
|
|
|
@@ -242,60 +232,45 @@ sudo systemctl start ytp-dl-api
|
|
|
242
232
|
|
|
243
233
|
---
|
|
244
234
|
|
|
245
|
-
##
|
|
235
|
+
## VPS Deployment
|
|
246
236
|
|
|
247
237
|
**What it does:**
|
|
248
238
|
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
239
|
+
* Installs Python and FFmpeg
|
|
240
|
+
* Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
241
|
+
* Creates a virtualenv at `/opt/ytp-dl/venv`
|
|
242
|
+
* Installs `ytp-dl==0.6.2` + `yt-dlp[default]` into the virtualenv
|
|
243
|
+
* Sets up a systemd service on port 5000
|
|
244
|
+
* Configures Gunicorn with gevent workers
|
|
255
245
|
|
|
256
246
|
```bash
|
|
257
247
|
#!/usr/bin/env bash
|
|
258
|
-
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API
|
|
248
|
+
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API
|
|
259
249
|
#
|
|
260
250
|
# What this does:
|
|
261
|
-
# - Installs Python
|
|
251
|
+
# - Installs Python + ffmpeg
|
|
262
252
|
# - Installs Deno system-wide (JS runtime required for modern YouTube extraction via yt-dlp)
|
|
263
|
-
# - Creates a virtualenv at /opt/
|
|
264
|
-
# - Installs ytp-dl==0.6.
|
|
253
|
+
# - Creates a virtualenv at /opt/ytp-dl/venv
|
|
254
|
+
# - Installs ytp-dl==0.6.2 + yt-dlp[default] + gunicorn + gevent in that venv
|
|
265
255
|
# - Creates a simple systemd service ytp-dl-api.service on port 5000
|
|
266
|
-
#
|
|
267
|
-
# Mullvad connect/disconnect is handled per-job by downloader.py.
|
|
268
256
|
|
|
269
257
|
set -euo pipefail
|
|
270
258
|
|
|
271
259
|
### --- Tunables -------------------------------------------------------------
|
|
272
|
-
PORT="${PORT:-5000}"
|
|
273
|
-
APP_DIR="${APP_DIR:-/opt/
|
|
274
|
-
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}"
|
|
260
|
+
PORT="${PORT:-5000}" # API listen port
|
|
261
|
+
APP_DIR="${APP_DIR:-/opt/ytp-dl}" # app/venv root
|
|
262
|
+
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}" # python venv
|
|
275
263
|
|
|
276
|
-
|
|
277
|
-
YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
|
|
278
|
-
YTPDL_MULLVAD_LOCATION="${YTPDL_MULLVAD_LOCATION:-us}" # default Mullvad relay hint
|
|
264
|
+
YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
|
|
279
265
|
### -------------------------------------------------------------------------
|
|
280
266
|
|
|
281
267
|
[[ "${EUID}" -eq 0 ]] || { echo "Please run as root"; exit 1; }
|
|
282
268
|
export DEBIAN_FRONTEND=noninteractive
|
|
283
269
|
|
|
284
|
-
echo "==> 1) Base packages
|
|
270
|
+
echo "==> 1) Base packages"
|
|
285
271
|
apt-get update
|
|
286
|
-
apt-get install -yq --no-install-recommends
|
|
287
|
-
|
|
288
|
-
if ! command -v mullvad >/dev/null 2>&1; then
|
|
289
|
-
curl -fsSLo /tmp/mullvad.deb https://mullvad.net/download/app/deb/latest/
|
|
290
|
-
apt-get install -y /tmp/mullvad.deb
|
|
291
|
-
fi
|
|
292
|
-
|
|
293
|
-
if [[ -n "${MV_ACCOUNT}" ]]; then
|
|
294
|
-
echo "Logging into Mullvad account (if not already logged in)..."
|
|
295
|
-
mullvad account login "${MV_ACCOUNT}" || true
|
|
296
|
-
fi
|
|
297
|
-
|
|
298
|
-
mullvad status || true
|
|
272
|
+
apt-get install -yq --no-install-recommends \
|
|
273
|
+
python3-venv python3-pip curl ffmpeg ca-certificates unzip
|
|
299
274
|
|
|
300
275
|
echo "==> 1.5) Install Deno (system-wide, for yt-dlp YouTube extraction)"
|
|
301
276
|
# Install into /usr/local/bin/deno so systemd PATH can see it.
|
|
@@ -310,20 +285,19 @@ mkdir -p "${APP_DIR}"
|
|
|
310
285
|
python3 -m venv "${VENV_DIR}"
|
|
311
286
|
source "${VENV_DIR}/bin/activate"
|
|
312
287
|
pip install --upgrade pip
|
|
313
|
-
pip install "ytp-dl==0.6.
|
|
288
|
+
pip install "ytp-dl==0.6.2" "yt-dlp[default]" gunicorn gevent
|
|
314
289
|
deactivate
|
|
315
290
|
|
|
316
291
|
echo "==> 3) API environment file (/etc/default/ytp-dl-api)"
|
|
317
292
|
tee /etc/default/ytp-dl-api >/dev/null <<EOF
|
|
318
293
|
YTPDL_MAX_CONCURRENT=${YTPDL_MAX_CONCURRENT}
|
|
319
|
-
YTPDL_MULLVAD_LOCATION=${YTPDL_MULLVAD_LOCATION}
|
|
320
294
|
YTPDL_VENV=${VENV_DIR}
|
|
321
295
|
EOF
|
|
322
296
|
|
|
323
297
|
echo "==> 4) Gunicorn systemd service (ytp-dl-api.service on :${PORT})"
|
|
324
298
|
tee /etc/systemd/system/ytp-dl-api.service >/dev/null <<EOF
|
|
325
299
|
[Unit]
|
|
326
|
-
Description=Gunicorn for ytp-dl
|
|
300
|
+
Description=Gunicorn for ytp-dl API (minimal)
|
|
327
301
|
After=network-online.target
|
|
328
302
|
Wants=network-online.target
|
|
329
303
|
|
|
@@ -334,7 +308,9 @@ EnvironmentFile=/etc/default/ytp-dl-api
|
|
|
334
308
|
Environment=VIRTUAL_ENV=${VENV_DIR}
|
|
335
309
|
Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
|
336
310
|
|
|
337
|
-
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1
|
|
311
|
+
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1 \
|
|
312
|
+
--worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 \
|
|
313
|
+
--bind 0.0.0.0:${PORT} scripts.api:app
|
|
338
314
|
|
|
339
315
|
Restart=always
|
|
340
316
|
RestartSec=3
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
scripts/__init__.py,sha256=EbAplfCcyLD3Q_9sxemm6owCc5_UJv53vmlxy810p2s,152
|
|
2
|
+
scripts/api.py,sha256=K-4iwgj6W4Gx8y3mzBe_CP4Ua9Ky9quESOqcw6BpNv0,3713
|
|
3
|
+
scripts/downloader.py,sha256=NGW1TmPmjHCTlN1uUNYwhSBm1c7UotkF8Pn9Q0dxqLk,9227
|
|
4
|
+
ytp_dl-0.6.2.dist-info/METADATA,sha256=7U33Y4moFmjs1xivWbR3_xGe5imTbGFlecFx6BI63os,9754
|
|
5
|
+
ytp_dl-0.6.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
6
|
+
ytp_dl-0.6.2.dist-info/entry_points.txt,sha256=QqjqZZAEt3Y7RGrleqZ312sjjboUpbMLdo7qFxuCH30,48
|
|
7
|
+
ytp_dl-0.6.2.dist-info/top_level.txt,sha256=rmzd5mewlrJy4sT608KPib7sM7edoY75AeqJeY3SPB4,8
|
|
8
|
+
ytp_dl-0.6.2.dist-info/RECORD,,
|
ytp_dl-0.6.0.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
scripts/__init__.py,sha256=EbAplfCcyLD3Q_9sxemm6owCc5_UJv53vmlxy810p2s,152
|
|
2
|
-
scripts/api.py,sha256=EmTmzhpElx5QaJJ5z8GiimJTVZOHRoKhcReIRUCShBg,3943
|
|
3
|
-
scripts/downloader.py,sha256=vvHasu-41DGPDUzOTA4kz52tijTkaii1NnuU4cHQxg8,10825
|
|
4
|
-
ytp_dl-0.6.0.dist-info/METADATA,sha256=3779KleCiYQVmOhwhPj5SYudvuESfW-Cvz7boCYk7c8,11342
|
|
5
|
-
ytp_dl-0.6.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
6
|
-
ytp_dl-0.6.0.dist-info/entry_points.txt,sha256=QqjqZZAEt3Y7RGrleqZ312sjjboUpbMLdo7qFxuCH30,48
|
|
7
|
-
ytp_dl-0.6.0.dist-info/top_level.txt,sha256=rmzd5mewlrJy4sT608KPib7sM7edoY75AeqJeY3SPB4,8
|
|
8
|
-
ytp_dl-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|