Refactor code structure for improved readability and maintainability

This commit is contained in:
MaddoScientisto 2026-02-09 21:56:17 +01:00
commit dd8abf03d3
4 changed files with 108 additions and 16 deletions

View file

@ -2,9 +2,18 @@
Inspired by https://github.com/EnterGin/Auto-Stream-Recording-Twitch
Python script to check, download live stream, VOD, chat and upload them to any cloud storage supported by rclone.
## ⚡ FFmpeg 8.0 Enhanced
Now with FFmpeg 8.0+ support featuring hardware acceleration and performance improvements!
- **5-10x faster encoding** with NVIDIA, Intel, or AMD GPUs
- **Docker-ready** with Linux builds
- **Configurable options** for different scenarios
- 📖 **[See FFMPEG_SETUP.md for detailed setup instructions](FFMPEG_SETUP.md)**
## Requirements
- [Python 3](https://www.python.org/downloads/)
- [Streamlink](https://github.com/streamlink/streamlink)
- [FFmpeg 8.0+](https://ffmpeg.org/download.html) (see [FFMPEG_SETUP.md](FFMPEG_SETUP.md) for platform-specific versions)
## Getting started
1. Install Python 3.x
2. Install Streamlink 5.1.x

BIN
bin/ffmpeg (Stored with Git LFS)

Binary file not shown.

BIN
bin/ffmpeg.exe (Stored with Git LFS)

Binary file not shown.

View file

@ -72,7 +72,16 @@ DEFAULT_CONFIG = {
'onlyRaw': 0,
'cleanRaw': 1,
'hls_segments': 3,
'hls_segmentsVOD': 10
'hls_segmentsVOD': 10,
# FFmpeg 8.0+ Enhancement Options
'ffmpeg_hwaccel': 'auto', # Hardware acceleration: 'auto', 'nvenc', 'qsv', 'amf', 'vaapi', 'none'
'ffmpeg_threads': 0, # Thread count (0 = auto-detect)
'ffmpeg_audio_codec': 'aac', # Audio codec for audio-only streams
'ffmpeg_audio_samplerate': 48000, # Audio sample rate (48000 recommended for broadcasts)
'ffmpeg_audio_bitrate': '192k', # Audio bitrate
'ffmpeg_error_recovery': 1, # Enable error recovery for corrupted streams (0/1)
'ffmpeg_faststart': 1, # Enable faststart for MP4 (better streaming compatibility) (0/1)
'ffmpeg_progress': 0 # Show encoding progress (0/1)
}
# ============================================================================
@ -537,6 +546,36 @@ class TwitchArchive:
return os.path.join(bin_path, 'TwitchDownloaderCLI.exe')
return os.path.join(bin_path, 'TwitchDownloaderCLI')
def _detect_hardware_acceleration(self) -> Optional[str]:
"""
Detect available hardware acceleration based on config and system.
Returns:
str: Hardware acceleration type ('nvenc', 'qsv', 'amf', 'vaapi', 'none') or None
"""
hwaccel_config = getattr(self, 'ffmpeg_hwaccel', 'auto')
# If user explicitly set to 'none', disable hardware acceleration
if hwaccel_config == 'none':
return 'none'
# If user specified a particular type, use it
if hwaccel_config in ['nvenc', 'qsv', 'amf', 'vaapi']:
return hwaccel_config
# Auto-detect: try to determine available hardware
if hwaccel_config == 'auto':
# On Windows, NVIDIA is most common
if self.os == 'windows':
# Could check for nvidia-smi, but just return 'auto' for ffmpeg to decide
return 'auto'
else:
# On Linux, VAAPI is common for Intel/AMD, or NVENC for NVIDIA
# Let ffmpeg auto-detect
return 'auto'
return None
def _record_livestream(self, stream_info: Dict[str, Any], output_path: str) -> bool:
"""
Record a live Twitch stream using streamlink.
@ -624,33 +663,77 @@ class TwitchArchive:
# Build ffmpeg command based on quality
if self.quality == 'audio_only':
# Audio-only conversion
# Audio-only conversion with modern AAC encoding
cmd = [
self._get_ffmpeg_executable(),
'-i', raw_path,
'-vn', # No video
'-ar', '44100', # Audio sample rate
'-c:a', self.ffmpeg_audio_codec, # Audio codec (AAC recommended)
'-ar', str(self.ffmpeg_audio_samplerate), # Audio sample rate
'-ac', '2', # Audio channels (stereo)
'-b:a', '192k', # Audio bitrate
output_path
'-b:a', self.ffmpeg_audio_bitrate, # Audio bitrate
]
# Add threading for faster encoding
if self.ffmpeg_threads > 0:
cmd.extend(['-threads', str(self.ffmpeg_threads)])
# Add faststart for better streaming compatibility (MP4/M4A)
if self.ffmpeg_faststart == 1 and output_path.endswith(('.mp4', '.m4a')):
cmd.extend(['-movflags', '+faststart'])
cmd.append(output_path)
else:
# Video conversion (copy streams for speed)
# Video conversion with hardware acceleration support
cmd = [
self._get_ffmpeg_executable(),
'-y', # Overwrite output file
]
# Add hardware acceleration if enabled
hwaccel_type = self._detect_hardware_acceleration()
if hwaccel_type and hwaccel_type != 'none':
print(f'{Fore.CYAN}Using hardware acceleration: {hwaccel_type}{Style.RESET_ALL}')
cmd.extend(['-hwaccel', 'auto'])
cmd.extend([
'-i', raw_path,
'-analyzeduration', '2147483647',
'-probesize', '2147483647',
'-c:v', 'copy', # Copy video codec (fast)
'-c:a', 'copy', # Copy audio codec (fast)
])
# Threading support
if self.ffmpeg_threads >= 0:
cmd.extend(['-threads', str(self.ffmpeg_threads)])
# Error recovery options for corrupted streams
if self.ffmpeg_error_recovery == 1:
cmd.extend([
'-fflags', '+genpts', # Generate missing timestamps
'-avoid_negative_ts', 'make_zero', # Handle timestamp issues
'-err_detect', 'ignore_err' # More tolerant of errors
])
# Stream copy (fast, no re-encoding)
cmd.extend([
'-c:v', 'copy', # Copy video codec
'-c:a', 'copy', # Copy audio codec
'-start_at_zero',
'-copyts',
output_path
]
])
# Add faststart for MP4 files
if self.ffmpeg_faststart == 1 and output_path.endswith('.mp4'):
cmd.extend(['-movflags', '+faststart'])
cmd.append(output_path)
# Run ffmpeg with optional progress output
if self.ffmpeg_progress == 1:
subprocess.call(cmd)
else:
subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
# Run ffmpeg (suppress output)
subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
print(f'{Fore.GREEN}✓ Stream processed successfully{Style.RESET_ALL}')
def _download_vod(self, vod_info: Dict[str, Any], output_path: str) -> bool: