Added FFmpeg system

This commit is contained in:
Trevor Mears
2025-12-31 09:52:26 -08:00
parent bec1b74208
commit a90ac32a3b
3 changed files with 33 additions and 12 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
FROM node:20-alpine FROM node:20-alpine
# Install build dependencies for better-sqlite3 # Install build dependencies for better-sqlite3 and FFmpeg for streaming
RUN apk add --no-cache python3 make g++ # Using system FFmpeg instead of ffmpeg-static for better Docker DNS compatibility
RUN apk add --no-cache python3 make g++ ffmpeg
WORKDIR /app WORKDIR /app
+27 -10
View File
@@ -16,21 +16,38 @@ app.use(express.json({ limit: '50mb' }));
app.use(express.static(path.join(__dirname, '..', 'public'))); app.use(express.static(path.join(__dirname, '..', 'public')));
// FFMPEG Configuration (optional - for transcoding support) // FFMPEG Configuration (optional - for transcoding support)
try { // Priority: 1. System FFmpeg (better Docker DNS support), 2. ffmpeg-static npm package
let ffmpegPath = require('ffmpeg-static'); const { execSync } = require('child_process');
// In packaged Electron apps, ffmpeg-static returns path inside .asar archive function findFFmpeg() {
// but the binary is actually unpacked to app.asar.unpacked // Try system FFmpeg first (better Docker compatibility)
if (ffmpegPath && ffmpegPath.includes('app.asar')) { try {
ffmpegPath = ffmpegPath.replace('app.asar', 'app.asar.unpacked'); 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; // Try ffmpeg-static npm package
console.log('FFmpeg binary configured at:', ffmpegPath); try {
} catch (err) { let ffmpegPath = require('ffmpeg-static');
console.warn('FFmpeg not available - transcoding will be disabled. Install ffmpeg-static for transcoding support.'); // 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 // API Routes
app.use('/api/sources', require('./routes/sources')); app.use('/api/sources', require('./routes/sources'));
app.use('/api/proxy', require('./routes/proxy')); app.use('/api/proxy', require('./routes/proxy'));
+3
View File
@@ -30,6 +30,9 @@ router.get('/', (req, res) => {
'-i', url, '-i', url,
// Copy ALL streams without re-encoding // Copy ALL streams without re-encoding
'-c', 'copy', '-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) // Fragmented MP4 for streaming (browser-compatible)
'-f', 'mp4', '-f', 'mp4',
'-movflags', 'frag_keyframe+empty_moov+default_base_moof', '-movflags', 'frag_keyframe+empty_moov+default_base_moof',