import { DOWNLOAD_PATH } from '$env/static/private'; import { redirect } from '@sveltejs/kit'; import ytdl from 'youtube-dl-exec'; import { json, error } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import { spawn } from 'child_process'; /** * Fetch YouTube metadata (title, uploader/artist) */ async function getYouTubeMetadata(link: string) { return await ytdl(link, { dumpSingleJson: true, noCheckCertificates: true, noWarnings: true, preferFreeFormats: true }); } /** * Streams the YouTube video/audio using youtube-dl-exec */ function streamYouTube(link: string, format: string): ReadableStream { return new ReadableStream({ start(controller) { const args = [ '-o', '-', format === 'mp3' ? '--embed-metadata' : '', '--format', format === 'mp3' ? 'bestaudio' : 'best', '--audio-format', format === 'mp3' ? 'mp3' : '', '--no-playlist' ].filter(Boolean); const process = spawn('yt-dlp', [...args, link], { stdio: ['ignore', 'pipe', 'ignore'] }); process.stdout.on('data', (chunk) => controller.enqueue(chunk)); process.stdout.on('end', () => controller.close()); process.stdout.on('error', (err) => { console.error('Stream error:', err); controller.error(err); }); } }); } /** * Sanitize filename by removing unsafe characters */ function sanitizeFilename(name: string): string { return name.replace(/[\/:*?"<>|]/g, '').trim(); } export const GET: RequestHandler = async ({ url }) => { // Get query params const link = url.searchParams.get('link'); const format = url.searchParams.get('format'); // mp3, mp4 const source = url.searchParams.get('source'); // youtube or spotify // Validate input if (!link || !format || !source) { throw error(400, 'Missing required query parameters: link, format, or source'); } if (source !== 'youtube') { throw error(400, 'Currently, only YouTube is supported'); } try { // Fetch metadata for filename const metadata = await getYouTubeMetadata(link); const { title, uploader } = metadata; const safeTitle = sanitizeFilename(`${uploader} - ${title}`); const filename = `${safeTitle}.${format}`; console.log(filename) // Stream video/audio return new Response(streamYouTube(link, format), { headers: { 'Content-Type': format === 'mp3' ? 'audio/mpeg' : 'video/mp4', 'Content-Disposition': `attachment; filename="${filename}"` } }); } catch (err) { console.error('Error fetching metadata:', err); throw error(500, 'Failed to fetch video metadata'); } };