diff --git a/bin/ffmpeg b/bin/ffmpeg new file mode 100755 index 0000000..a628f08 Binary files /dev/null and b/bin/ffmpeg differ diff --git a/bin/yt-dlp b/bin/yt-dlp new file mode 100755 index 0000000..370f89d Binary files /dev/null and b/bin/yt-dlp differ diff --git a/config/app.config.ts b/config/app.config.ts index 301ba69..e7d665c 100644 --- a/config/app.config.ts +++ b/config/app.config.ts @@ -1,3 +1,5 @@ +import path from 'path' + export const config = { DOWNLOAD_LINK_TTL_HOURS: 24, WORKER_CONCURRENCY: 3, @@ -5,4 +7,5 @@ export const config = { STORAGE_PATH: process.env.STORAGE_PATH ?? '', RATE_LIMIT_MAX: 5, RATE_LIMIT_WINDOW_MS: 3_600_000, + BIN_DIR: process.env.BIN_DIR ?? path.join(process.cwd(), 'bin'), } as const diff --git a/src/lib/ytdlp.ts b/src/lib/ytdlp.ts index ab56be8..d40a5d9 100644 --- a/src/lib/ytdlp.ts +++ b/src/lib/ytdlp.ts @@ -1,3 +1,4 @@ +import { existsSync } from 'fs' import path from 'path' import { config } from '../../config/app.config' @@ -16,6 +17,11 @@ export function buildYtdlpArgs(params: YtdlpParams): string[] { const args: string[] = ['--no-playlist', '-o', outputTemplate] + const ffmpegBin = path.join(config.BIN_DIR, 'ffmpeg') + if (existsSync(ffmpegBin)) { + args.push('--ffmpeg-location', ffmpegBin) + } + if (quality !== 'best') { const height = quality.replace('p', '') args.push('-f', `${format}[height<=?${height}]+bestaudio/best[height<=?${height}]`) diff --git a/worker/processor.ts b/worker/processor.ts index 8d2ad78..27196d4 100644 --- a/worker/processor.ts +++ b/worker/processor.ts @@ -1,11 +1,16 @@ import { spawn } from 'child_process' -import { readdirSync, statSync } from 'fs' +import { existsSync, readdirSync, statSync } from 'fs' import path from 'path' import { prisma } from '@/lib/prisma' import { buildYtdlpArgs } from '@/lib/ytdlp' import { createToken } from '@/lib/token' import { config } from '../config/app.config' +function resolveYtdlpBin(): string { + const local = path.join(config.BIN_DIR, 'yt-dlp') + return existsSync(local) ? local : 'yt-dlp' +} + export async function processDownload(downloadId: string): Promise { const download = await prisma.download.findUnique({ where: { id: downloadId } }) if (!download) return @@ -22,7 +27,7 @@ export async function processDownload(downloadId: string): Promise { let stderr = '' await new Promise((resolve) => { - const proc = spawn('yt-dlp', args) + const proc = spawn(resolveYtdlpBin(), args) proc.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() }) proc.on('close', async (code) => {