feat: bundle yt-dlp and ffmpeg Linux binaries in bin/
Adds precompiled Linux x86_64 binaries for yt-dlp and ffmpeg under bin/. The processor resolves yt-dlp from bin/ when present, falling back to PATH. ffmpeg is passed via --ffmpeg-location so yt-dlp uses the bundled binary on o2switch. BIN_DIR is configurable via env var. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
import path from 'path'
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
DOWNLOAD_LINK_TTL_HOURS: 24,
|
DOWNLOAD_LINK_TTL_HOURS: 24,
|
||||||
WORKER_CONCURRENCY: 3,
|
WORKER_CONCURRENCY: 3,
|
||||||
@@ -5,4 +7,5 @@ export const config = {
|
|||||||
STORAGE_PATH: process.env.STORAGE_PATH ?? '',
|
STORAGE_PATH: process.env.STORAGE_PATH ?? '',
|
||||||
RATE_LIMIT_MAX: 5,
|
RATE_LIMIT_MAX: 5,
|
||||||
RATE_LIMIT_WINDOW_MS: 3_600_000,
|
RATE_LIMIT_WINDOW_MS: 3_600_000,
|
||||||
|
BIN_DIR: process.env.BIN_DIR ?? path.join(process.cwd(), 'bin'),
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { existsSync } from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { config } from '../../config/app.config'
|
import { config } from '../../config/app.config'
|
||||||
|
|
||||||
@@ -16,6 +17,11 @@ export function buildYtdlpArgs(params: YtdlpParams): string[] {
|
|||||||
|
|
||||||
const args: string[] = ['--no-playlist', '-o', outputTemplate]
|
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') {
|
if (quality !== 'best') {
|
||||||
const height = quality.replace('p', '')
|
const height = quality.replace('p', '')
|
||||||
args.push('-f', `${format}[height<=?${height}]+bestaudio/best[height<=?${height}]`)
|
args.push('-f', `${format}[height<=?${height}]+bestaudio/best[height<=?${height}]`)
|
||||||
|
|||||||
+7
-2
@@ -1,11 +1,16 @@
|
|||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { readdirSync, statSync } from 'fs'
|
import { existsSync, readdirSync, statSync } from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { prisma } from '@/lib/prisma'
|
import { prisma } from '@/lib/prisma'
|
||||||
import { buildYtdlpArgs } from '@/lib/ytdlp'
|
import { buildYtdlpArgs } from '@/lib/ytdlp'
|
||||||
import { createToken } from '@/lib/token'
|
import { createToken } from '@/lib/token'
|
||||||
import { config } from '../config/app.config'
|
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<void> {
|
export async function processDownload(downloadId: string): Promise<void> {
|
||||||
const download = await prisma.download.findUnique({ where: { id: downloadId } })
|
const download = await prisma.download.findUnique({ where: { id: downloadId } })
|
||||||
if (!download) return
|
if (!download) return
|
||||||
@@ -22,7 +27,7 @@ export async function processDownload(downloadId: string): Promise<void> {
|
|||||||
let stderr = ''
|
let stderr = ''
|
||||||
|
|
||||||
await new Promise<void>((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
const proc = spawn('yt-dlp', args)
|
const proc = spawn(resolveYtdlpBin(), args)
|
||||||
proc.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() })
|
proc.stderr.on('data', (chunk: Buffer) => { stderr += chunk.toString() })
|
||||||
|
|
||||||
proc.on('close', async (code) => {
|
proc.on('close', async (code) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user