Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 87 additions & 18 deletions src/services/RtspStreamService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,28 +136,97 @@ export class RtspStreamService extends EventEmitter {

/**
* Check if ffmpeg is available on the system
* On macOS, Electron apps don't inherit user PATH, so check common install locations explicitly
* Also checks common paths on Linux (Snap, Flatpak, etc.) and Windows
*/
private async checkFfmpegAvailability(): Promise<void> {
try {
const { stdout } = await execAsync('ffmpeg -version');
const versionMatch = stdout.match(/ffmpeg version ([^\s]+)/);
const version = versionMatch ? versionMatch[1] : 'unknown';

this.ffmpegStatus = {
available: true,
version
};

console.log(`[RtspStreamService] ffmpeg found: version ${version}`);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.ffmpegStatus = {
available: false,
error: errorMessage
};
// Common ffmpeg installation paths across platforms
// Order matters: try PATH first, then check platform-specific locations
const ffmpegPaths = [
'ffmpeg', // Try PATH first (works if launched from terminal or properly configured)

// ===== macOS =====
// Homebrew (most common on macOS)
'/opt/homebrew/bin/ffmpeg', // Homebrew on Apple Silicon (M1/M2/M3)
'/usr/local/bin/ffmpeg', // Homebrew on Intel Mac
'/opt/local/bin/ffmpeg', // MacPorts

// ===== Linux =====
// Standard package manager locations (usually in PATH, but checking explicitly doesn't hurt)
'/usr/bin/ffmpeg', // apt (Debian/Ubuntu), yum/dnf (Fedora/RHEL), pacman (Arch)

// Universal package managers (often not in Electron's PATH)
'/snap/bin/ffmpeg', // Snap packages
'/var/lib/flatpak/exports/bin/ffmpeg', // Flatpak system-wide
'~/.local/share/flatpak/exports/bin/ffmpeg', // Flatpak user install

// Manual/compiled installations
'/usr/local/bin/ffmpeg', // Common manual install location
'~/bin/ffmpeg', // User home bin directory

// ===== Windows =====
'C:\\ffmpeg\\bin\\ffmpeg.exe', // Common manual install
'C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe', // Program Files install
'C:\\Program Files (x86)\\ffmpeg\\bin\\ffmpeg.exe', // 32-bit on 64-bit system
];

let lastError = '';

// Try each path in order
for (const ffmpegPath of ffmpegPaths) {
try {
// Expand ~ to home directory if present
const expandedPath = ffmpegPath.replace(/^~/, process.env.HOME || process.env.USERPROFILE || '');

// Quote the path to handle spaces
const { stdout } = await execAsync(`"${expandedPath}" -version`);
const versionMatch = stdout.match(/ffmpeg version ([^\s]+)/);
const version = versionMatch ? versionMatch[1] : 'unknown';

this.ffmpegStatus = {
available: true,
version
};

// Add ffmpeg directory to PATH so node-rtsp-stream can spawn it
// This is critical for macOS GUI launches where PATH doesn't include Homebrew paths
if (expandedPath !== 'ffmpeg') { // Only for explicit paths, not PATH-based
const lastSlashIndex = expandedPath.lastIndexOf('/');
const lastBackslashIndex = expandedPath.lastIndexOf('\\');
const separatorIndex = Math.max(lastSlashIndex, lastBackslashIndex);

if (separatorIndex > 0) {
const ffmpegDir = expandedPath.substring(0, separatorIndex);
const pathSep = process.platform === 'win32' ? ';' : ':';

// Add to beginning of PATH so it takes precedence
process.env.PATH = `${ffmpegDir}${pathSep}${process.env.PATH || ''}`;
console.log(`[RtspStreamService] Added ${ffmpegDir} to PATH for node-rtsp-stream`);
}
}

console.warn('[RtspStreamService] ffmpeg not found:', errorMessage);
console.log(`[RtspStreamService] ffmpeg found at ${expandedPath}: version ${version}`);
return; // Success! Exit the function
} catch (error) {
lastError = error instanceof Error ? error.message : String(error);
// Continue to next path
}
}

// If we get here, ffmpeg wasn't found in any location
this.ffmpegStatus = {
available: false,
error: `ffmpeg not found in any common location. Last error: ${lastError}`
};

console.warn('[RtspStreamService] ffmpeg not found in any location');
console.warn('[RtspStreamService] Searched paths:', ffmpegPaths);
console.warn('[RtspStreamService] Install ffmpeg to enable RTSP camera viewing:');
console.warn('[RtspStreamService] - macOS: brew install ffmpeg');
console.warn('[RtspStreamService] - Ubuntu/Debian: sudo apt install ffmpeg');
console.warn('[RtspStreamService] - Fedora/RHEL: sudo dnf install ffmpeg');
console.warn('[RtspStreamService] - Arch: sudo pacman -S ffmpeg');
console.warn('[RtspStreamService] - Windows: Download from ffmpeg.org');
}

// ============================================================================
Expand Down