Fix GPU transcoding timeout - use CBR mode, increase timeouts, add keyframe interval

This commit is contained in:
Michael committed 2026-01-01 23:27:04 +01:00
1 parent a00d5ae4da
commit cd3a49ce63
2 files changed
+20 -15

No files matched your search

+18 -13
View File
@@ -157,14 +157,14 @@ Handler createLiveStreamHandler(
final ffmpegArgs = <String>[ final ffmpegArgs = <String>[
'-hide_banner', '-hide_banner',
'-loglevel', '-loglevel',
'error', 'warning', // Changed from error to see more info
]; ];
// NVIDIA GPU Hardware Acceleration (NVDEC for decoding) // NVIDIA GPU Hardware Acceleration (NVDEC for decoding)
if (useNvidiaGpu) { if (useNvidiaGpu) {
ffmpegArgs.addAll([ ffmpegArgs.addAll([
'-hwaccel', 'cuda', // Use NVIDIA CUDA for decoding '-hwaccel', 'cuda', // Use NVIDIA CUDA for decoding
'-hwaccel_output_format', 'cuda', // Keep frames on GPU // Note: Don't use hwaccel_output_format cuda - it can cause issues with some codecs
]); ]);
} }
@@ -179,15 +179,17 @@ Handler createLiveStreamHandler(
'-reconnect_streamed', '-reconnect_streamed',
'1', '1',
'-reconnect_delay_max', '-reconnect_delay_max',
'5', '10', // Increased from 5
'-rw_timeout', '-rw_timeout',
'15000000', '30000000', // Increased from 15s to 30s
'-timeout',
'30000000', // Add explicit timeout
'-fflags', '-fflags',
'+nobuffer+fastseek+genpts', '+nobuffer+genpts+discardcorrupt', // Added discardcorrupt for robustness
'-analyzeduration', '-analyzeduration',
'3000000', '5000000', // Increased for GPU decode
'-probesize', '-probesize',
'5000000', '10000000', // Increased for GPU decode
'-i', '-i',
targetUrl, targetUrl,
]); ]);
@@ -198,15 +200,18 @@ Handler createLiveStreamHandler(
print('[Live] Transcoding video with h264_nvenc (GPU)'); print('[Live] Transcoding video with h264_nvenc (GPU)');
ffmpegArgs.addAll([ ffmpegArgs.addAll([
'-c:v', 'h264_nvenc', // Use NVIDIA NVENC encoder '-c:v', 'h264_nvenc', // Use NVIDIA NVENC encoder
'-preset', 'p4', // Good quality/speed balance (p1=fastest, p7=best) '-preset', 'p1', // Fastest preset for live (p1=fastest)
'-tune', 'll', // Low latency tuning for live streams '-tune', 'll', // Low latency tuning for live streams
'-rc', 'vbr', // Variable bitrate '-rc', 'cbr', // Constant bitrate for stable streaming
'-cq', '23', // Quality level (similar to CRF) '-b:v', '4000k', // Fixed video bitrate
'-maxrate', '6000k', // Max bitrate for live '-maxrate', '4500k', // Max bitrate
'-bufsize', '12000k', // Buffer size '-bufsize', '8000k', // Buffer size (2x bitrate)
'-g', '50', // Keyframe interval (every 2 seconds at 25fps)
'-bf', '0', // No B-frames for lower latency
'-c:a', 'aac', // Audio to AAC (browser compatible) '-c:a', 'aac', // Audio to AAC (browser compatible)
'-b:a', '192k', '-b:a', '128k', // Audio bitrate
'-ac', '2', '-ac', '2',
'-ar', '44100', // Audio sample rate
]); ]);
} else { } else {
// Without GPU: Standard CPU processing (copy video) // Without GPU: Standard CPU processing (copy video)
+2 -2
View File
@@ -424,7 +424,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
// Bottom Controls - styled like EPG // Bottom Controls - styled like EPG
AnimatedPositioned( AnimatedPositioned(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
bottom: _showControls ? 100 : -100, bottom: _showControls ? 16 : -100,
left: 24, left: 24,
right: 24, right: 24,
child: Center( child: Center(
@@ -493,7 +493,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
if (widget.streamType == StreamType.live) if (widget.streamType == StreamType.live)
AnimatedPositioned( AnimatedPositioned(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
bottom: _showControls ? 16 : -140, bottom: _showControls ? 100 : -140,
left: 24, left: 24,
right: 24, right: 24,
child: PointerInterceptor( child: PointerInterceptor(