ytp-dl 0.6.2__tar.gz → 0.6.3__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.
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/PKG-INFO +70 -46
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/README.md +70 -46
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/scripts/api.py +9 -2
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/scripts/downloader.py +102 -48
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/setup.py +1 -1
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/PKG-INFO +70 -46
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/scripts/__init__.py +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/setup.cfg +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/SOURCES.txt +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/dependency_links.txt +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/entry_points.txt +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/requires.txt +0 -0
- {ytp_dl-0.6.2 → ytp_dl-0.6.3}/ytp_dl.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: ytp-dl
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
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,35 +34,37 @@ Dynamic: summary
|
|
|
34
34
|
|
|
35
35
|
# ytp-dl
|
|
36
36
|
|
|
37
|
-
> A lightweight YouTube downloader with
|
|
37
|
+
> A lightweight YouTube downloader with Mullvad VPN integration and 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 automatically routes downloads through Mullvad VPN via an HTTP API.
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
## Features
|
|
48
|
+
## ✨ Features
|
|
49
49
|
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* 🔒 **Privacy First** — Automatically connects/disconnects Mullvad VPN per download
|
|
51
|
+
* 🎥 **Smart Quality Selection** — Prefers 1080p H.264 + AAC (no transcoding needed)
|
|
52
|
+
* 🎵 **Audio Downloads** — Extract audio as MP3
|
|
53
|
+
* 🚀 **HTTP API** — Simple Flask-based API with concurrency controls
|
|
54
|
+
* ⚡ **VPS Ready** — Includes automated installer script for Ubuntu
|
|
54
55
|
|
|
55
56
|
---
|
|
56
57
|
|
|
57
|
-
## Installation
|
|
58
|
+
## 📦 Installation
|
|
58
59
|
|
|
59
60
|
```bash
|
|
60
|
-
pip install ytp-dl==0.6.
|
|
61
|
+
pip install ytp-dl==0.6.3 yt-dlp[default]
|
|
61
62
|
```
|
|
62
63
|
|
|
63
64
|
**Requirements:**
|
|
64
65
|
|
|
65
66
|
* Linux operating system (tested on Ubuntu 24.04/25.04)
|
|
67
|
+
* [Mullvad CLI](https://mullvad.net/en/download/vpn/linux) installed and configured
|
|
66
68
|
* FFmpeg (for handling audio + video)
|
|
67
69
|
* Deno (system-wide, required by yt-dlp for modern YouTube extraction)
|
|
68
70
|
* Python 3.8+
|
|
@@ -73,7 +75,7 @@ Notes:
|
|
|
73
75
|
|
|
74
76
|
---
|
|
75
77
|
|
|
76
|
-
## Using Your VPS
|
|
78
|
+
## 🎯 Using Your VPS
|
|
77
79
|
|
|
78
80
|
Once your VPS is running, you can download videos using simple HTTP requests:
|
|
79
81
|
|
|
@@ -138,26 +140,34 @@ else:
|
|
|
138
140
|
|
|
139
141
|
---
|
|
140
142
|
|
|
141
|
-
## Configuration
|
|
143
|
+
## ⚙️ Configuration
|
|
142
144
|
|
|
143
145
|
### Installation Script Variables
|
|
144
146
|
|
|
145
147
|
These environment variables configure the VPS installation (they can be overridden when running the script):
|
|
146
148
|
|
|
147
|
-
| Variable
|
|
148
|
-
|
|
|
149
|
-
| `PORT`
|
|
150
|
-
| `APP_DIR`
|
|
151
|
-
| `
|
|
149
|
+
| Variable | Description | Default |
|
|
150
|
+
| ------------------------ | --------------------------------------- | --------------------- |
|
|
151
|
+
| `PORT` | API server port | `5000` |
|
|
152
|
+
| `APP_DIR` | Installation directory | `/opt/yt-dlp-mullvad` |
|
|
153
|
+
| `MV_ACCOUNT` | Mullvad account number | your mullvad id |
|
|
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.
|
|
152
161
|
|
|
153
162
|
### Runtime Environment Variables
|
|
154
163
|
|
|
155
164
|
After installation, these variables control the API behavior. They are set in `/etc/default/ytp-dl-api` and can be edited manually:
|
|
156
165
|
|
|
157
|
-
| Variable
|
|
158
|
-
|
|
|
159
|
-
| `YTPDL_MAX_CONCURRENT`
|
|
160
|
-
| `
|
|
166
|
+
| Variable | Description | Default |
|
|
167
|
+
| ------------------------ | ----------------------------- | -------------------------- |
|
|
168
|
+
| `YTPDL_MAX_CONCURRENT` | Maximum concurrent downloads | `1` |
|
|
169
|
+
| `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code | `us` |
|
|
170
|
+
| `YTPDL_VENV` | Path to virtualenv for ytp-dl | `/opt/yt-dlp-mullvad/venv` |
|
|
161
171
|
|
|
162
172
|
To change configuration after installation:
|
|
163
173
|
|
|
@@ -168,7 +178,7 @@ sudo systemctl restart ytp-dl-api
|
|
|
168
178
|
|
|
169
179
|
---
|
|
170
180
|
|
|
171
|
-
## Managing Your VPS Service
|
|
181
|
+
## 🔧 Managing Your VPS Service
|
|
172
182
|
|
|
173
183
|
### View Service Status
|
|
174
184
|
|
|
@@ -197,7 +207,7 @@ sudo systemctl start ytp-dl-api
|
|
|
197
207
|
|
|
198
208
|
---
|
|
199
209
|
|
|
200
|
-
## API Reference
|
|
210
|
+
## 📋 API Reference
|
|
201
211
|
|
|
202
212
|
### POST `/api/download`
|
|
203
213
|
|
|
@@ -232,45 +242,60 @@ sudo systemctl start ytp-dl-api
|
|
|
232
242
|
|
|
233
243
|
---
|
|
234
244
|
|
|
235
|
-
## VPS Deployment
|
|
245
|
+
## 🖥️ VPS Deployment
|
|
236
246
|
|
|
237
247
|
**What it does:**
|
|
238
248
|
|
|
239
|
-
* Installs Python and
|
|
240
|
-
* Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
241
|
-
* Creates
|
|
242
|
-
* Installs `ytp-dl==0.6.
|
|
243
|
-
* Sets up
|
|
244
|
-
* Configures Gunicorn with gevent workers
|
|
249
|
+
* ✅ Installs Python, FFmpeg, and Mullvad CLI
|
|
250
|
+
* ✅ Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
251
|
+
* ✅ Creates virtualenv at `/opt/yt-dlp-mullvad/venv`
|
|
252
|
+
* ✅ Installs `ytp-dl==0.6.3` + `yt-dlp[default]` into the virtualenv
|
|
253
|
+
* ✅ Sets up systemd service on port 5000
|
|
254
|
+
* ✅ Configures Gunicorn with gevent workers
|
|
245
255
|
|
|
246
256
|
```bash
|
|
247
257
|
#!/usr/bin/env bash
|
|
248
|
-
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API
|
|
258
|
+
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API + Mullvad
|
|
249
259
|
#
|
|
250
260
|
# What this does:
|
|
251
|
-
# - Installs Python
|
|
261
|
+
# - Installs Python, ffmpeg, Mullvad CLI
|
|
252
262
|
# - Installs Deno system-wide (JS runtime required for modern YouTube extraction via yt-dlp)
|
|
253
|
-
# - Creates a virtualenv at /opt/
|
|
254
|
-
# - Installs ytp-dl==0.6.
|
|
263
|
+
# - Creates a virtualenv at /opt/yt-dlp-mullvad/venv
|
|
264
|
+
# - Installs ytp-dl==0.6.3 + yt-dlp[default] + gunicorn + gevent in that venv
|
|
255
265
|
# - Creates a simple systemd service ytp-dl-api.service on port 5000
|
|
266
|
+
#
|
|
267
|
+
# Mullvad connect/disconnect is handled per-job by downloader.py.
|
|
256
268
|
|
|
257
269
|
set -euo pipefail
|
|
258
270
|
|
|
259
271
|
### --- Tunables -------------------------------------------------------------
|
|
260
|
-
PORT="${PORT:-5000}"
|
|
261
|
-
APP_DIR="${APP_DIR:-/opt/
|
|
262
|
-
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}"
|
|
272
|
+
PORT="${PORT:-5000}" # API listen port
|
|
273
|
+
APP_DIR="${APP_DIR:-/opt/yt-dlp-mullvad}" # app/venv root
|
|
274
|
+
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}" # python venv
|
|
263
275
|
|
|
264
|
-
|
|
276
|
+
MV_ACCOUNT="${MV_ACCOUNT:-}" # Mullvad account (put number after -)
|
|
277
|
+
YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
|
|
278
|
+
YTPDL_MULLVAD_LOCATION="${YTPDL_MULLVAD_LOCATION:-us}" # default Mullvad relay hint
|
|
265
279
|
### -------------------------------------------------------------------------
|
|
266
280
|
|
|
267
281
|
[[ "${EUID}" -eq 0 ]] || { echo "Please run as root"; exit 1; }
|
|
268
282
|
export DEBIAN_FRONTEND=noninteractive
|
|
269
283
|
|
|
270
|
-
echo "==> 1) Base packages"
|
|
284
|
+
echo "==> 1) Base packages & Mullvad CLI"
|
|
271
285
|
apt-get update
|
|
272
|
-
apt-get install -yq --no-install-recommends
|
|
273
|
-
|
|
286
|
+
apt-get install -yq --no-install-recommends python3-venv python3-pip curl ffmpeg ca-certificates unzip
|
|
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
|
|
274
299
|
|
|
275
300
|
echo "==> 1.5) Install Deno (system-wide, for yt-dlp YouTube extraction)"
|
|
276
301
|
# Install into /usr/local/bin/deno so systemd PATH can see it.
|
|
@@ -285,19 +310,20 @@ mkdir -p "${APP_DIR}"
|
|
|
285
310
|
python3 -m venv "${VENV_DIR}"
|
|
286
311
|
source "${VENV_DIR}/bin/activate"
|
|
287
312
|
pip install --upgrade pip
|
|
288
|
-
pip install "ytp-dl==0.6.
|
|
313
|
+
pip install "ytp-dl==0.6.3" "yt-dlp[default]" gunicorn gevent
|
|
289
314
|
deactivate
|
|
290
315
|
|
|
291
316
|
echo "==> 3) API environment file (/etc/default/ytp-dl-api)"
|
|
292
317
|
tee /etc/default/ytp-dl-api >/dev/null <<EOF
|
|
293
318
|
YTPDL_MAX_CONCURRENT=${YTPDL_MAX_CONCURRENT}
|
|
319
|
+
YTPDL_MULLVAD_LOCATION=${YTPDL_MULLVAD_LOCATION}
|
|
294
320
|
YTPDL_VENV=${VENV_DIR}
|
|
295
321
|
EOF
|
|
296
322
|
|
|
297
323
|
echo "==> 4) Gunicorn systemd service (ytp-dl-api.service on :${PORT})"
|
|
298
324
|
tee /etc/systemd/system/ytp-dl-api.service >/dev/null <<EOF
|
|
299
325
|
[Unit]
|
|
300
|
-
Description=Gunicorn for ytp-dl API (minimal)
|
|
326
|
+
Description=Gunicorn for ytp-dl Mullvad API (minimal)
|
|
301
327
|
After=network-online.target
|
|
302
328
|
Wants=network-online.target
|
|
303
329
|
|
|
@@ -308,9 +334,7 @@ EnvironmentFile=/etc/default/ytp-dl-api
|
|
|
308
334
|
Environment=VIRTUAL_ENV=${VENV_DIR}
|
|
309
335
|
Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
|
310
336
|
|
|
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
|
|
337
|
+
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1 --worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 --bind 0.0.0.0:${PORT} scripts.api:app
|
|
314
338
|
|
|
315
339
|
Restart=always
|
|
316
340
|
RestartSec=3
|
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
# ytp-dl
|
|
2
2
|
|
|
3
|
-
> A lightweight YouTube downloader with
|
|
3
|
+
> A lightweight YouTube downloader with Mullvad VPN integration and HTTP API
|
|
4
4
|
|
|
5
5
|
[](https://pypi.org/project/ytp-dl/)
|
|
6
6
|
[](https://pypi.org/project/ytp-dl/)
|
|
7
7
|
[](https://pypi.org/project/ytp-dl/)
|
|
8
8
|
[](https://pypi.org/project/ytp-dl/)
|
|
9
9
|
|
|
10
|
-
**ytp-dl** is a privacy-focused YouTube downloader that
|
|
10
|
+
**ytp-dl** is a privacy-focused YouTube downloader that automatically routes downloads through Mullvad VPN via an HTTP API.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
## Features
|
|
14
|
+
## ✨ Features
|
|
15
15
|
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* 🔒 **Privacy First** — Automatically connects/disconnects Mullvad VPN per download
|
|
17
|
+
* 🎥 **Smart Quality Selection** — Prefers 1080p H.264 + AAC (no transcoding needed)
|
|
18
|
+
* 🎵 **Audio Downloads** — Extract audio as MP3
|
|
19
|
+
* 🚀 **HTTP API** — Simple Flask-based API with concurrency controls
|
|
20
|
+
* ⚡ **VPS Ready** — Includes automated installer script for Ubuntu
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
23
|
-
## Installation
|
|
24
|
+
## 📦 Installation
|
|
24
25
|
|
|
25
26
|
```bash
|
|
26
|
-
pip install ytp-dl==0.6.
|
|
27
|
+
pip install ytp-dl==0.6.3 yt-dlp[default]
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
**Requirements:**
|
|
30
31
|
|
|
31
32
|
* Linux operating system (tested on Ubuntu 24.04/25.04)
|
|
33
|
+
* [Mullvad CLI](https://mullvad.net/en/download/vpn/linux) installed and configured
|
|
32
34
|
* FFmpeg (for handling audio + video)
|
|
33
35
|
* Deno (system-wide, required by yt-dlp for modern YouTube extraction)
|
|
34
36
|
* Python 3.8+
|
|
@@ -39,7 +41,7 @@ Notes:
|
|
|
39
41
|
|
|
40
42
|
---
|
|
41
43
|
|
|
42
|
-
## Using Your VPS
|
|
44
|
+
## 🎯 Using Your VPS
|
|
43
45
|
|
|
44
46
|
Once your VPS is running, you can download videos using simple HTTP requests:
|
|
45
47
|
|
|
@@ -104,26 +106,34 @@ else:
|
|
|
104
106
|
|
|
105
107
|
---
|
|
106
108
|
|
|
107
|
-
## Configuration
|
|
109
|
+
## ⚙️ Configuration
|
|
108
110
|
|
|
109
111
|
### Installation Script Variables
|
|
110
112
|
|
|
111
113
|
These environment variables configure the VPS installation (they can be overridden when running the script):
|
|
112
114
|
|
|
113
|
-
| Variable
|
|
114
|
-
|
|
|
115
|
-
| `PORT`
|
|
116
|
-
| `APP_DIR`
|
|
117
|
-
| `
|
|
115
|
+
| Variable | Description | Default |
|
|
116
|
+
| ------------------------ | --------------------------------------- | --------------------- |
|
|
117
|
+
| `PORT` | API server port | `5000` |
|
|
118
|
+
| `APP_DIR` | Installation directory | `/opt/yt-dlp-mullvad` |
|
|
119
|
+
| `MV_ACCOUNT` | Mullvad account number | your mullvad id |
|
|
120
|
+
| `YTPDL_MAX_CONCURRENT` | Max simultaneous downloads (API cap) | `1` |
|
|
121
|
+
| `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code (e.g. `us`) | `us` |
|
|
122
|
+
|
|
123
|
+
Notes:
|
|
124
|
+
|
|
125
|
+
* If `MV_ACCOUNT` is set, the installer attempts `mullvad account login <MV_ACCOUNT>` once.
|
|
126
|
+
* If `MV_ACCOUNT` is left empty, the script skips login and assumes Mullvad is already configured.
|
|
118
127
|
|
|
119
128
|
### Runtime Environment Variables
|
|
120
129
|
|
|
121
130
|
After installation, these variables control the API behavior. They are set in `/etc/default/ytp-dl-api` and can be edited manually:
|
|
122
131
|
|
|
123
|
-
| Variable
|
|
124
|
-
|
|
|
125
|
-
| `YTPDL_MAX_CONCURRENT`
|
|
126
|
-
| `
|
|
132
|
+
| Variable | Description | Default |
|
|
133
|
+
| ------------------------ | ----------------------------- | -------------------------- |
|
|
134
|
+
| `YTPDL_MAX_CONCURRENT` | Maximum concurrent downloads | `1` |
|
|
135
|
+
| `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code | `us` |
|
|
136
|
+
| `YTPDL_VENV` | Path to virtualenv for ytp-dl | `/opt/yt-dlp-mullvad/venv` |
|
|
127
137
|
|
|
128
138
|
To change configuration after installation:
|
|
129
139
|
|
|
@@ -134,7 +144,7 @@ sudo systemctl restart ytp-dl-api
|
|
|
134
144
|
|
|
135
145
|
---
|
|
136
146
|
|
|
137
|
-
## Managing Your VPS Service
|
|
147
|
+
## 🔧 Managing Your VPS Service
|
|
138
148
|
|
|
139
149
|
### View Service Status
|
|
140
150
|
|
|
@@ -163,7 +173,7 @@ sudo systemctl start ytp-dl-api
|
|
|
163
173
|
|
|
164
174
|
---
|
|
165
175
|
|
|
166
|
-
## API Reference
|
|
176
|
+
## 📋 API Reference
|
|
167
177
|
|
|
168
178
|
### POST `/api/download`
|
|
169
179
|
|
|
@@ -198,45 +208,60 @@ sudo systemctl start ytp-dl-api
|
|
|
198
208
|
|
|
199
209
|
---
|
|
200
210
|
|
|
201
|
-
## VPS Deployment
|
|
211
|
+
## 🖥️ VPS Deployment
|
|
202
212
|
|
|
203
213
|
**What it does:**
|
|
204
214
|
|
|
205
|
-
* Installs Python and
|
|
206
|
-
* Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
207
|
-
* Creates
|
|
208
|
-
* Installs `ytp-dl==0.6.
|
|
209
|
-
* Sets up
|
|
210
|
-
* Configures Gunicorn with gevent workers
|
|
215
|
+
* ✅ Installs Python, FFmpeg, and Mullvad CLI
|
|
216
|
+
* ✅ Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
217
|
+
* ✅ Creates virtualenv at `/opt/yt-dlp-mullvad/venv`
|
|
218
|
+
* ✅ Installs `ytp-dl==0.6.3` + `yt-dlp[default]` into the virtualenv
|
|
219
|
+
* ✅ Sets up systemd service on port 5000
|
|
220
|
+
* ✅ Configures Gunicorn with gevent workers
|
|
211
221
|
|
|
212
222
|
```bash
|
|
213
223
|
#!/usr/bin/env bash
|
|
214
|
-
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API
|
|
224
|
+
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API + Mullvad
|
|
215
225
|
#
|
|
216
226
|
# What this does:
|
|
217
|
-
# - Installs Python
|
|
227
|
+
# - Installs Python, ffmpeg, Mullvad CLI
|
|
218
228
|
# - Installs Deno system-wide (JS runtime required for modern YouTube extraction via yt-dlp)
|
|
219
|
-
# - Creates a virtualenv at /opt/
|
|
220
|
-
# - Installs ytp-dl==0.6.
|
|
229
|
+
# - Creates a virtualenv at /opt/yt-dlp-mullvad/venv
|
|
230
|
+
# - Installs ytp-dl==0.6.3 + yt-dlp[default] + gunicorn + gevent in that venv
|
|
221
231
|
# - Creates a simple systemd service ytp-dl-api.service on port 5000
|
|
232
|
+
#
|
|
233
|
+
# Mullvad connect/disconnect is handled per-job by downloader.py.
|
|
222
234
|
|
|
223
235
|
set -euo pipefail
|
|
224
236
|
|
|
225
237
|
### --- Tunables -------------------------------------------------------------
|
|
226
|
-
PORT="${PORT:-5000}"
|
|
227
|
-
APP_DIR="${APP_DIR:-/opt/
|
|
228
|
-
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}"
|
|
238
|
+
PORT="${PORT:-5000}" # API listen port
|
|
239
|
+
APP_DIR="${APP_DIR:-/opt/yt-dlp-mullvad}" # app/venv root
|
|
240
|
+
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}" # python venv
|
|
229
241
|
|
|
230
|
-
|
|
242
|
+
MV_ACCOUNT="${MV_ACCOUNT:-}" # Mullvad account (put number after -)
|
|
243
|
+
YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
|
|
244
|
+
YTPDL_MULLVAD_LOCATION="${YTPDL_MULLVAD_LOCATION:-us}" # default Mullvad relay hint
|
|
231
245
|
### -------------------------------------------------------------------------
|
|
232
246
|
|
|
233
247
|
[[ "${EUID}" -eq 0 ]] || { echo "Please run as root"; exit 1; }
|
|
234
248
|
export DEBIAN_FRONTEND=noninteractive
|
|
235
249
|
|
|
236
|
-
echo "==> 1) Base packages"
|
|
250
|
+
echo "==> 1) Base packages & Mullvad CLI"
|
|
237
251
|
apt-get update
|
|
238
|
-
apt-get install -yq --no-install-recommends
|
|
239
|
-
|
|
252
|
+
apt-get install -yq --no-install-recommends python3-venv python3-pip curl ffmpeg ca-certificates unzip
|
|
253
|
+
|
|
254
|
+
if ! command -v mullvad >/dev/null 2>&1; then
|
|
255
|
+
curl -fsSLo /tmp/mullvad.deb https://mullvad.net/download/app/deb/latest/
|
|
256
|
+
apt-get install -y /tmp/mullvad.deb
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
if [[ -n "${MV_ACCOUNT}" ]]; then
|
|
260
|
+
echo "Logging into Mullvad account (if not already logged in)..."
|
|
261
|
+
mullvad account login "${MV_ACCOUNT}" || true
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
mullvad status || true
|
|
240
265
|
|
|
241
266
|
echo "==> 1.5) Install Deno (system-wide, for yt-dlp YouTube extraction)"
|
|
242
267
|
# Install into /usr/local/bin/deno so systemd PATH can see it.
|
|
@@ -251,19 +276,20 @@ mkdir -p "${APP_DIR}"
|
|
|
251
276
|
python3 -m venv "${VENV_DIR}"
|
|
252
277
|
source "${VENV_DIR}/bin/activate"
|
|
253
278
|
pip install --upgrade pip
|
|
254
|
-
pip install "ytp-dl==0.6.
|
|
279
|
+
pip install "ytp-dl==0.6.3" "yt-dlp[default]" gunicorn gevent
|
|
255
280
|
deactivate
|
|
256
281
|
|
|
257
282
|
echo "==> 3) API environment file (/etc/default/ytp-dl-api)"
|
|
258
283
|
tee /etc/default/ytp-dl-api >/dev/null <<EOF
|
|
259
284
|
YTPDL_MAX_CONCURRENT=${YTPDL_MAX_CONCURRENT}
|
|
285
|
+
YTPDL_MULLVAD_LOCATION=${YTPDL_MULLVAD_LOCATION}
|
|
260
286
|
YTPDL_VENV=${VENV_DIR}
|
|
261
287
|
EOF
|
|
262
288
|
|
|
263
289
|
echo "==> 4) Gunicorn systemd service (ytp-dl-api.service on :${PORT})"
|
|
264
290
|
tee /etc/systemd/system/ytp-dl-api.service >/dev/null <<EOF
|
|
265
291
|
[Unit]
|
|
266
|
-
Description=Gunicorn for ytp-dl API (minimal)
|
|
292
|
+
Description=Gunicorn for ytp-dl Mullvad API (minimal)
|
|
267
293
|
After=network-online.target
|
|
268
294
|
Wants=network-online.target
|
|
269
295
|
|
|
@@ -274,9 +300,7 @@ EnvironmentFile=/etc/default/ytp-dl-api
|
|
|
274
300
|
Environment=VIRTUAL_ENV=${VENV_DIR}
|
|
275
301
|
Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
|
276
302
|
|
|
277
|
-
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1
|
|
278
|
-
--worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 \
|
|
279
|
-
--bind 0.0.0.0:${PORT} scripts.api:app
|
|
303
|
+
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1 --worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 --bind 0.0.0.0:${PORT} scripts.api:app
|
|
280
304
|
|
|
281
305
|
Restart=always
|
|
282
306
|
RestartSec=3
|
|
@@ -306,4 +330,4 @@ echo "Installation complete!"
|
|
|
306
330
|
echo "API running on port ${PORT}"
|
|
307
331
|
echo "Test from outside: curl http://YOUR_VPS_IP:${PORT}/healthz"
|
|
308
332
|
echo "========================================="
|
|
309
|
-
```
|
|
333
|
+
```
|
|
@@ -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)
|
|
23
24
|
STALE_JOB_TTL_S = int(os.environ.get("YTPDL_STALE_JOB_TTL_S", "3600"))
|
|
24
25
|
|
|
25
|
-
# extension is now a "mode": mp3 | mp4 | best
|
|
26
26
|
_ALLOWED_EXTENSIONS = {"mp3", "mp4", "best"}
|
|
27
27
|
|
|
28
28
|
|
|
@@ -63,6 +63,8 @@ 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
|
|
66
68
|
extension = (data.get("extension") or "mp4").strip().lower()
|
|
67
69
|
|
|
68
70
|
if not url:
|
|
@@ -89,6 +91,7 @@ def handle_download():
|
|
|
89
91
|
raise RuntimeError("Download failed")
|
|
90
92
|
|
|
91
93
|
# Release semaphore as soon as yt-dlp is done.
|
|
94
|
+
# Streaming the file should not block the next download job.
|
|
92
95
|
_release_once()
|
|
93
96
|
|
|
94
97
|
response = send_file(filename, as_attachment=True)
|
|
@@ -108,7 +111,11 @@ def handle_download():
|
|
|
108
111
|
if job_dir:
|
|
109
112
|
shutil.rmtree(job_dir, ignore_errors=True)
|
|
110
113
|
_release_once()
|
|
111
|
-
|
|
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
|
|
112
119
|
|
|
113
120
|
except Exception as e:
|
|
114
121
|
if job_dir:
|
|
@@ -5,13 +5,15 @@ import os
|
|
|
5
5
|
import shlex
|
|
6
6
|
import shutil
|
|
7
7
|
import subprocess
|
|
8
|
+
import time
|
|
8
9
|
from typing import Optional, List, Tuple
|
|
9
10
|
|
|
10
11
|
# =========================
|
|
11
12
|
# Config / constants
|
|
12
13
|
# =========================
|
|
13
|
-
VENV_PATH = os.environ.get("YTPDL_VENV", "/opt/
|
|
14
|
+
VENV_PATH = os.environ.get("YTPDL_VENV", "/opt/yt-dlp-mullvad/venv")
|
|
14
15
|
YTDLP_BIN = os.path.join(VENV_PATH, "bin", "yt-dlp")
|
|
16
|
+
MULLVAD_LOCATION = os.environ.get("YTPDL_MULLVAD_LOCATION", "us")
|
|
15
17
|
|
|
16
18
|
MODERN_UA = os.environ.get(
|
|
17
19
|
"YTPDL_USER_AGENT",
|
|
@@ -20,11 +22,6 @@ MODERN_UA = os.environ.get(
|
|
|
20
22
|
"Chrome/124.0.0.0 Safari/537.36",
|
|
21
23
|
)
|
|
22
24
|
|
|
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
|
-
|
|
28
25
|
FFMPEG_BIN = shutil.which("ffmpeg") or "ffmpeg"
|
|
29
26
|
DEFAULT_OUT_DIR = os.environ.get("YTPDL_DOWNLOAD_DIR", "/root")
|
|
30
27
|
|
|
@@ -63,8 +60,13 @@ def _tail(out: str) -> str:
|
|
|
63
60
|
return txt.strip()
|
|
64
61
|
|
|
65
62
|
|
|
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
|
+
|
|
66
68
|
# =========================
|
|
67
|
-
# Environment
|
|
69
|
+
# Environment / Mullvad
|
|
68
70
|
# =========================
|
|
69
71
|
def validate_environment() -> None:
|
|
70
72
|
if not os.path.exists(YTDLP_BIN):
|
|
@@ -73,12 +75,59 @@ def validate_environment() -> None:
|
|
|
73
75
|
raise RuntimeError("ffmpeg not found on PATH")
|
|
74
76
|
|
|
75
77
|
|
|
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
|
+
|
|
76
125
|
# =========================
|
|
77
126
|
# yt-dlp helpers
|
|
78
127
|
# =========================
|
|
79
128
|
def _common_flags() -> List[str]:
|
|
80
129
|
# --no-playlist prevents accidental channel/playlist pulls (and disk blowups)
|
|
81
|
-
|
|
130
|
+
return [
|
|
82
131
|
"--no-playlist",
|
|
83
132
|
"--retries", "10",
|
|
84
133
|
"--fragment-retries", "10",
|
|
@@ -90,13 +139,6 @@ def _common_flags() -> List[str]:
|
|
|
90
139
|
"--sleep-interval", "1",
|
|
91
140
|
]
|
|
92
141
|
|
|
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
|
-
|
|
100
142
|
|
|
101
143
|
def _extract_final_path(stdout: str, out_dir: str) -> Optional[str]:
|
|
102
144
|
"""
|
|
@@ -215,6 +257,7 @@ def _download_with_format(
|
|
|
215
257
|
]
|
|
216
258
|
|
|
217
259
|
if extract_mp3:
|
|
260
|
+
# Force audio extraction to MP3 (requires ffmpeg)
|
|
218
261
|
argv.extend(["--extract-audio", "--audio-format", "mp3"])
|
|
219
262
|
|
|
220
263
|
# Only force merge container when we actually want MP4 output.
|
|
@@ -266,44 +309,55 @@ def download_video(
|
|
|
266
309
|
|
|
267
310
|
validate_environment()
|
|
268
311
|
|
|
269
|
-
|
|
312
|
+
require_mullvad_login()
|
|
313
|
+
mullvad_connect(MULLVAD_LOCATION)
|
|
314
|
+
if not mullvad_wait_connected():
|
|
315
|
+
raise RuntimeError("Mullvad connection failed")
|
|
270
316
|
|
|
271
|
-
|
|
272
|
-
|
|
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)
|
|
317
|
+
try:
|
|
318
|
+
mode = (extension or "mp4").lower().strip()
|
|
281
319
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
try:
|
|
320
|
+
if mode == "mp3":
|
|
321
|
+
# bestaudio -> ffmpeg -> mp3 (post-processed by yt-dlp)
|
|
285
322
|
return _download_with_format(
|
|
286
323
|
url=url,
|
|
287
324
|
out_dir=out_dir,
|
|
288
|
-
fmt=
|
|
325
|
+
fmt="bestaudio",
|
|
289
326
|
merge_output_format=None,
|
|
290
|
-
extract_mp3=
|
|
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,
|
|
327
|
+
extract_mp3=True,
|
|
300
328
|
)
|
|
301
329
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
330
|
+
cap = int(resolution or 1080)
|
|
331
|
+
|
|
332
|
+
if mode == "best":
|
|
333
|
+
# Try best first (may produce webm/mkv/etc).
|
|
334
|
+
try:
|
|
335
|
+
return _download_with_format(
|
|
336
|
+
url=url,
|
|
337
|
+
out_dir=out_dir,
|
|
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)
|
|
@@ -8,7 +8,7 @@ with open("requirements.txt", "r", encoding="utf-8") as fh:
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="ytp-dl",
|
|
11
|
-
version="0.6.
|
|
11
|
+
version="0.6.3",
|
|
12
12
|
author="dumgum82",
|
|
13
13
|
author_email="dumgum42@gmail.com",
|
|
14
14
|
description="YouTube video downloader with Mullvad VPN integration and Flask API",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: ytp-dl
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
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,35 +34,37 @@ Dynamic: summary
|
|
|
34
34
|
|
|
35
35
|
# ytp-dl
|
|
36
36
|
|
|
37
|
-
> A lightweight YouTube downloader with
|
|
37
|
+
> A lightweight YouTube downloader with Mullvad VPN integration and 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 automatically routes downloads through Mullvad VPN via an HTTP API.
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
## Features
|
|
48
|
+
## ✨ Features
|
|
49
49
|
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* 🔒 **Privacy First** — Automatically connects/disconnects Mullvad VPN per download
|
|
51
|
+
* 🎥 **Smart Quality Selection** — Prefers 1080p H.264 + AAC (no transcoding needed)
|
|
52
|
+
* 🎵 **Audio Downloads** — Extract audio as MP3
|
|
53
|
+
* 🚀 **HTTP API** — Simple Flask-based API with concurrency controls
|
|
54
|
+
* ⚡ **VPS Ready** — Includes automated installer script for Ubuntu
|
|
54
55
|
|
|
55
56
|
---
|
|
56
57
|
|
|
57
|
-
## Installation
|
|
58
|
+
## 📦 Installation
|
|
58
59
|
|
|
59
60
|
```bash
|
|
60
|
-
pip install ytp-dl==0.6.
|
|
61
|
+
pip install ytp-dl==0.6.3 yt-dlp[default]
|
|
61
62
|
```
|
|
62
63
|
|
|
63
64
|
**Requirements:**
|
|
64
65
|
|
|
65
66
|
* Linux operating system (tested on Ubuntu 24.04/25.04)
|
|
67
|
+
* [Mullvad CLI](https://mullvad.net/en/download/vpn/linux) installed and configured
|
|
66
68
|
* FFmpeg (for handling audio + video)
|
|
67
69
|
* Deno (system-wide, required by yt-dlp for modern YouTube extraction)
|
|
68
70
|
* Python 3.8+
|
|
@@ -73,7 +75,7 @@ Notes:
|
|
|
73
75
|
|
|
74
76
|
---
|
|
75
77
|
|
|
76
|
-
## Using Your VPS
|
|
78
|
+
## 🎯 Using Your VPS
|
|
77
79
|
|
|
78
80
|
Once your VPS is running, you can download videos using simple HTTP requests:
|
|
79
81
|
|
|
@@ -138,26 +140,34 @@ else:
|
|
|
138
140
|
|
|
139
141
|
---
|
|
140
142
|
|
|
141
|
-
## Configuration
|
|
143
|
+
## ⚙️ Configuration
|
|
142
144
|
|
|
143
145
|
### Installation Script Variables
|
|
144
146
|
|
|
145
147
|
These environment variables configure the VPS installation (they can be overridden when running the script):
|
|
146
148
|
|
|
147
|
-
| Variable
|
|
148
|
-
|
|
|
149
|
-
| `PORT`
|
|
150
|
-
| `APP_DIR`
|
|
151
|
-
| `
|
|
149
|
+
| Variable | Description | Default |
|
|
150
|
+
| ------------------------ | --------------------------------------- | --------------------- |
|
|
151
|
+
| `PORT` | API server port | `5000` |
|
|
152
|
+
| `APP_DIR` | Installation directory | `/opt/yt-dlp-mullvad` |
|
|
153
|
+
| `MV_ACCOUNT` | Mullvad account number | your mullvad id |
|
|
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.
|
|
152
161
|
|
|
153
162
|
### Runtime Environment Variables
|
|
154
163
|
|
|
155
164
|
After installation, these variables control the API behavior. They are set in `/etc/default/ytp-dl-api` and can be edited manually:
|
|
156
165
|
|
|
157
|
-
| Variable
|
|
158
|
-
|
|
|
159
|
-
| `YTPDL_MAX_CONCURRENT`
|
|
160
|
-
| `
|
|
166
|
+
| Variable | Description | Default |
|
|
167
|
+
| ------------------------ | ----------------------------- | -------------------------- |
|
|
168
|
+
| `YTPDL_MAX_CONCURRENT` | Maximum concurrent downloads | `1` |
|
|
169
|
+
| `YTPDL_MULLVAD_LOCATION` | Mullvad relay location code | `us` |
|
|
170
|
+
| `YTPDL_VENV` | Path to virtualenv for ytp-dl | `/opt/yt-dlp-mullvad/venv` |
|
|
161
171
|
|
|
162
172
|
To change configuration after installation:
|
|
163
173
|
|
|
@@ -168,7 +178,7 @@ sudo systemctl restart ytp-dl-api
|
|
|
168
178
|
|
|
169
179
|
---
|
|
170
180
|
|
|
171
|
-
## Managing Your VPS Service
|
|
181
|
+
## 🔧 Managing Your VPS Service
|
|
172
182
|
|
|
173
183
|
### View Service Status
|
|
174
184
|
|
|
@@ -197,7 +207,7 @@ sudo systemctl start ytp-dl-api
|
|
|
197
207
|
|
|
198
208
|
---
|
|
199
209
|
|
|
200
|
-
## API Reference
|
|
210
|
+
## 📋 API Reference
|
|
201
211
|
|
|
202
212
|
### POST `/api/download`
|
|
203
213
|
|
|
@@ -232,45 +242,60 @@ sudo systemctl start ytp-dl-api
|
|
|
232
242
|
|
|
233
243
|
---
|
|
234
244
|
|
|
235
|
-
## VPS Deployment
|
|
245
|
+
## 🖥️ VPS Deployment
|
|
236
246
|
|
|
237
247
|
**What it does:**
|
|
238
248
|
|
|
239
|
-
* Installs Python and
|
|
240
|
-
* Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
241
|
-
* Creates
|
|
242
|
-
* Installs `ytp-dl==0.6.
|
|
243
|
-
* Sets up
|
|
244
|
-
* Configures Gunicorn with gevent workers
|
|
249
|
+
* ✅ Installs Python, FFmpeg, and Mullvad CLI
|
|
250
|
+
* ✅ Installs Deno system-wide (required by yt-dlp for modern YouTube extraction)
|
|
251
|
+
* ✅ Creates virtualenv at `/opt/yt-dlp-mullvad/venv`
|
|
252
|
+
* ✅ Installs `ytp-dl==0.6.3` + `yt-dlp[default]` into the virtualenv
|
|
253
|
+
* ✅ Sets up systemd service on port 5000
|
|
254
|
+
* ✅ Configures Gunicorn with gevent workers
|
|
245
255
|
|
|
246
256
|
```bash
|
|
247
257
|
#!/usr/bin/env bash
|
|
248
|
-
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API
|
|
258
|
+
# VPS_Installation.sh - Minimal Ubuntu 24.04/25.04 setup for ytp-dl API + Mullvad
|
|
249
259
|
#
|
|
250
260
|
# What this does:
|
|
251
|
-
# - Installs Python
|
|
261
|
+
# - Installs Python, ffmpeg, Mullvad CLI
|
|
252
262
|
# - Installs Deno system-wide (JS runtime required for modern YouTube extraction via yt-dlp)
|
|
253
|
-
# - Creates a virtualenv at /opt/
|
|
254
|
-
# - Installs ytp-dl==0.6.
|
|
263
|
+
# - Creates a virtualenv at /opt/yt-dlp-mullvad/venv
|
|
264
|
+
# - Installs ytp-dl==0.6.3 + yt-dlp[default] + gunicorn + gevent in that venv
|
|
255
265
|
# - Creates a simple systemd service ytp-dl-api.service on port 5000
|
|
266
|
+
#
|
|
267
|
+
# Mullvad connect/disconnect is handled per-job by downloader.py.
|
|
256
268
|
|
|
257
269
|
set -euo pipefail
|
|
258
270
|
|
|
259
271
|
### --- Tunables -------------------------------------------------------------
|
|
260
|
-
PORT="${PORT:-5000}"
|
|
261
|
-
APP_DIR="${APP_DIR:-/opt/
|
|
262
|
-
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}"
|
|
272
|
+
PORT="${PORT:-5000}" # API listen port
|
|
273
|
+
APP_DIR="${APP_DIR:-/opt/yt-dlp-mullvad}" # app/venv root
|
|
274
|
+
VENV_DIR="${VENV_DIR:-${APP_DIR}/venv}" # python venv
|
|
263
275
|
|
|
264
|
-
|
|
276
|
+
MV_ACCOUNT="${MV_ACCOUNT:-}" # Mullvad account (put number after -)
|
|
277
|
+
YTPDL_MAX_CONCURRENT="${YTPDL_MAX_CONCURRENT:-1}" # API concurrency cap
|
|
278
|
+
YTPDL_MULLVAD_LOCATION="${YTPDL_MULLVAD_LOCATION:-us}" # default Mullvad relay hint
|
|
265
279
|
### -------------------------------------------------------------------------
|
|
266
280
|
|
|
267
281
|
[[ "${EUID}" -eq 0 ]] || { echo "Please run as root"; exit 1; }
|
|
268
282
|
export DEBIAN_FRONTEND=noninteractive
|
|
269
283
|
|
|
270
|
-
echo "==> 1) Base packages"
|
|
284
|
+
echo "==> 1) Base packages & Mullvad CLI"
|
|
271
285
|
apt-get update
|
|
272
|
-
apt-get install -yq --no-install-recommends
|
|
273
|
-
|
|
286
|
+
apt-get install -yq --no-install-recommends python3-venv python3-pip curl ffmpeg ca-certificates unzip
|
|
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
|
|
274
299
|
|
|
275
300
|
echo "==> 1.5) Install Deno (system-wide, for yt-dlp YouTube extraction)"
|
|
276
301
|
# Install into /usr/local/bin/deno so systemd PATH can see it.
|
|
@@ -285,19 +310,20 @@ mkdir -p "${APP_DIR}"
|
|
|
285
310
|
python3 -m venv "${VENV_DIR}"
|
|
286
311
|
source "${VENV_DIR}/bin/activate"
|
|
287
312
|
pip install --upgrade pip
|
|
288
|
-
pip install "ytp-dl==0.6.
|
|
313
|
+
pip install "ytp-dl==0.6.3" "yt-dlp[default]" gunicorn gevent
|
|
289
314
|
deactivate
|
|
290
315
|
|
|
291
316
|
echo "==> 3) API environment file (/etc/default/ytp-dl-api)"
|
|
292
317
|
tee /etc/default/ytp-dl-api >/dev/null <<EOF
|
|
293
318
|
YTPDL_MAX_CONCURRENT=${YTPDL_MAX_CONCURRENT}
|
|
319
|
+
YTPDL_MULLVAD_LOCATION=${YTPDL_MULLVAD_LOCATION}
|
|
294
320
|
YTPDL_VENV=${VENV_DIR}
|
|
295
321
|
EOF
|
|
296
322
|
|
|
297
323
|
echo "==> 4) Gunicorn systemd service (ytp-dl-api.service on :${PORT})"
|
|
298
324
|
tee /etc/systemd/system/ytp-dl-api.service >/dev/null <<EOF
|
|
299
325
|
[Unit]
|
|
300
|
-
Description=Gunicorn for ytp-dl API (minimal)
|
|
326
|
+
Description=Gunicorn for ytp-dl Mullvad API (minimal)
|
|
301
327
|
After=network-online.target
|
|
302
328
|
Wants=network-online.target
|
|
303
329
|
|
|
@@ -308,9 +334,7 @@ EnvironmentFile=/etc/default/ytp-dl-api
|
|
|
308
334
|
Environment=VIRTUAL_ENV=${VENV_DIR}
|
|
309
335
|
Environment=PATH=${VENV_DIR}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
|
310
336
|
|
|
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
|
|
337
|
+
ExecStart=${VENV_DIR}/bin/gunicorn -k gevent -w 1 --worker-connections 200 --timeout 0 --graceful-timeout 15 --keep-alive 20 --bind 0.0.0.0:${PORT} scripts.api:app
|
|
314
338
|
|
|
315
339
|
Restart=always
|
|
316
340
|
RestartSec=3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|