153 lines
5.4 KiB
Markdown
153 lines
5.4 KiB
Markdown
# AV1 Batch Video Transcoder - Project Structure
|
|
|
|
## Overview
|
|
This project is a modular batch video transcoding system using NVIDIA's av1_nvenc codec with intelligent audio stream processing and resolution handling.
|
|
|
|
## Architecture
|
|
|
|
### Entry Point
|
|
- **main.py** - CLI entry point with argument parsing
|
|
- Loads configuration from `config.xml`
|
|
- Initializes logger and CSV tracker
|
|
- Dispatches to `process_folder()` for batch processing
|
|
|
|
### Core Modules
|
|
|
|
#### `core/config_helper.py`
|
|
- XML configuration parser
|
|
- Returns dict with audio, encoding, and filter settings
|
|
- **Key Config:**
|
|
- `audio.stereo.high/medium`: Target bitrates for stereo audio (1080p/720p)
|
|
- `audio.multi_channel.low/medium`: Target bitrates for multichannel audio
|
|
- `encode.cq`: CQ values per content type (tv_720, tv_1080, movie_720, movie_1080, etc.)
|
|
- `encode.fallback`: Bitrate fallback settings (900k/1080p, 650k/720p, etc.)
|
|
- `extensions`: Video file types to process (mkv, mp4, etc.)
|
|
- `ignore_tags`: Files to skip (trailer, sample, etc.)
|
|
|
|
#### `core/logger_helper.py`
|
|
- Comprehensive logging to `logs/conversion.log`
|
|
- Captures source/target specs, audio decisions, bitrate info
|
|
- Separate handlers for console (INFO+) and file (DEBUG+)
|
|
|
|
#### `core/audio_handler.py`
|
|
- **`calculate_stream_bitrate(input_file, stream_index)`**: Extracts audio stream with ffmpeg `-c copy`, parses bitrate output, falls back to file size calculation
|
|
- **`get_audio_streams(input_file)`**: Detects all audio streams with robust bitrate calculation
|
|
- **`choose_audio_bitrate(channels, bitrate_kbps, audio_config, is_1080_class)`**: Returns (codec, target_bitrate) tuple
|
|
- Stereo 1080p+: >192k → encode; ≤192k → preserve ("copy")
|
|
- Stereo 720p: >160k → encode; ≤160k → preserve
|
|
- Multichannel: Encodes to low (384k) or medium (448k) based on current bitrate
|
|
|
|
#### `core/video_handler.py`
|
|
- **`get_source_resolution(input_file)`**: ffprobe detection of video dimensions
|
|
- **`determine_target_resolution(src_width, src_height, explicit_resolution)`**: Smart resolution logic
|
|
- If >1080p → scale to 1080p
|
|
- Else → preserve source resolution
|
|
- Can be overridden with explicit `--r 480/720/1080` argument
|
|
|
|
#### `core/encode_engine.py`
|
|
- **`run_ffmpeg(...)`**: Main FFmpeg encoding orchestration
|
|
- Builds command with av1_nvenc settings
|
|
- Per-stream audio codec/bitrate decisions
|
|
- Handles both CQ and Bitrate modes
|
|
- Logs detailed before/after specs
|
|
|
|
#### `core/process_manager.py`
|
|
- **`process_folder(...)`**: Main batch processing loop
|
|
- Classifies files as TV/Movie/Anime based on path
|
|
- Detects per-file source resolution
|
|
- Applies smart resolution defaults or explicit overrides
|
|
- Handles CQ → Bitrate fallback if size threshold exceeded
|
|
- Tracks results in `conversion_tracker.csv`
|
|
- Deletes originals after successful encoding
|
|
|
|
## Workflow
|
|
|
|
1. **User** runs: `python main.py "C:\Videos\TV\ShowName" --r 720 --m bitrate`
|
|
2. **main.py** parses args, loads config.xml
|
|
3. **process_manager** iterates video files in folder
|
|
4. For each file:
|
|
- **video_handler** detects source resolution
|
|
- **audio_handler** analyzes audio streams and calculates bitrates
|
|
- **encode_engine** builds FFmpeg command with smart audio/resolution settings
|
|
- FFmpeg encodes with per-stream audio decisions
|
|
- **tracker** logs results to CSV
|
|
5. **logger** captures all details to `logs/conversion.log`
|
|
|
|
## Configuration Examples
|
|
|
|
### Force 720p Bitrate Mode
|
|
```bash
|
|
python main.py "C:\Videos\TV\Show" --r 720 --m bitrate
|
|
```
|
|
|
|
### Force 1080p with CQ=28
|
|
```bash
|
|
python main.py "C:\Videos\Movies" --cq 28 --r 1080
|
|
```
|
|
|
|
### Smart Mode (preserve resolution, 4K→1080p)
|
|
```bash
|
|
python main.py "C:\Videos\Mixed"
|
|
```
|
|
|
|
### Force 480p (for low-res content)
|
|
```bash
|
|
python main.py "C:\Videos\OldTV" --r 480
|
|
```
|
|
|
|
## Audio Encoding Logic
|
|
|
|
### Decision Tree
|
|
```
|
|
Stereo audio?
|
|
├─ YES + 1080p: [>192kbps] ENCODE to 192k AAC, [≤192k] COPY
|
|
├─ YES + 720p: [>160kbps] ENCODE to 160k AAC, [≤160k] COPY
|
|
└─ NO (Multichannel 6ch+): ENCODE to 384k (low) or 448k (medium) AAC
|
|
```
|
|
|
|
### Rationale
|
|
- Preserves high-quality original audio when already well-compressed
|
|
- Re-encodes excessive bitrate audio to standard targets
|
|
- Handles stereo at different resolutions appropriately
|
|
- Normalizes multichannel to 6ch surround (5.1) or 2ch stereo
|
|
|
|
## Files Modified/Created
|
|
|
|
### New Modules (Session Work)
|
|
- ✅ `core/audio_handler.py` - NEW
|
|
- ✅ `core/video_handler.py` - NEW
|
|
- ✅ `core/encode_engine.py` - NEW
|
|
- ✅ `core/process_manager.py` - NEW
|
|
- ✅ `main.py` - REFACTORED (524 lines → 70 lines)
|
|
|
|
### Cleanup
|
|
- ✅ Deleted `core/ffmpeg_helper.py` (code moved to audio_handler)
|
|
- ✅ Deleted `core/process_helper.py` (empty)
|
|
- ✅ Deleted `core/tracker_helper.py` (empty)
|
|
|
|
### Enhanced
|
|
- ✅ `config.xml` - Added `<low>384000</low>` to multi_channel audio
|
|
- ✅ `transcode.bat` - Enhanced with job counting and status tracking
|
|
- ✅ `paths.txt` - Queue format with --r and --m flags
|
|
|
|
## Validation Checklist
|
|
- ✅ All modules pass Pylance syntax check
|
|
- ✅ All imports resolve correctly
|
|
- ✅ Config loads and provides expected keys
|
|
- ✅ No unused/deprecated files remain
|
|
- ✅ Project structure clean and maintainable
|
|
|
|
## Running Tests
|
|
|
|
Verify the complete system:
|
|
```bash
|
|
# Test imports
|
|
python -c "from core.audio_handler import *; from core.video_handler import *; print('OK')"
|
|
|
|
# Run on test folder
|
|
python main.py "C:\Test\Videos" --r 720 --m bitrate
|
|
|
|
# Check logs
|
|
cat logs/conversion.log
|
|
```
|