diff --git a/Dockerfile b/Dockerfile index e57f867..cae87a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ FROM node:20-alpine -# Install build dependencies for better-sqlite3 -RUN apk add --no-cache python3 make g++ +# Install build dependencies for better-sqlite3 and FFmpeg for streaming +# Using system FFmpeg instead of ffmpeg-static for better Docker DNS compatibility +RUN apk add --no-cache python3 make g++ ffmpeg WORKDIR /app diff --git a/server/index.js b/server/index.js index 98555c7..ca1b633 100644 --- a/server/index.js +++ b/server/index.js @@ -16,21 +16,38 @@ app.use(express.json({ limit: '50mb' })); app.use(express.static(path.join(__dirname, '..', 'public'))); // FFMPEG Configuration (optional - for transcoding support) -try { - let ffmpegPath = require('ffmpeg-static'); +// Priority: 1. System FFmpeg (better Docker DNS support), 2. ffmpeg-static npm package +const { execSync } = require('child_process'); - // In packaged Electron apps, ffmpeg-static returns path inside .asar archive - // but the binary is actually unpacked to app.asar.unpacked - if (ffmpegPath && ffmpegPath.includes('app.asar')) { - ffmpegPath = ffmpegPath.replace('app.asar', 'app.asar.unpacked'); +function findFFmpeg() { + // Try system FFmpeg first (better Docker compatibility) + try { + execSync('ffmpeg -version', { stdio: 'ignore' }); + console.log('FFmpeg binary configured at: ffmpeg (system)'); + return 'ffmpeg'; + } catch (e) { + // System FFmpeg not found, try ffmpeg-static } - app.locals.ffmpegPath = ffmpegPath; - console.log('FFmpeg binary configured at:', ffmpegPath); -} catch (err) { - console.warn('FFmpeg not available - transcoding will be disabled. Install ffmpeg-static for transcoding support.'); + // Try ffmpeg-static npm package + try { + let ffmpegPath = require('ffmpeg-static'); + // In packaged Electron apps, ffmpeg-static returns path inside .asar archive + // but the binary is actually unpacked to app.asar.unpacked + if (ffmpegPath && ffmpegPath.includes('app.asar')) { + ffmpegPath = ffmpegPath.replace('app.asar', 'app.asar.unpacked'); + } + console.log('FFmpeg binary configured at:', ffmpegPath); + return ffmpegPath; + } catch (err) { + console.warn('FFmpeg not available - transcoding/remuxing will be disabled.'); + console.warn('Install FFmpeg via your package manager or npm install ffmpeg-static'); + return null; + } } +app.locals.ffmpegPath = findFFmpeg(); + // API Routes app.use('/api/sources', require('./routes/sources')); app.use('/api/proxy', require('./routes/proxy')); diff --git a/server/routes/remux.js b/server/routes/remux.js index 476193b..5ebd0cd 100644 --- a/server/routes/remux.js +++ b/server/routes/remux.js @@ -30,6 +30,9 @@ router.get('/', (req, res) => { '-i', url, // Copy ALL streams without re-encoding '-c', 'copy', + // Convert AAC from ADTS format (TS) to ASC format (MP4) + // Required when remuxing MPEG-TS with AAC audio to MP4 + '-bsf:a', 'aac_adtstoasc', // Fragmented MP4 for streaming (browser-compatible) '-f', 'mp4', '-movflags', 'frag_keyframe+empty_moov+default_base_moof',