nvenc
This commit is contained in:
@@ -11,6 +11,28 @@ import atexit
|
||||
import warnings
|
||||
|
||||
|
||||
def test_nvenc_support() -> bool:
|
||||
"""Test if NVENC encoding is available"""
|
||||
try:
|
||||
# Quick test with a 1-frame video
|
||||
cmd = [
|
||||
'ffmpeg', '-f', 'lavfi', '-i', 'testsrc=duration=0.1:size=320x240:rate=1',
|
||||
'-c:v', 'h264_nvenc', '-t', '0.1', '-f', 'null', '-'
|
||||
]
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
timeout=10,
|
||||
text=True
|
||||
)
|
||||
|
||||
return result.returncode == 0
|
||||
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||||
return False
|
||||
|
||||
|
||||
class StreamingFrameWriter:
|
||||
"""Write frames directly to ffmpeg via pipe for memory-efficient output"""
|
||||
|
||||
@@ -36,6 +58,16 @@ class StreamingFrameWriter:
|
||||
self.frames_written = 0
|
||||
self.ffmpeg_process = None
|
||||
|
||||
# Test NVENC support if GPU codec requested
|
||||
if video_codec in ['h264_nvenc', 'hevc_nvenc']:
|
||||
print(f"🔍 Testing NVENC support...")
|
||||
if not test_nvenc_support():
|
||||
print(f"❌ NVENC not available, switching to CPU encoding")
|
||||
video_codec = 'libx264'
|
||||
quality_preset = 'medium'
|
||||
else:
|
||||
print(f"✅ NVENC available")
|
||||
|
||||
# Build ffmpeg command
|
||||
self.ffmpeg_cmd = self._build_ffmpeg_command(
|
||||
video_codec, quality_preset, crf
|
||||
@@ -134,23 +166,39 @@ class StreamingFrameWriter:
|
||||
|
||||
# Test if ffmpeg starts successfully (quick check)
|
||||
import time
|
||||
time.sleep(0.1) # Give ffmpeg time to fail if it's going to
|
||||
time.sleep(0.2) # Give ffmpeg time to fail if it's going to
|
||||
|
||||
if self.ffmpeg_process.poll() is not None:
|
||||
# Process already died - read error
|
||||
stderr = self.ffmpeg_process.stderr.read().decode()
|
||||
raise RuntimeError(f"FFmpeg failed immediately: {stderr}")
|
||||
|
||||
# Check for specific NVENC errors and provide better feedback
|
||||
if 'nvenc' in ' '.join(self.ffmpeg_cmd):
|
||||
if 'unsupported device' in stderr.lower():
|
||||
print(f"❌ NVENC not available on this GPU - switching to CPU encoding")
|
||||
elif 'cannot load' in stderr.lower() or 'not found' in stderr.lower():
|
||||
print(f"❌ NVENC drivers not available - switching to CPU encoding")
|
||||
else:
|
||||
print(f"❌ NVENC encoding failed: {stderr}")
|
||||
|
||||
# Try CPU fallback
|
||||
print(f"🔄 Falling back to CPU encoding (libx264)...")
|
||||
self.ffmpeg_cmd = self._build_ffmpeg_command('libx264', 'medium', 18)
|
||||
return self._start_ffmpeg()
|
||||
else:
|
||||
raise RuntimeError(f"FFmpeg failed: {stderr}")
|
||||
|
||||
# Set process to ignore SIGINT (Ctrl+C) - we'll handle it
|
||||
if hasattr(signal, 'pthread_sigmask'):
|
||||
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])
|
||||
|
||||
except Exception as e:
|
||||
# Try CPU fallback if GPU encoding fails
|
||||
# Final fallback if everything fails
|
||||
if 'nvenc' in ' '.join(self.ffmpeg_cmd):
|
||||
print(f"⚠️ GPU encoding failed, trying CPU fallback...")
|
||||
print(f"⚠️ GPU encoding failed with error: {e}")
|
||||
print(f"🔄 Falling back to CPU encoding...")
|
||||
self.ffmpeg_cmd = self._build_ffmpeg_command('libx264', 'medium', 18)
|
||||
self._start_ffmpeg()
|
||||
return self._start_ffmpeg()
|
||||
else:
|
||||
raise RuntimeError(f"Failed to start ffmpeg: {e}")
|
||||
|
||||
|
||||
@@ -83,9 +83,10 @@ class SAM2StreamingProcessor:
|
||||
# Set to eval mode
|
||||
self.predictor.eval()
|
||||
|
||||
# Enable FP16 if requested
|
||||
# Note: FP16 conversion can cause type mismatches with compiled models
|
||||
# Let SAM2 handle precision internally via build_sam2_video_predictor options
|
||||
if self.fp16 and self.device.type == 'cuda':
|
||||
self.predictor = self.predictor.half()
|
||||
print(" FP16 enabled via SAM2 internal settings")
|
||||
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Failed to initialize SAM2 predictor: {e}")
|
||||
|
||||
Reference in New Issue
Block a user