Enhance Dockerfile and API for yt-dlp integration
- Install Deno as a JavaScript runtime for yt-dlp in the Dockerfile. - Add configuration for yt-dlp to support cookies and JavaScript runtime selection. - Update API to handle cookies for YouTube bot detection and allow specifying the JavaScript runtime. - Introduce new environment variables for cookie management and JavaScript runtime configuration in README.
This commit is contained in:
14
Dockerfile
14
Dockerfile
@@ -3,15 +3,25 @@ FROM node:20-alpine
|
||||
# Set default locale to German
|
||||
ENV LOCALE=de
|
||||
|
||||
# yt-dlp und ffmpeg installieren
|
||||
# yt-dlp, ffmpeg und deno (JavaScript Runtime für YouTube) installieren
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
py3-pip \
|
||||
ffmpeg \
|
||||
&& pip3 install --no-cache-dir --break-system-packages yt-dlp
|
||||
curl \
|
||||
unzip \
|
||||
&& pip3 install --no-cache-dir --break-system-packages yt-dlp \
|
||||
&& curl -fsSL https://deno.land/install.sh | sh \
|
||||
&& mv /root/.deno/bin/deno /usr/local/bin/deno \
|
||||
&& chmod +x /usr/local/bin/deno
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# yt-dlp Konfiguration erstellen (für deno als JS-Runtime)
|
||||
RUN mkdir -p /root/.config/yt-dlp && \
|
||||
echo "--js-runtimes deno" > /root/.config/yt-dlp/config && \
|
||||
echo "--no-warnings" >> /root/.config/yt-dlp/config
|
||||
|
||||
# Package-Dateien kopieren und Dependencies installieren
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
|
||||
11
README.md
11
README.md
@@ -101,6 +101,9 @@ Siehe [BUILD-MACOS.md](./BUILD-MACOS.md) für detaillierte Anleitung.
|
||||
- `SESSION_SECRET`: Secret für Session-Cookies (Standard: `default-secret-change-in-production`)
|
||||
- `STREAM_ONLY`: Wenn auf `true` gesetzt, werden Dateien nicht physisch gespeichert, sondern direkt als Download-Stream angeboten (Standard: `false`)
|
||||
- `LOCALE`: Sprache der Anwendung - `de` für Deutsch oder `en` für Englisch (Standard: `de`)
|
||||
- `YT_DLP_COOKIES`: Pfad zu einer Cookie-Datei für yt-dlp (z.B. `./cookies.txt`). Wird verwendet, um YouTube Bot-Erkennung zu umgehen. Siehe [yt-dlp Cookie-Dokumentation](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp)
|
||||
- `YT_DLP_COOKIES_FROM_BROWSER`: Browser-Name, aus dem Cookies geladen werden sollen (z.B. `chrome`, `firefox`, `edge`, `safari`). Alternative zu `YT_DLP_COOKIES`. Siehe [yt-dlp Cookie-Dokumentation](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies)
|
||||
- `YT_DLP_JS_RUNTIME`: JavaScript Runtime für yt-dlp (Standard: `deno`). Andere Optionen: `node`, `d8`, etc.
|
||||
|
||||
**Beispiel `.env` Datei mit Login:**
|
||||
```
|
||||
@@ -111,6 +114,7 @@ DOWNLOAD_DIR=./downloaded
|
||||
SESSION_SECRET=mein-geheimes-session-secret
|
||||
STREAM_ONLY=false
|
||||
LOCALE=de
|
||||
YT_DLP_COOKIES_FROM_BROWSER=chrome
|
||||
```
|
||||
|
||||
**Beispiel `.env` Datei ohne Login:**
|
||||
@@ -119,8 +123,15 @@ LOGIN=false
|
||||
DOWNLOAD_DIR=./downloaded
|
||||
STREAM_ONLY=false
|
||||
LOCALE=de
|
||||
YT_DLP_COOKIES_FROM_BROWSER=chrome
|
||||
```
|
||||
|
||||
**Hinweis zu Cookies:**
|
||||
- Wenn YouTube Bot-Erkennung auftritt, müssen Cookies verwendet werden
|
||||
- `YT_DLP_COOKIES_FROM_BROWSER` ist die einfachste Option: Gibt den Browser-Namen an (z.B. `chrome`, `firefox`, `edge`, `safari`)
|
||||
- Alternativ kann `YT_DLP_COOKIES` mit dem Pfad zu einer Cookie-Datei verwendet werden
|
||||
- Cookie-Dateien können mit Browser-Erweiterungen wie "Get cookies.txt LOCALLY" oder "cookies.txt" exportiert werden
|
||||
|
||||
**Hinweis zu `LOGIN`:**
|
||||
- Wenn `LOGIN=false`: Keine Login-Seite, alle Seiten sind öffentlich zugänglich. `LOGIN_USERNAME` und `LOGIN_PASSWORD` werden ignoriert.
|
||||
- Wenn `LOGIN=true` oder nicht gesetzt: Login ist aktiviert. `LOGIN_USERNAME` und `LOGIN_PASSWORD` müssen gesetzt sein.
|
||||
|
||||
@@ -56,8 +56,23 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
// Format aus Request Header (optional, Standard: MP4)
|
||||
const format = request.headers.get("x-format") || "mp4";
|
||||
|
||||
// Cookie-Unterstützung für YouTube Bot-Erkennung
|
||||
const cookiesFile = process.env.YT_DLP_COOKIES;
|
||||
const cookiesFromBrowser = process.env.YT_DLP_COOKIES_FROM_BROWSER;
|
||||
|
||||
// JavaScript Runtime für yt-dlp (Standard: deno)
|
||||
const jsRuntime = process.env.YT_DLP_JS_RUNTIME || "deno";
|
||||
|
||||
// Zuerst Video-Informationen abrufen, um den Dateinamen zu erhalten
|
||||
const videoInfo = await ytDlpWrap.getVideoInfo(url);
|
||||
// getVideoInfo verwendet intern yt-dlp mit --dump-json
|
||||
// Deno wird beim eigentlichen Download verwendet
|
||||
const videoInfoOptions: string[] = [];
|
||||
if (cookiesFile) {
|
||||
videoInfoOptions.push("--cookies", cookiesFile);
|
||||
} else if (cookiesFromBrowser) {
|
||||
videoInfoOptions.push("--cookies-from-browser", cookiesFromBrowser);
|
||||
}
|
||||
const videoInfo = await ytDlpWrap.getVideoInfo(url, videoInfoOptions);
|
||||
const title = videoInfo.title || "Video";
|
||||
|
||||
// Dateiendung bestimmen
|
||||
@@ -72,12 +87,13 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
const filename = `${title}.${ext}`;
|
||||
|
||||
// Format-String für yt-dlp
|
||||
// Für "best": Kein Format-String = yt-dlp wählt automatisch bestes Format und merged
|
||||
const formatString =
|
||||
format === "mp4"
|
||||
? "bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo[ext=mp4]+bestaudio/best[ext=mp4]/best"
|
||||
: format === "audio"
|
||||
? "bestaudio[ext=m4a]/bestaudio[ext=mp3]/bestaudio"
|
||||
: "best";
|
||||
: undefined; // undefined = yt-dlp wählt automatisch bestes Format
|
||||
|
||||
if (streamOnly) {
|
||||
// STREAM-MODUS: Datei temporär speichern, streamen, dann löschen
|
||||
@@ -91,12 +107,24 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
url,
|
||||
"-o",
|
||||
tempFilePath,
|
||||
"-f",
|
||||
formatString,
|
||||
"--no-mtime",
|
||||
"--no-playlist",
|
||||
"--js-runtimes",
|
||||
jsRuntime,
|
||||
];
|
||||
|
||||
// Cookie-Unterstützung hinzufügen
|
||||
if (cookiesFile) {
|
||||
execArgs.push("--cookies", cookiesFile);
|
||||
} else if (cookiesFromBrowser) {
|
||||
execArgs.push("--cookies-from-browser", cookiesFromBrowser);
|
||||
}
|
||||
|
||||
// Format nur hinzufügen wenn definiert
|
||||
if (formatString) {
|
||||
execArgs.push("-f", formatString);
|
||||
}
|
||||
|
||||
if (format === "mp4") {
|
||||
execArgs.push("--merge-output-format", "mp4");
|
||||
} else if (format === "audio") {
|
||||
@@ -184,12 +212,24 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
url,
|
||||
"-o",
|
||||
outputPath,
|
||||
"-f",
|
||||
formatString,
|
||||
"--no-mtime",
|
||||
"--no-playlist",
|
||||
"--js-runtimes",
|
||||
jsRuntime,
|
||||
];
|
||||
|
||||
// Cookie-Unterstützung hinzufügen
|
||||
if (cookiesFile) {
|
||||
execArgs.push("--cookies", cookiesFile);
|
||||
} else if (cookiesFromBrowser) {
|
||||
execArgs.push("--cookies-from-browser", cookiesFromBrowser);
|
||||
}
|
||||
|
||||
// Format nur hinzufügen wenn definiert
|
||||
if (formatString) {
|
||||
execArgs.push("-f", formatString);
|
||||
}
|
||||
|
||||
if (format === "mp4") {
|
||||
execArgs.push("--merge-output-format", "mp4");
|
||||
} else if (format === "audio") {
|
||||
|
||||
Reference in New Issue
Block a user