major improvements

This commit is contained in:
TylerCG 2026-05-17 21:21:28 -04:00
parent 6b46f4aa33
commit 7e77f85b5f
29 changed files with 83208 additions and 64556 deletions

View File

@ -1,422 +0,0 @@
# Interactive Audio Stream Selection - Architecture Diagram
## System Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ main.py │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ArgumentParser │ │
│ │ --filter-audio (enables audio filtering) │ │
│ │ --interactive (enables interactive mode) ← NEW │ │
│ │ --cq, --r, --m, --language, --test (existing) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ normalize_input_path() → folder path │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ process_folder( │ │
│ │ filter_audio=True/False, │ │
│ │ interactive_audio=True/False ← NEW │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ core/process_manager.py │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ process_folder(folder, ..., filter_audio, interactive) │ │
│ │ ↑ NEW param │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ For each video file: │ │
│ │ 1. Get source resolution & target resolution │ │
│ │ 2. Create audio_filter_config dict: │ │
│ │ { │ │
│ │ "enabled": filter_audio, │ │
│ │ "interactive": interactive_audio ← NEW FIELD │ │
│ │ } │ │
│ │ 3. Call run_ffmpeg() with audio_filter_config │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ core/encode_engine.py │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ run_ffmpeg( │ │
│ │ input_file, output_file, ..., │ │
│ │ audio_filter_config={enabled, interactive} │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. streams = get_audio_streams(input_file) │ │
│ │ └─ Returns: [(index, ch, br, lang, meta), ...] │ │
│ │ │ │
│ │ 2. if audio_filter_config.get("enabled"): │ │
│ │ ├─ if audio_filter_config.get("interactive"): │ │
│ │ │ └─ Call: prompt_user_audio_selection(streams) ← ◆ │ │
│ │ │ [SHOWS PROMPT TO USER] │ │
│ │ │ └─ Returns: filtered_streams │ │
│ │ │ │ │
│ │ └─ else: │ │
│ │ └─ Call: filter_audio_streams(input_file, streams) │ │
│ │ (Automatic: keep best English + Commentary) │ │
│ │ └─ Returns: filtered_streams │ │
│ │ │ │
│ │ 3. For each stream in filtered_streams: │ │
│ │ ├─ choose_audio_bitrate() (codec selection) │ │
│ │ └─ Build FFmpeg codec params (-c:a, -b:a, etc.) │ │
│ │ │ │
│ │ 4. subprocess.run(ffmpeg_cmd) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ core/audio_handler.py │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ def prompt_user_audio_selection(streams) ← NEW FUNCTION │ │
│ │ ◆ Interactive User Prompt ◆ │ │
│ │ │ │
│ │ Display: │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ 🎵 AUDIO STREAM SELECTION │ │ │
│ │ │ │ │ │
│ │ │ Stream #0: 2ch | Lang: eng | Bitrate: 128kbps │ │
│ │ │ Stream #1: 6ch | Lang: eng | Bitrate: 448kbps │ │
│ │ │ Stream #2: 2ch | Lang: spa | Bitrate: 128kbps │ │
│ │ │ Stream #3: 2ch | Lang: comment | Bitrate: 64kbps │ │
│ │ │ │ │ │
│ │ │ Keep streams: 1,3 │ │ │
│ │ │ │ │ │
│ │ │ ✅ Keeping 2 stream(s), removing 2 stream(s) │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Process: │ │
│ │ 1. Check if streams empty/single → return as-is │ │
│ │ 2. Display all streams with formatting │ │
│ │ 3. Prompt user for comma-separated indices │ │
│ │ 4. Parse and validate input │ │
│ │ 5. Filter streams to selected only │ │
│ │ 6. Log selections & removed streams │ │
│ │ 7. Return filtered_streams │ │
│ │ │ │
│ │ Error Handling: │ │
│ │ • Invalid input → Keep all (log warning) │ │
│ │ • No selections → Keep all (log warning) │ │
│ │ • Empty input → Keep all (user confirmed) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Data Flow Example
### User Command
```bash
python main.py "C:\Videos" --filter-audio --interactive
```
### Data Transformation
```
Step 1: ArgumentParser
─────────────────────
Input Args:
folder = "C:\Videos"
filter_audio = True
interactive_audio = True
Output: args object
────────────────────────────────────────────────────────
Step 2: main() → process_folder()
───────────────────────────────────
Input:
folder, filter_audio=True, interactive_audio=True
Output: Called with both flags
────────────────────────────────────────────────────────
Step 3: process_folder() → Builds audio_filter_config
──────────────────────────────────────────────────────
Input:
filter_audio=True
interactive_audio=True
Logic:
if filter_audio is not None:
audio_filter_config = {
"enabled": True,
"interactive": True ← NEW
}
Output: audio_filter_config dict
────────────────────────────────────────────────────────
Step 4: process_folder() → run_ffmpeg()
─────────────────────────────────────────
Input:
input_file = "movie.mkv"
audio_filter_config = {"enabled": True, "interactive": True}
Output: Called with config
────────────────────────────────────────────────────────
Step 5: run_ffmpeg() → Audio Stream Detection
──────────────────────────────────────────────
Input:
input_file = "movie.mkv"
Output:
streams = [
(0, 2, 128, "eng", 0), # Stream #0: 2ch English 128kbps
(1, 6, 448, "eng", 0), # Stream #1: 6ch English 448kbps
(2, 2, 128, "spa", 0), # Stream #2: 2ch Spanish 128kbps
(3, 2, 64, "und", 0) # Stream #3: 2ch Undefined 64kbps
]
────────────────────────────────────────────────────────
Step 6: Audio Filtering Decision
────────────────────────────────
Input:
audio_filter_config = {"enabled": True, "interactive": True}
streams = [4 streams above]
Logic:
if audio_filter_config.get("enabled"): ✓ True
if audio_filter_config.get("interactive"): ✓ True
→ Call prompt_user_audio_selection() ← INTERACTIVE PATH
Output: User prompt shown to console
────────────────────────────────────────────────────────
Step 7: prompt_user_audio_selection() → User Input
──────────────────────────────────────────────────────
Input:
streams = [4 streams]
Display:
🎵 AUDIO STREAM SELECTION
════════════════════════════════════════════════════
Stream #0: 2ch | Lang: eng | Bitrate: 128kbps
Stream #1: 6ch | Lang: eng | Bitrate: 448kbps
Stream #2: 2ch | Lang: spa | Bitrate: 128kbps
Stream #3: 2ch | Lang: undefined | Bitrate: 64kbps
Keep streams: ← WAIT FOR USER INPUT
User Input:
"1,3"
Parse:
selected_indices = {1, 3}
Filter:
filtered = [
(1, 6, 448, "eng", 0), ✓ Keep
(3, 2, 64, "und", 0) ✓ Keep
]
Output:
✅ Keeping 2 stream(s), removing 2 stream(s)
Return: filtered streams
────────────────────────────────────────────────────────
Step 8: Back to run_ffmpeg() → Codec Selection
──────────────────────────────────────────────
Input:
streams = [
(1, 6, 448, "eng", 0),
(3, 2, 64, "und", 0)
]
Process each stream:
Stream 1: 6ch → choose_audio_bitrate() → ("eac3", 384000)
Stream 3: 2ch → choose_audio_bitrate() → ("aac", 160000)
Output:
FFmpeg codec params:
-c:a:1 eac3 -b:a:1 384k -ac:1 6 -channel_layout:1 5.1
-c:a:3 aac -b:a:3 160k -ac:3 2 -channel_layout:3 stereo
────────────────────────────────────────────────────────
Step 9: FFmpeg Encoding
───────────────────────
Input:
ffmpeg -i movie.mkv \
-vf scale=... \
-c:v av1_nvenc \
-c:a:1 eac3 -b:a:1 384k ... \
-c:a:3 aac -b:a:3 160k ... \
output.mkv
Process:
FFmpeg encodes video and audio streams
Only streams 1 and 3 included (streams 0 and 2 excluded)
Output:
output.mkv (with only selected audio tracks)
```
## State Diagram
```
┌─────────────────────────────────┐
│ User Runs Script │
│ --filter-audio --interactive │
└──────────────┬──────────────────┘
┌─────────────────────────────────┐
│ Parse Arguments │
│ interactive_audio = True │
└──────────────┬──────────────────┘
┌─────────────────────────────────┐
│ process_folder() │
│ Build audio_filter_config │
│ {enabled: T, interactive: T} │
└──────────────┬──────────────────┘
┌────────────┴────────────┐
│ │
▼ ▼
For each file Detect audio streams
┌──────────────┐ get_audio_streams()
│ run_ffmpeg() │ └─ Returns 4 streams
└──────┬───────┘
┌──────────────────────────┐
│ Check filter enabled? │
│ audio_filter_config │
└──────┬─────────────┬─────┘
│ No │ Yes
│ ▼
│ ┌─────────────────────┐
│ │ Check interactive? │
│ └────┬────────────┬───┘
│ │ No │ Yes
│ │ ▼
│ │ ┌───────────────────┐
│ │ │ INTERACTIVE PROMPT│
│ │ │ Show streams │
│ │ │ Get user input │
│ │ │ Filter streams │
│ │ └─────────┬─────────┘
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Automatic Filter │ │
│ │ (Best English + │ │
│ │ Commentary) │ │
│ └─────────┬────────┘ │
│ │ │
└────────────────┴───────────┘
┌────────────────────────────────┐
│ Apply Codec Selection │
│ (for selected streams only) │
│ choose_audio_bitrate() │
└────────────┬───────────────────┘
┌────────────────────────────────┐
│ Build FFmpeg Command │
│ (with selected audio streams) │
└────────────┬───────────────────┘
┌────────────────────────────────┐
│ Run FFmpeg Encoding │
│ subprocess.run(cmd) │
└────────────┬───────────────────┘
┌────────────────────────────────┐
│ Success/Failure Handling │
│ Log Results │
└────────────┬───────────────────┘
┌────────────┴─────────┐
│ │
Next file? Process Complete
```
## Component Interaction
```
┌─────────────┐
│ main.py │
└──────┬──────┘
│ calls with (filter_audio, interactive_audio)
┌──────────────────────┐
│ process_manager.py │
├──────────────────────┤
│ • Build config │ ◄─── Set "interactive" field
│ • For each file: │ in audio_filter_config
│ └─ run_ffmpeg() │
└──────┬───────────────┘
│ passes audio_filter_config
┌──────────────────────┐
│ encode_engine.py │
├──────────────────────┤
│ • Check "enabled" │ ◄─── Decide which
│ • Check "interactive"│ filtering method
│ • Route to: │ to use
│ ├─ interactive path│
│ └─ automatic path │
└──────┬───────────────┘
│ passes streams
┌──────────────────────┐
│ audio_handler.py │
├──────────────────────┤
│ • Interactive: │
│ prompt_user_...() │◄──── NEW FUNCTION
│ └─ Show & filter │ Shows prompt
│ │ Gets user input
│ • Automatic: │ Returns filtered
│ filter_audio_...() │
│ └─ Logic filter │
└──────────────────────┘
│ returns filtered streams
┌──────────────────────┐
│ encode_engine.py │
├──────────────────────┤
│ • Codec selection │
│ • Build FFmpeg cmd │
│ • Run encoding │
└──────────────────────┘
```
---
This architecture ensures clean separation of concerns:
- **main.py**: CLI interface
- **process_manager.py**: Orchestration & config building
- **encode_engine.py**: FFmpeg command building & execution
- **audio_handler.py**: Audio detection & stream filtering
The interactive prompt is cleanly isolated in `audio_handler.py` and only called when needed.

View File

@ -1,81 +0,0 @@
# Dual Encoder Support - Implementation Complete ✅
## Features Added
The transcoder now supports switching between two video encoders via the `--encoder` CLI option:
### 1. **HEVC NVENC 10-bit** (Default)
- **Command**: `--encoder nvenc` or default (no flag needed)
- **Codec**: `hevc_nvenc`
- **Preset**: `slow` (high quality)
- **Bit Depth**: 10-bit
- **Pixel Format**: `yuv420p10le`
- **Use Case**: Best quality archival format, suitable for Plex compatibility
### 2. **AV1 NVENC 8-bit**
- **Command**: `--encoder av1`
- **Codec**: `av1_nvenc`
- **Preset**: `p7` (high quality)
- **Bit Depth**: 8-bit
- **Pixel Format**: `yuv420p`
- **Use Case**: Maximum file size reduction, modern playback devices
## Usage Examples
```bash
# Default to HEVC NVENC 10-bit with smart resolution scaling
python main.py "C:\Videos\Movies"
# Force AV1 NVENC 8-bit encoding
python main.py "C:\Videos\TV" --encoder av1
# AV1 with explicit resolution
python main.py "C:\Videos\Anime" --encoder av1 --r 1080
# AV1 with CQ mode at specific quality
python main.py "C:\Videos\Low-Res" --encoder av1 --cq 28
# AV1 with bitrate mode
python main.py "C:\Videos\Movies" --encoder av1 --m bitrate
# HEVC (explicit, though it's the default)
python main.py "C:\Videos\TV" --encoder nvenc --cq 26
```
## Configuration
Encoder settings are stored in `config.xml`:
```xml
<encoder default="nvenc">
<av1_nvenc preset="p7" bit_depth="8" pix_fmt="yuv420p" />
<hevc_nvenc preset="slow" bit_depth="10" pix_fmt="yuv420p10le" />
</encoder>
```
The `default="nvenc"` attribute can be changed, but CLI `--encoder` flag always takes precedence.
## Files Modified
1. **config.xml** - Added `<encoder>` section with both encoder configurations
2. **main.py** - Added `--encoder` argument, defaults to "nvenc"
3. **encode_engine.py** - Updated `run_ffmpeg()` to:
- Accept `encoder` parameter
- Dynamically set encoder codec, preset, bit depth, and pixel format
- Display encoder details in logging output
4. **process_manager.py** - Updated to:
- Accept and pass `encoder` parameter through processing pipeline
- Updated both Phase 1 (initial encode) and Phase 2 (bitrate retry) encode calls
## Quality Notes
| Aspect | HEVC NVENC | AV1 NVENC |
|--------|-----------|----------|
| **File Size** | ~80-90% of AV1 | Smallest (baseline) |
| **Quality** | Excellent | Excellent |
| **Preset** | slow (p6) | p7 |
| **Bit Depth** | 10-bit | 8-bit |
| **Compatibility** | Excellent (Plex) | Good (modern devices) |
| **Encoding Speed** | Fast | Fast |
Both encoders use NVIDIA GPU acceleration (NVENC) for fast encoding.

View File

@ -1,280 +0,0 @@
# Interactive Audio Stream Selection - Complete Implementation
## Overview
**COMPLETE** - Interactive audio stream selection feature has been successfully implemented.
Users can now view all available audio streams in each video file and select which ones to keep for encoding, providing fine-grained control over audio track inclusion.
## Features Implemented
### 1. Stream Display ✅
- Shows all audio streams with human-readable format
- Displays: Stream number, channel count, language code, bitrate
- Clear visual separation and organized layout
- Example: `Stream #0: 2ch | Lang: eng | Bitrate: 128kbps`
### 2. User Input ✅
- Accepts comma-separated stream indices: `0,1,3`
- Accepts single stream: `1`
- Accepts blank input (keep all streams)
- Input validation with helpful error messages
- Optional spaces in comma-separated list: `0, 1, 3`
### 3. Filtering ✅
- Removes non-selected streams from encoding
- Preserves original stream indices for FFmpeg mapping
- Logs all selections and removals
- Falls back to keeping all streams on invalid input
### 4. CLI Integration ✅
- New flag: `--interactive` (boolean)
- Works with `--filter-audio` flag
- Can be used independently (auto-enables filtering)
- Integrated into argument parser with help text
### 5. Processing Pipeline ✅
- Called from `run_ffmpeg()` in encode_engine.py
- Executed after stream detection
- Executed before codec selection
- Per-file prompting (allows different selections per video)
### 6. Logging ✅
- Logs user selections: `User selected X audio stream(s): [0, 1, 3]`
- Logs removed streams: `Removed X audio stream(s): [2]`
- Logs invalid input attempts
- Integrated with project's logging system
## File Changes Summary
### main.py
**Added**:
- `--interactive` argument to argparse
- Pass `args.interactive_audio` to `process_folder()`
**Lines Changed**: 2
### core/process_manager.py
**Added**:
- `interactive_audio: bool = False` parameter to function signature
- Logic to set `audio_filter_config["interactive"]` based on CLI args
- Auto-enable filtering if `--interactive` used without `--filter-audio`
**Lines Changed**: ~5
### core/encode_engine.py
**Added**:
- Import `prompt_user_audio_selection`
- Check for `audio_filter_config.get("interactive", False)`
- Route to interactive or automatic filtering accordingly
**Lines Changed**: ~5
### core/audio_handler.py
**Added**:
- `prompt_user_audio_selection()` function (64 lines)
- Comprehensive docstring
- User-friendly output formatting
- Input validation and error handling
- Logging integration
**Lines Changed**: +64 (new function)
## Code Structure
### Function: `prompt_user_audio_selection(streams: list) -> list`
**Location**: `core/audio_handler.py` (line 297)
**Parameters**:
- `streams`: List of (index, channels, bitrate, language, metadata) tuples
**Returns**:
- Filtered list containing only user-selected streams
**Key Features**:
1. Early return if 0-1 streams (no selection needed)
2. Display header with visual formatting
3. Show each stream with index, channels, language, bitrate
4. Prompt for user input with examples
5. Parse comma-separated input
6. Validate stream indices
7. Handle edge cases (empty input, invalid input)
8. Log results to project logger
9. Return filtered streams ready for encoding
**Error Handling**:
- ValueError on unparseable input → keep all
- No valid selections → keep all with warning
- Empty input → keep all (user confirmed)
## Execution Flow
```
User runs:
$ python main.py "C:\Videos" --filter-audio --interactive
main.py parses arguments
- filter_audio = True (from --filter-audio)
- interactive_audio = True (from --interactive)
process_folder() called with both flags
For each video file:
└─ run_ffmpeg() called
└─ get_audio_streams() detects streams
└─ Check audio_filter_config.enabled
└─ True: Apply filtering
└─ Check audio_filter_config.interactive
└─ True: Call prompt_user_audio_selection()
└─ [INTERACTIVE PROMPT APPEARS]
└─ User sees streams and selects
└─ Returns filtered stream list
└─ False: Call filter_audio_streams()
└─ Automatic filtering (keep best English + Commentary)
└─ Process selected streams for encoding
```
## Usage Examples
### Basic Interactive Mode
```bash
python main.py "C:\Videos\Movies" --filter-audio --interactive
```
### Combined with Other Options
```bash
python main.py "C:\Videos\TV" --filter-audio --interactive --cq 28 --r 1080 --language eng
```
### Interactive Without Explicit --filter-audio
```bash
python main.py "C:\Videos\Anime" --interactive
```
(Filtering is auto-enabled with interactive mode)
## Testing Scenarios
### Scenario 1: Multiple Audio Languages
**Input**: Video with English (stereo), English (5.1), Spanish, Commentary
**Expected**: Prompt shows 4 streams, user can select any combination
### Scenario 2: Invalid Selection
**Input**: User types "abc" or non-existent stream number
**Expected**: Tool logs warning, keeps all streams, continues
### Scenario 3: Single Audio Stream
**Input**: Video with only one audio track
**Expected**: Function returns early, no prompt shown
### Scenario 4: Empty Input
**Input**: User presses Enter without typing
**Expected**: All streams kept, confirmation message shown
## Backward Compatibility
✅ **Fully Backward Compatible**
- Existing `--filter-audio` behavior unchanged
- New feature is opt-in via `--interactive` flag
- Default behavior (no interactive) preserved
- No changes to config.xml schema required
- All existing scripts/automation continues to work
## Integration Points
### With Audio Language Tagging
- `--language eng --filter-audio --interactive` works together
- User selects streams, then language metadata applied to all
### With Resolution/CQ Options
- `--filter-audio --interactive --cq 28 --r 1080` fully compatible
- Interactive selection happens first, encoding follows
### With Test Mode
- `--filter-audio --interactive --test` shows interactive prompt on first file
- Useful for testing selections before batch encoding
## Performance Impact
✅ **Minimal Impact**
- Interactive prompt only appears when user explicitly requests it
- No performance overhead when `--interactive` not used
- Per-file prompt adds negligible time (user wait for input)
- No change to FFmpeg encoding performance
## Documentation Provided
1. **INTERACTIVE_AUDIO.md** - User guide with examples
2. **IMPLEMENTATION_NOTES.md** - Technical implementation details
3. **QUICK_REFERENCE.md** - Quick reference guide and FAQ
4. This summary document
## Completion Checklist
✅ Function implementation (prompt_user_audio_selection)
✅ CLI argument (--interactive)
✅ Integration with process_manager
✅ Integration with encode_engine
✅ Input validation
✅ Error handling
✅ Logging integration
✅ Backward compatibility
✅ Documentation
✅ Syntax validation
✅ Code review
## Example Output
When user runs with `--filter-audio --interactive`:
```
================================================================================
🎵 AUDIO STREAM SELECTION
================================================================================
Stream #0: 2ch | Lang: eng | Bitrate: 128kbps
Stream #1: 6ch | Lang: eng | Bitrate: 448kbps
Stream #2: 2ch | Lang: spa | Bitrate: 128kbps
Stream #3: 2ch | Lang: comment | Bitrate: 64kbps
────────────────────────────────────────────────────────────────────────────
Enter stream numbers to keep (comma-separated, e.g.: 1,2 or just 2)
Leave blank to keep all streams
────────────────────────────────────────────────────────────────────────────
➜ Keep streams: 1,3
✅ Keeping 2 stream(s), removing 2 stream(s)
🎬 Running CQ encode: output.mkv
...
```
## Next Steps (Optional Enhancements)
Future improvements could include:
- [ ] Preset buttons for common selections (e.g., "Best Audio", "English Only", "All")
- [ ] Auto-numbering display for clarity
- [ ] Arrow key selection interface (more interactive)
- [ ] Save/load selection templates for batch consistency
- [ ] GUI interface for stream selection
- [ ] Default selection from config for silent/batch operation
---
## Summary
The interactive audio stream selection feature is **complete and ready for use**. Users can now:
1. ✅ See all available audio streams with details
2. ✅ Choose which streams to keep for encoding
3. ✅ Get immediate confirmation of their selection
4. ✅ Have per-file control in batch operations
5. ✅ Maintain automatic fallback if input is invalid
The implementation is clean, well-documented, backward-compatible, and fully integrated into the existing codebase.

View File

@ -1,141 +0,0 @@
# Interactive Audio Stream Selection - Implementation Summary
## Changes Made
### 1. New Function: `prompt_user_audio_selection()` in audio_handler.py
- **Purpose**: Display audio streams and prompt user for selection
- **Input**: List of streams with (index, channels, bitrate, language, metadata)
- **Output**: Filtered list containing only user-selected streams
- **Features**:
- Displays stream info: `Stream #X: YYch | Lang: YYY | Bitrate: XYZkbps`
- Accepts comma-separated input: `1,2,3` or `1` or empty (keep all)
- Validates input and logs selections
- Falls back to keeping all streams on invalid input
### 2. Updated: `run_ffmpeg()` in encode_engine.py
- Now checks `audio_filter_config.get("interactive", False)`
- Routes to interactive prompt if `interactive=True`
- Routes to automatic filtering if `interactive=False`
- Both modes filter streams before codec selection
### 3. Updated: `process_folder()` in process_manager.py
- New parameter: `interactive_audio: bool = False`
- Builds audio_filter_config with both `enabled` and `interactive` fields
- If `--interactive` used without `--filter-audio`, enables both automatically
### 4. Updated: main.py
- New CLI argument: `--interactive`
- Action: `store_true` (binary flag)
- Passed through to `process_folder()`
- Help text: "Interactive mode: show audio streams and let user select which to keep (requires --filter-audio)"
## Usage Examples
### Example 1: Automatic Filtering (Existing)
```bash
python main.py "C:\Videos" --filter-audio
```
- Automatically keeps best English + Commentary
- No user interaction
### Example 2: Interactive Selection (New)
```bash
python main.py "C:\Videos" --filter-audio --interactive
```
- Shows each file's audio streams
- User picks which streams to keep
- Different selections per file allowed
### Example 3: Interactive Without --filter-audio
```bash
python main.py "C:\Videos" --interactive
```
- Same as Example 2 (enables filtering automatically)
- More intuitive UX
## Stream Display Format
When interactive mode runs, user sees:
```
================================================================================
🎵 AUDIO STREAM SELECTION
================================================================================
Stream #0: 2ch | Lang: eng | Bitrate: 128kbps
Stream #1: 6ch | Lang: eng | Bitrate: 448kbps
Stream #2: 2ch | Lang: spa | Bitrate: 128kbps
────────────────────────────────────────────────────────────────────────────
Enter stream numbers to keep (comma-separated, e.g.: 1,2 or just 2)
Leave blank to keep all streams
────────────────────────────────────────────────────────────────────────────
➜ Keep streams:
```
## Logging Output
When user selects streams:
```
✅ Keeping 2 stream(s), removing 1 stream(s)
User selected 2 audio stream(s): [1, 2]
Removed 1 audio stream(s): [0]
```
## Audio Filter Config Structure
**Old (Automatic only)**:
```python
{
"enabled": True/False
}
```
**New (With Interactive)**:
```python
{
"enabled": True/False,
"interactive": True/False
}
```
## Flow Diagram
```
main.py
└─ parse args (--filter-audio, --interactive)
└─ process_folder()
└─ for each file:
└─ run_ffmpeg()
└─ get_audio_streams()
└─ if audio_filter_config.enabled:
├─ if audio_filter_config.interactive:
│ └─ prompt_user_audio_selection() ← NEW
│ └─ [User sees streams and selects]
└─ else:
└─ filter_audio_streams() (automatic)
└─ encode with selected streams
```
## Input Validation
- **Valid**: `1`, `0,1,3`, `2, 3, 5` (spaces OK)
- **Invalid**: `abc`, `1.5`, `1-3` (ranges not supported)
- **On Invalid**: Keep all streams, log warning
## Edge Cases Handled
1. **No streams**: Return original (nothing to filter)
2. **Single stream**: Return as-is (no selection needed)
3. **Invalid stream indices**: Keep all streams
4. **Empty input**: Keep all streams
5. **No valid selections**: Keep all streams (with warning)
## Backward Compatibility
- Existing `--filter-audio` behavior unchanged (automatic mode)
- `--interactive` is optional, defaults to False
- No breaking changes to config.xml structure
- Language tagging (--language) still works alongside audio filtering

View File

@ -1,109 +0,0 @@
# Interactive Audio Stream Selection
## Overview
The conversion tool now supports **interactive audio stream selection**, allowing you to manually choose which audio tracks to keep during encoding rather than relying on automatic filtering.
## Usage
### Enable Interactive Mode
Use both `--filter-audio` and `--interactive` flags together:
```bash
python main.py "C:\path\to\videos" --filter-audio --interactive
```
### What Happens
When encoding each file with multiple audio streams:
1. **Audio Stream Display**
- The tool displays all available audio streams with details:
```
🎵 AUDIO STREAM SELECTION
================================================================================
Stream #0: 2ch | Lang: eng | Bitrate: 128kbps
Stream #1: 6ch | Lang: eng | Bitrate: 448kbps
Stream #2: 2ch | Lang: spa | Bitrate: 128kbps
Stream #3: 2ch | Lang: comment | Bitrate: 64kbps
```
2. **User Prompt**
- You're asked to select which streams to keep:
```
────────────────────────────────────────────────────────────────────────────
Enter stream numbers to keep (comma-separated, e.g.: 1,2 or just 2)
Leave blank to keep all streams
────────────────────────────────────────────────────────────────────────────
➜ Keep streams: 1,3
```
3. **Encoding
**
- Only selected streams are included in the encoded output
- Other streams are removed
- Selection is logged for reference
## Input Format
- **Multiple streams**: `0,1,3` or `0, 1, 3` (spaces optional)
- **Single stream**: `1` or `2`
- **Keep all**: Press Enter without typing anything
## Example Scenarios
### Scenario 1: Keep Main Audio Only
```
Streams:
Stream #0: 2ch (English, 128kbps)
Stream #1: 6ch (English Surround, 448kbps) ← Best quality
Stream #2: 2ch (Spanish, 128kbps)
Input: 1
Result: Only Stream #1 (6ch English Surround) is encoded
```
### Scenario 2: Keep Multiple Languages
```
Streams:
Stream #0: 2ch (English, 128kbps)
Stream #1: 6ch (English Surround, 448kbps)
Stream #2: 2ch (Spanish, 128kbps)
Stream #3: 2ch (Commentary, 64kbps)
Input: 1,2,3
Result: Streams #1, #2, and #3 are encoded (English Surround, Spanish, Commentary)
```
## Comparison with Automatic Filtering
### Automatic Mode (--filter-audio only)
- Keeps: Best English audio + all Commentary tracks
- No user interaction
- Faster batch processing
### Interactive Mode (--filter-audio --interactive)
- Shows all streams and asks user to choose
- Per-file control
- Better for selective archiving/organization
- Useful when automatic filtering doesn't match your preferences
## Logging
All user selections are logged to the conversion log for reference:
```
User selected 2 audio stream(s): [1, 3]
Removed 1 audio stream(s): [2]
```
## Notes
- Interactive mode requires `--filter-audio` to be enabled
- If you use `--interactive` without `--filter-audio`, filtering is automatically enabled
- Invalid input (non-existent stream numbers) falls back to keeping all streams
- Empty input keeps all audio streams unchanged
- The prompt appears for each file being encoded, allowing different selections per file

View File

@ -1,101 +0,0 @@
# Structured Logging with Media Context
## Overview
The conversion system now uses **structured JSON logging** to enable organized analysis and filtering of conversion results by media type, show name, season, and episode.
## Terminal vs Log Output
- **Terminal Output**: Clean, human-readable print statements (VIDEO/AUDIO/PROGRESS sections)
- **Log Output**: Rich structured JSON with full media context for programmatic analysis
## Media Context Fields
Extracted automatically from file path structure:
```python
{
"video_filename": "episode01.mkv",
"media_type": "tv", # "tv", "anime", "movie", or "other"
"show_name": "Breaking Bad",
"season": "01", # Optional (TV/anime only)
"episode": "01" # Optional (TV/anime only)
}
```
## Usage Examples
### Path Structure Recognition
**TV Show**:
```
P:\tv\Breaking Bad\season01\episode01.mkv
→ media_type: "tv", show_name: "Breaking Bad", season: "01", episode: "01"
```
**Anime**:
```
P:\anime\Demon Slayer\season02\e12.mkv
→ media_type: "anime", show_name: "Demon Slayer", season: "02", episode: "12"
```
**Movie**:
```
P:\movies\Inception.mkv
→ media_type: "movie", show_name: "Inception"
```
## Log Output Format
JSON logs contain both the message and media context:
```json
{
"timestamp": "2026-02-22 15:30:45",
"level": "INFO",
"message": "✅ CONVERSION COMPLETE: episode01[EHX].mkv",
"video_filename": "episode01.mkv",
"media_type": "tv",
"show_name": "Breaking Bad",
"season": "01",
"episode": "01",
"method": "CQ",
"original_size_mb": 4096.5,
"output_size_mb": 1843.2,
"reduction_pct": 55.0
}
```
## Filtering Logs Later
You can parse the JSON logs to group by show/season/episode:
```python
import json
# Filter all Breaking Bad conversions
with open("logs/conversion.log") as f:
for line in f:
entry = json.loads(line)
if entry.get("show_name") == "Breaking Bad":
print(f"S{entry['season']}E{entry['episode']}: {entry['reduction_pct']}% reduction")
```
## Current Implementation
**Files Updated**:
- `core/process_manager.py`:
- Added `get_media_context()` function to parse file paths
- Extracts media context once per file processing
- Passes context to all logging calls via `extra={}` parameter
- `core/logger_helper.py`:
- JsonFormatter automatically includes all extra fields in output
- Added `log_event()` helper for consistent structured logging
## Best Practices
1. Always call `get_media_context()` once per file
2. Pass result to all logging calls for that file: `logger.info(msg, extra=media_context)`
3. For additional context: `logger.info(msg, extra={**media_context, "custom_field": value})`
4. Parse logs with JSON reader for reliable data extraction

View File

@ -1,184 +0,0 @@
# AV1 Batch Video Transcoder - Project Structure
## Overview
A modular batch AV1 video transcoding system using NVIDIA's av1_nvenc codec (8-bit yuv420p) with intelligent audio/video processing, subtitle embedding, and optional audio language tagging.
## Recent Changes (Latest Session)
### Removed
- ❌ **Sonarr/Radarr integration** - Removed helper module, cache loading, and config sections (simplified to basic tagging)
- ❌ **Auto-rename functionality** - No longer renames based on Sonarr metadata
- ❌ **Web UI** - Removed `/webui` folder (can be added back if needed)
- ❌ **Rename tool** - Moved to separate `/rename` folder
### Added
- ✅ **Subtitle detection & embedding** - Auto-finds .vtt, .srt, .ass, .ssa, .sub files (including language-prefixed like .en.vtt)
- ✅ **Subtitle cleanup** - Deletes embedded subtitle files after successful encoding
- ✅ **Test mode** (`--test`) - Encodes first file, shows compression ratio, doesn't move files
- ✅ **Optional language tagging** (`--language`) - Only tags audio if explicitly provided (default: no tagging)
- ✅ **Always output MKV** - Changed from using source extension to always outputting .mkv
- ✅ **Improved subtitle matching** - Finds both exact matches (video.vtt) and language-prefixed (video.en.vtt)
### Refactored
- 🔧 **File structure reorganization**: Moved path_manager GUI, rename tool, and cache to separate folders
- 🔧 **Config simplification**: Removed Sonarr/Radarr sections, cleaner general settings
- 🔧 **Suffix handling**: Applied once during encoding, moved directly without re-tagging
- 🔧 **Audio language**: Changed from config-based default to CLI-only optional flag
## Architecture
### Entry Point
- **main.py** - CLI with argparse
- Arguments: `folder`, `--cq`, `--m {cq,bitrate}`, `--r {480,720,1080}`, `--test`, `--language`
- Loads config.xml, initializes logging
- Calls `process_folder()` from process_manager
### Core Modules
#### `core/config_helper.py`
- **`load_config_xml(config_path)`** - Parses XML configuration
- Returns dict with keys:
- `general`: processing_folder, suffix (" - [EHX]"), extensions, reduction_ratio_threshold, subtitles config
- `encode.cq`: CQ values per content type (tv_1080, tv_720, movie_1080, movie_720)
- `encode.fallback`: Bitrate fallback (Phase 2 retry)
- `audio`: Bitrate buckets for stereo/multichannel
- `path_mappings`: Windows ↔ Linux path conversion
#### `core/logger_helper.py`
- Sets up logging to `logs/conversion.log` (INFO+) and console (DEBUG+)
- Separate failure logger for `logs/conversion_failures.log`
- Captures encoding decisions, bitrates, resolutions, timings
#### `core/process_manager.py`
- **`process_folder(folder, cq, transcode_mode, resolution, config, tracker_file, test_mode, audio_language)`**
- Scans folder for video files
- **Per file**: Copy to temp, detect subtitles, analyze streams, encode, move, cleanup
- **Subtitle detection**: Looks for exact match + glob pattern (filename.*.ext)
- **Phase 1 (CQ)**: Try CQ-based encoding, check size threshold
- **Phase 2 (Bitrate)**: Retry failed files with bitrate mode
- **Cleanup**: Delete original + subtitle + temp copies on success
- **`_save_successful_encoding(...)`** - Moves file from temp → original folder
- File already has ` - [EHX]` suffix from temp_output filename
- Deletes original file, subtitle file, and temp copies
- Logs to CSV tracker
#### `core/encode_engine.py`
- **`run_ffmpeg(input_file, output_file, cq, scale_width, scale_height, src_width, src_height, filter_flags, audio_config, method, bitrate_config, subtitle_file, audio_language)`**
- Builds FFmpeg command with av1_nvenc codec (preset p7, pix_fmt yuv420p)
- Per-stream audio codec/bitrate decisions
- Conditional subtitle input mapping (if subtitle_file provided)
- Optional audio language metadata (only if audio_language not None)
- Returns: (orig_size, out_size, reduction_ratio)
#### `core/audio_handler.py`
- **`get_audio_streams(input_file)`** - Detects all audio streams with bitrate info
- **`choose_audio_bitrate(channels, avg_bitrate, audio_config, is_1080_class)`** - Returns (codec, target_bitrate) tuple
- Stereo 1080p: >192k → encode to 192k, ≤192k → copy
- Stereo 720p: >160k → encode to 160k, ≤160k → copy
- Multichannel: Encode to 384k (low) or 448k (medium)
#### `core/video_handler.py`
- **`get_source_resolution(input_file)`** - ffprobe detection
- **`determine_target_resolution(src_width, src_height, explicit_resolution)`** - Smart scaling
- If >1080p → scale to 1080p
- Else → preserve source
- Override with `--r {480,720,1080}`
## Workflow Example
```bash
python main.py "P:\tv\Supernatural\Season 7" --language eng
```
**Processing:**
1. Scan folder for .mkv/.mp4 files
2. For each file:
- Copy to `processing/Supernatural - S07E01 - Pilot.mkv`
- Look for subtitle: `Supernatural - S07E01 - Pilot.en.vtt` ✓ found
- Detect source: 1920x1080 (1080p) ✓
- Get audio streams: [AAC 2ch @ 192k, AC3 6ch @ 448k]
- Determine CQ: tv_1080 → CQ 28
- Build FFmpeg command:
- Video: av1_nvenc (CQ 28)
- Audio 0: Copy AAC (≤192k already good)
- Audio 1: Re-encode AC3 to AAC 6ch @ 448k
- Subtitles: Input subtitle, map as srt stream, language=eng
- Output: `processing/Supernatural - S07E01 - Pilot - [EHX].mkv`
- FFmpeg runs, outputs ~400MB (original 1.2GB)
- Check size: 400/1200 = 33.3% < 75% SUCCESS
- Move: `processing/... - [EHX].mkv``P:\tv\Supernatural\Season 7/... - [EHX].mkv`
- Cleanup: Delete original + subtitle + temp copy
- Log to CSV
**Result:**
- Original files gone
- New `Supernatural - S07E01 - Pilot - [EHX].mkv` (subtitle embedded, audio tagged with language=eng)
## Configuration
### config.xml Key Sections
```xml
<general>
<processing_folder>processing</processing_folder>
<suffix> - [EHX]</suffix>
<extensions>.mkv,.mp4</extensions>
<reduction_ratio_threshold>0.75</reduction_ratio_threshold>
<subtitles>
<enabled>true</enabled>
<extensions>.vtt,.srt,.ass,.ssa,.sub</extensions>
<codec>srt</codec>
</subtitles>
</general>
<encode>
<cq>
<tv_1080>28</tv_1080>
<tv_720>32</tv_720>
<movie_1080>32</movie_1080>
<movie_720>34</movie_720>
</cq>
</encode>
<audio>
<stereo>
<high>192000</high>
<medium>160000</medium>
</stereo>
<multi_channel>
<medium>448000</medium>
<low>384000</low>
</multi_channel>
</audio>
```
## File Movements
```
Original:
P:\tv\Show\Episode.mkv (1.2GB)
P:\tv\Show\Episode.en.vtt
During Encoding:
processing/Episode.mkv (temp copy)
processing/Episode - [EHX].mkv (encoding output)
After Success:
P:\tv\Show\Episode - [EHX].mkv (1.2GB → 400MB)
(original .mkv deleted)
(original .en.vtt deleted)
(temp folder cleaned)
```
## Validation Checklist
- ✅ All core modules import correctly
- ✅ Config loads without Sonarr/Radarr references
- ✅ Subtitle detection finds exact matches + language-prefixed files
- ✅ Audio language tagging only applied with --language flag
- ✅ Output always MKV regardless of source format
- ✅ Suffix applied once (in temp output filename)
- ✅ Subtitle files deleted with original files
- ✅ Test mode shows compression ratio and stops
- ✅ Phase 1 (CQ) and Phase 2 (Bitrate) retry logic works
- ✅ CSV tracking logs all conversions

View File

@ -1,182 +0,0 @@
# Interactive Audio Selection - Quick Reference
## Command Syntax
### Enable Interactive Audio Selection
```bash
python main.py "C:\path\to\videos" --filter-audio --interactive
```
### Other Flags (Optional)
```bash
--filter-audio --interactive --cq 28 --r 1080 --language eng --test
```
## What User Sees
### Per File Prompt (appears for each video)
```
================================================================================
🎵 AUDIO STREAM SELECTION
================================================================================
Stream #0: 2ch | Lang: eng | Bitrate: 128kbps
Stream #1: 6ch | Lang: eng | Bitrate: 448kbps
Stream #2: 2ch | Lang: spa | Bitrate: 128kbps
Stream #3: 2ch | Lang: comment | Bitrate: 64kbps
────────────────────────────────────────────────────────────────────────────
Enter stream numbers to keep (comma-separated, e.g.: 1,2 or just 2)
Leave blank to keep all streams
────────────────────────────────────────────────────────────────────────────
➜ Keep streams:
```
### User Input Examples
| Input | Result |
|-------|--------|
| `1` | Keep Stream #1 (6ch English, 448kbps) |
| `1,3` | Keep Streams #1 and #3 |
| `0,1,2` | Keep Streams #0, #1, and #2 |
| ` ` (blank) | Keep all 4 streams |
### Expected Output
```
✅ Keeping 1 stream(s), removing 3 stream(s)
🎬 Running CQ encode: output.mkv
...
```
## Features
**Per-File Control**: Different selections for each video
**Clear Display**: See channel count, language, bitrate for each stream
**Flexible Input**: Comma-separated numbers, optional spaces
**Safe Defaults**: Invalid input keeps all streams
**Logging**: All selections recorded in conversion log
**Backwards Compatible**: Doesn't break existing workflows
## Common Scenarios
### Movie with Multiple Audio Tracks
```
Stream #0: 2ch English (128kbps)
Stream #1: 6ch English Surround (448kbps) ← Main audio
Stream #2: 2ch Spanish (128kbps)
Stream #3: 2ch Commentary (64kbps)
Input: 1,3
Output: Keep English 5.1 + Commentary
```
### TV Episode with Multiple Languages
```
Stream #0: 6ch English (384kbps)
Stream #1: 6ch Spanish (384kbps)
Stream #2: 2ch Commentary (64kbps)
Input: 0,1,2
Output: Keep all (English, Spanish, Commentary)
```
### File with Only One Audio Track
```
Stream #0: 6ch English (448kbps)
Input: (blank or 0)
Output: Keep the only track
```
## FAQ
**Q: What if I provide an invalid stream number?**
A: The tool keeps all streams and logs a warning.
**Q: Can I specify stream ranges like "0-2"?**
A: No, use comma-separated individual numbers: "0,1,2"
**Q: Do I have to answer the prompt for every file?**
A: Yes, this allows different selections per file. Use automatic --filter-audio mode if you want consistent filtering across all files.
**Q: What happens with invalid input like "abc" or "1.5"?**
A: The tool keeps all streams and logs the invalid input. Then continues to the next file.
**Q: Does --interactive work alone?**
A: Yes! If you use --interactive without --filter-audio, filtering is automatically enabled with interactive mode.
**Q: Can I combine this with --language tagging?**
A: Yes! Use: `--filter-audio --interactive --language eng`
This lets you select streams AND tag them with language metadata.
## Integration Points
### When Called
- After audio stream detection in `run_ffmpeg()`
- Before codec selection and FFmpeg command building
- Only if `audio_filter_config.enabled = True` AND `audio_filter_config.interactive = True`
### Stream Information Provided
- **Index**: Stream number in FFmpeg (0-based)
- **Channels**: 2ch, 6ch, etc.
- **Language**: eng, spa, und (undefined), etc.
- **Bitrate**: Detected bitrate in kbps
### What Gets Removed
- All streams NOT selected by user
- Metadata and descriptors for removed streams
- No re-encoding of audio (codec decisions apply per stream)
## Tips & Tricks
### Keeping Only Surround Audio
Most videos have stereo + surround. To keep only 5.1/6ch:
```
Input: 1 (if Stream #1 is 6ch)
```
### Keeping All Commentary
Commentary tracks are usually indexed separately:
```
Input: 0,2,3 (Stream #0 main + #2 and #3 commentary)
```
### English Only
If you have multiple languages:
```
Input: 0,1 (Stream #0 and #1 English only)
```
## Log Output Examples
**Successful Selection**
```
User selected 2 audio stream(s): [1, 3]
Removed 1 audio stream(s): [0, 2]
```
**Invalid Input**
```
User provided invalid audio selection input
Keeping all audio streams
```
**No Selection**
```
Keeping all audio streams
```
## Troubleshooting
**Issue**: Prompt doesn't appear
- **Solution**: Make sure both --filter-audio AND --interactive are specified
**Issue**: Selection is ignored
- **Solution**: Check log file for errors. Verify stream indices exist.
**Issue**: Want automatic mode back
- **Solution**: Use --filter-audio alone (without --interactive)

942
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,184 +0,0 @@
# AV1 Batch Video Transcoder
A clean, modular batch video transcoding system using NVIDIA's AV1 NVENC codec with intelligent audio and subtitle handling.
## Project Structure
```
conversion_project/
├── main.py - CLI entry point for batch transcoding
├── config.xml - Configuration (encoding settings, audio buckets, etc.)
├── core/ - Core modules
│ ├── config_helper.py - XML configuration loader
│ ├── logger_helper.py - Logging setup
│ ├── process_manager.py - Main transcoding orchestration
│ ├── encode_engine.py - FFmpeg command builder and execution
│ ├── audio_handler.py - Audio stream analysis and bitrate decisions
│ ├── video_handler.py - Video resolution detection and scaling logic
│ └── hardware_helper.py - Hardware detection (GPU/CPU)
├── /rename/ - Separate rename utility (rolling_rename.py)
├── /path_manager/ - GUI path management (kept separate from conversion)
│ ├── gui_path_manager.py
│ ├── transcode.bat
│ ├── paths.txt
│ └── cache/
├── logs/ - Log files and conversion tracker CSV
├── processing/ - Temporary encoding files (cleaned up after move)
└── cache/ (removed) - Folder cache now in /path_manager/cache
```
## Quick Start
### Basic Usage
```bash
# Encode a folder (smart mode: CQ first, bitrate fallback if size exceeds 75%)
python main.py "P:\tv\Show Name"
# Force CQ mode with specific quality
python main.py "P:\movies\Movie" --cq 30
# Force Bitrate mode
python main.py "P:\tv\Show" --m bitrate
# Explicit resolution
python main.py "P:\movies\Movie" --r 1080
# Test mode: encode first file only, show compression ratio, don't move files
python main.py "P:\tv\Show" --test
# Optional: tag audio streams with language code
python main.py "P:\tv\Show" --language eng
```
## Features
- **Hardware Encoding**: NVIDIA av1_nvenc (8-bit yuv420p, preset p7)
- **Smart Audio**: Analyzes streams, re-encodes excessive bitrate, preserves good quality
- **Smart Video**: Detects source resolution, scales 4K→1080p, preserves lower resolutions
- **Subtitle Detection**: Auto-finds and embeds subtitles (vtt, srt, ass, ssa, sub)
- Supports language-prefixed files: `movie.en.vtt`, `movie.eng.vtt`
- Cleans up subtitle files after embedding
- **Two-Phase Encoding** (smart mode):
- Phase 1: Try CQ mode for quality
- Phase 2: Retry failed files with Bitrate mode
- **File Tagging**: Encodes output with ` - [EHX]` suffix
- **CSV Tracking**: Detailed conversion log with compression ratios
- **Automatic Cleanup**: Deletes originals + subtitles after successful move
## Configuration
Edit `config.xml` to customize:
- **CQ Values**: Per content type (tv_1080, tv_720, movie_1080, movie_720)
- **Audio Buckets**: Bitrate targets for stereo/multichannel
- **Fallback Bitrates**: Used in Phase 2 bitrate retry
- **Subtitle Settings**: Extensions to detect, codec for embedding
- **Path Mappings**: Windows ↔ Linux path conversion (optional)
## Encoding Process (Per File)
1. **Detect subtitles**: Looks for matching `.en.vtt`, `.srt`, etc.
2. **Analyze source**: Resolution, audio streams, bitrates
3. **FFmpeg encode**:
- Video: AV1 NVENC (8-bit yuv420p)
- Audio: Per-stream decisions (copy or re-encode)
- Subtitles: Embedded as SRT (if found)
4. **Size check**: Compare output vs original (default 75% threshold)
5. **Move file**: From temp folder → original location with `- [EHX]` suffix
6. **Cleanup**: Delete original file + subtitle file
## Audio Encoding Logic
```
Stereo audio?
├─ YES + 1080p: [>192kbps] ENCODE to 192k AAC, [≤192k] COPY
├─ YES + 720p: [>160kbps] ENCODE to 160k AAC, [≤160k] COPY
└─ NO (Multichannel): ENCODE to 384k/448k AAC (5.1)
```
## Removed Features
- ❌ Sonarr/Radarr integration (was complex, removed for simplicity)
- ❌ Auto-rename based on Sonarr metadata
- ❌ Web UI (kept separate if needed in future)
- ❌ Rename functionality (moved to `/rename` folder)
## Advanced Options
### Test Mode
Encodes first file only, shows compression ratio, leaves file in temp folder:
```bash
python main.py "P:\tv\Show" --test
```
Useful for: Testing CQ values, checking quality before batch conversion.
### Language Tagging (Optional)
Only tags audio if explicitly provided:
```bash
python main.py "P:\tv\Show" --language eng
```
Without `--language` flag, original audio metadata is preserved.
### Resolution Override
Force specific output resolution:
```bash
python main.py "P:\movies" --r 720 # Force 720p
python main.py "P:\tv" --r 1080 # Force 1080p
```
## Output Examples
**Input File:**
```
SupernaturalS07E21.mkv (size: 1.5GB)
SupernaturalS07E21.en.vtt (subtitle)
```
**Output:**
```
SupernaturalS07E21 - [EHX].mkv (size: 450MB, subtitle embedded)
(original files deleted)
```
## Troubleshooting
### Wrong Bitrate
Check CQ values in config.xml or use `--cq` override:
```bash
python main.py "P:\tv\Show" --cq 31
```
### Subtitles Not Embedding
- Verify file is named correctly: `filename.en.vtt` or `filename.vtt`
- Check `config.xml` has subtitles enabled and extensions listed
- Check logs for "Found subtitle" message
### Files Not Moving
Check if reduction ratio threshold (default 0.75) is exceeded:
```bash
python main.py "P:\tv\Show" --test # Check ratio in Phase 1
```
If ratio is high, lower CQ value or use bitrate mode.
## Logs
- `logs/conversion.log`: Detailed encoding info, errors, decisions
- `logs/conversion_tracker.csv`: Summary table of all conversions
- `logs/conversion_failures.log`: Failed file tracking

View File

@ -11,6 +11,10 @@
<!-- File suffix added to encoded outputs --> <!-- File suffix added to encoded outputs -->
<suffix> - [EHX]</suffix> <suffix> - [EHX]</suffix>
<!-- Optional title suffix inserted before main suffix (e.g., quality or version info) -->
<!-- Leave empty or remove to disable. Example: " 1080p" results in "filename 1080p - [EHX].mkv" -->
<title_suffix></title_suffix>
<!-- Allowed input extensions --> <!-- Allowed input extensions -->
<extensions>.mkv,.mp4</extensions> <extensions>.mkv,.mp4</extensions>
@ -23,8 +27,9 @@
<!-- Subtitle settings --> <!-- Subtitle settings -->
<subtitles> <subtitles>
<enabled>true</enabled> <enabled>true</enabled>
<extensions>.vtt,.srt,.ass,.ssa,.sub</extensions> <extensions>.vtt,.srt,.ass,.ssa,.sub,.mov</extensions>
<codec>srt</codec> <codec>srt</codec>
<!-- Note: mov_text (embedded in MP4/MOV) will be automatically converted to SRT -->
</subtitles> </subtitles>
<!-- Audio track filtering: keep only best English audio + Commentary --> <!-- Audio track filtering: keep only best English audio + Commentary -->
@ -36,15 +41,24 @@
<!-- Audio language tag --> <!-- Audio language tag -->
<audio_language>eng</audio_language> <audio_language>eng</audio_language>
<!-- Default language for undefined (und) audio tracks -->
<!-- When an audio track has no language tag (und), it will be replaced with this language -->
<!-- Set to desired ISO 639-2 code (eng, spa, fra, deu, etc.). Set to 'und' to disable replacement -->
<default_language>eng</default_language>
<!-- Replace undefined language tracks with default language -->
<!-- When true and audio has 'und' language tag, it will be replaced with default_language -->
<replace_undefined_language>true</replace_undefined_language>
</general> </general>
<!-- ============================= <!-- =============================
PATH MAPPINGS (Windows → Linux) PATH MAPPINGS (Windows to Linux)
============================= --> ============================= -->
<path_mappings> <path_mappings>
<map from="P:\tv" to="/mnt/plex/tv" /> <map from="P:\\tv" to="/mnt/plex/tv" />
<map from="P:\anime" to="/mnt/plex/anime" /> <map from="P:\\anime" to="/mnt/plex/anime" />
<map from="P:\movies" to="/mnt/plex/movies" /> <map from="P:\\movies" to="/mnt/plex/movies" />
</path_mappings> </path_mappings>
<!-- ============================= <!-- =============================
@ -58,6 +72,7 @@
<tv_720>30</tv_720> <tv_720>30</tv_720>
<anime_1080>32</anime_1080> <anime_1080>32</anime_1080>
<anime_720>30</anime_720> <anime_720>30</anime_720>
<movie_2160>29</movie_2160>
<movie_1080>32</movie_1080> <movie_1080>32</movie_1080>
<movie_720>30</movie_720> <movie_720>30</movie_720>
</av1> </av1>
@ -66,6 +81,7 @@
<tv_720>26</tv_720> <tv_720>26</tv_720>
<anime_1080>28</anime_1080> <anime_1080>28</anime_1080>
<anime_720>26</anime_720> <anime_720>26</anime_720>
<movie_2160>25</movie_2160>
<movie_1080>28</movie_1080> <movie_1080>28</movie_1080>
<movie_720>26</movie_720> <movie_720>26</movie_720>
</hevc> </hevc>
@ -101,6 +117,7 @@
<multi_channel> <multi_channel>
<low>384000</low> <low>384000</low>
<medium>448000</medium> <medium>448000</medium>
<high>640000</high>
</multi_channel> </multi_channel>
</audio> </audio>

View File

@ -1907,3 +1907,943 @@ tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E22 - Monkey (
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E01 - Zoo (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.49,730.19,86.0,1920x1080,1920x1080,1,28,CQ tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E01 - Zoo (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.49,730.19,86.0,1920x1080,1920x1080,1,28,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E02 - Humilithon (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.38,719.01,84.7,1920x1080,1920x1080,1,28,CQ tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E02 - Humilithon (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.38,719.01,84.7,1920x1080,1920x1080,1,28,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E03 - Family Reunion (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.79,713.97,84.0,1920x1080,1920x1080,1,28,CQ tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E03 - Family Reunion (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.79,713.97,84.0,1920x1080,1920x1080,1,28,CQ
movie,N/A,The.Hammer.2023.1080p.WEBRip.x264.AAC-LAMA - [EHX].mkv,1530.75,904.44,59.1,1920x1080,1280x720,1,30,CQ
movie,N/A,Sunshine (2007) h264 DTS-HD MA 5.1 Bluray-1080p Radarr - [EHX].mkv,28789.49,1357.08,4.7,1920x1080,1280x720,2,30,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E01 - Traffic Jam (2) (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,863.19,522.61,60.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E01 - Pilot (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,748.56,405.87,54.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E02 - Red Dress (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,720.88,376.75,52.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E03 - Home Alone 4 (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,680.96,358.58,52.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E04 - Shame (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,625.17,324.82,52.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E05 - Malcolm Babysits (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,675.54,350.61,51.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E06 - Sleepover (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,593.74,292.16,49.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E07 - Francis Escapes (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,759.32,410.03,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E08 - Krelboyne Picnic (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,692.2,383.74,55.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E09 - Lois vs. Evil (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,707.9,387.19,54.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E10 - Stock Car Races (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,827.53,460.3,55.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E11 - Funeral (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,640.42,326.92,51.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E12 - Cheerleader (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,706.16,374.54,53.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E13 - Rollerskates (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,663.27,351.02,52.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E14 - The Bots and the Bees (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,684.2,369.44,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E15 - Smunday (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,689.08,368.05,53.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S01E16 - Water Park (1) (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,754.21,420.33,55.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E02 - Halloween Approximately (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,629.67,325.45,51.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E03 - Lois's Birthday (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,678.31,369.15,54.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E04 - Dinner Out (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,693.15,367.86,53.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E05 - Casino (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,713.62,389.07,54.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E06 - Convention (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,654.11,339.65,51.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E07 - Robbery (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,574.79,280.7,48.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E08 - Therapy (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,628.39,329.75,52.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E09 - High School Play (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,618.99,335.21,54.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E10 - The Bully (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,624.12,336.79,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E11 - Old Mrs. Old (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,562.62,294.11,52.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E12 - Krelboyne Girl (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,618.82,321.91,52.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E13 - New Neighbors (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,629.86,341.29,54.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E14 - Hal Quits (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,545.75,288.92,52.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E15 - The Grandparents (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,518.2,281.97,54.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E16 - Traffic Ticket (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,550.93,293.61,53.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E17 - Surgery (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,590.2,300.67,50.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E18 - Reese Cooks (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,618.58,320.68,51.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E19 - Tutoring Reese (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,562.84,296.28,52.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E20 - Bowling (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,618.56,320.6,51.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E21 - Malcolm vs. Reese (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,610.79,312.03,51.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E22 - Mini-Bike (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,657.95,340.24,51.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E23 - Carnival (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,510.18,253.56,49.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E24 - Evacuation (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,649.77,348.49,53.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S02E25 - Flashback (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,715.42,396.22,55.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E01 - Houseboat (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,602.38,332.04,55.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E02 - Emancipation (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,576.08,316.45,54.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E03 - Book Club (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,487.55,241.38,49.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E04 - Malcolm's Girlfriend (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,561.32,304.77,54.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E05 - Charity (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,491.01,257.9,52.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E06 - Health Scare (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,499.26,259.33,51.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E07 - Christmas (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,494.53,253.3,51.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E08 - Poker (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,534.68,274.08,51.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E09 - Reese's Job (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,554.92,290.52,52.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E10 - Lois's Makeover (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,588.49,319.81,54.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E11 - Company Picnic (Part 1) (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,668.58,369.02,55.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E12 - Company Picnic (Part 2) (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,772.78,441.79,57.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E13 - Reese Drives (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,527.77,280.6,53.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E14 - Cynthia's Back (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,579.04,303.41,52.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E15 - Hal's Birthday (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,583.03,303.55,52.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E16 - Hal Coaches (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,654.13,361.25,55.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E17 - Dewey's Dog (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,564.4,288.87,51.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E18 - Poker #2 (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,549.25,276.83,50.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E19 - Clip Show (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,629.34,332.62,52.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E20 - Jury Duty (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,531.74,281.39,52.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E21 - Cliques (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,612.59,328.25,53.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S03E22 - Monkey (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,579.38,304.31,52.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E01 - Zoo (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,730.19,409.9,56.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E02 - Humilithon (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,719.01,405.53,56.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E03 - Family Reunion (1080p AMZN WEB-DL x265 Silence) - [EHX] - [EHX].mkv,713.97,393.1,55.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E04 - Stupid Girl (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.33,370.05,43.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E05 - Forwards Backwards (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.5,419.2,49.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E06 - Forbidden Girlfriend (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.41,442.33,52.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E07 - Malcolm Holds His Tongue (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.2,412.83,48.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E08 - Boys at Ranch (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.09,419.41,49.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E09 - Grandma Sues (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,828.26,370.89,44.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E10 - If Boys Were Girls (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.5,480.13,56.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E11 - Long Drive (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.4,388.5,45.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E12 - Kicked Out (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.25,396.88,46.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E13 - Stereo Store (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.96,396.4,46.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E14 - Hal's Friend (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.21,411.67,48.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E15 - Garage Sale (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.1,472.18,55.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E16 - Academic Octathalon (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.59,395.22,46.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E17 - Clip Show #2 (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,850.03,408.64,48.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E18 - Reese's Party (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.89,439.86,51.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E19 - Future Malcolm (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.78,458.76,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E20 - Baby (Part 1) (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,872.55,455.74,52.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E21 - Baby (Part 2) (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,854.83,444.28,52.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S04E22 - Day Care (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,831.66,416.73,50.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E01 - Vegas (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,868.62,354.63,40.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E02 - Watching the Baby (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.1,414.62,48.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E03 - Goodbye Kitty (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.63,400.98,47.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E04 - Thanksgiving (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,833.75,386.56,46.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E05 - Malcolm Films Reese (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,839.41,376.47,44.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E06 - Malcolm's Job (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,833.26,377.37,45.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E07 - Christmas Trees (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,840.01,416.36,49.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E08 - Block Party (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.87,453.74,53.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E09 - Dirty Magazine (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.42,380.96,44.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E10 - Hot Tub (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.41,364.77,42.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E11 - Ida's Boyfriend (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,847.57,361.04,42.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E12 - Softball (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.74,388.64,45.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E13 - Lois's Sister (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.54,298.99,35.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E14 - Malcolm Dates a Family (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.74,312.34,36.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E15 - Reese's Apartment (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.63,301.67,35.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E16 - Malcolm Visits College (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.57,369.89,43.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E17 - Polly in the Middle (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.5,326.39,38.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E18 - Dewey's Special Class (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.97,376.47,44.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E19 - Experiment (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,841.67,319.57,38.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E20 - Victor's Other Family (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.32,319.92,37.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E21 - Reese Joins The Army (Part 1) (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.21,343.82,40.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S05E22 - Reese Joins The Army (Part 2) (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.65,306.27,36.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E01 - Reese Comes Home (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,836.39,427.95,51.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E02 - Buseys Run Away (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.86,432.29,51.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E03 - Standee (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.96,401.03,47.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E04 - Pearl Harbor (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.24,399.72,47.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E05 - Kitty's Back (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,864.36,392.81,45.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E06 - Hal's Christmas Gift (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.08,380.69,44.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E07 - Hal Sleepwalks (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.27,438.36,51.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E08 - Lois Battles Jamie (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,843.84,394.17,46.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E09 - Malcolm's Car (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,844.34,456.21,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E10 - Billboard (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,846.17,399.84,47.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E11 - Dewey's Opera (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,863.55,404.91,46.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E12 - Living Will (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.66,446.13,52.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E13 - Tiki Lounge (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,844.2,416.31,49.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E14 - Ida Loses A Leg (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,846.43,473.89,56.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E15 - Chad's Sleepover (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,844.62,437.22,51.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E16 - No Motorcycles (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,844.75,464.56,55.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E17 - Butterflies (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,840.89,455.39,54.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E18 - Ida's Dance (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.92,468.57,55.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E19 - Motivational Seminar (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,844.28,392.11,46.4,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E20 - Stilts (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,878.48,471.14,53.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E21 - Buseys Take a Hostage (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.88,441.71,52.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S06E22 - Mrs. Tri-County (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,864.43,462.63,53.5,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E01 - Burning Man (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.52,463.46,54.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E02 - Health Insurance (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,832.22,454.45,54.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E03 - Reese vs. Stevie (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,850.6,394.2,46.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E04 - Halloween (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,780.9,367.72,47.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E05 - Jessica Stays Over (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,847.74,432.36,51.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E06 - Secret Boyfriend (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.5,448.82,52.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E07 - Blackout (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,868.1,442.94,51.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E08 - Army Buddy (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.33,450.79,53.1,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E09 - Malcolm Defends Reese (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.69,443.76,52.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E10 - Malcolm's Money (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,845.08,469.49,55.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E11 - Bride of Ida (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,867.96,465.72,53.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E12 - College Recruiters (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.03,451.83,53.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E13 - Mono (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,850.37,459.03,54.0,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E14 - Hal Grieves (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,868.47,440.91,50.8,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E15 - A.A. (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,846.41,453.65,53.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E16 - Lois Strikes Back (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.08,437.46,51.6,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E17 - Hal's Dentist (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,828.0,432.91,52.3,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E18 - Bomb Shelter (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,850.34,490.52,57.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E19 - Stevie in the Hospital (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,850.1,483.45,56.9,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E20 - Cattle Court (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,848.89,464.64,54.7,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E21 - Morp (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,849.52,460.27,54.2,1920x1080,1280x720,1,26,CQ
tv,Malcolm in the Middle (2000),Malcolm in the Middle (2000) - S07E22 - Graduation (1080p AMZN WEB-DL x265 Silence) - [EHX].mkv,871.17,467.92,53.7,1920x1080,1280x720,1,26,CQ
movie,N/A,How to Make a Killing (2026) x265 EAC3 Atmos 5.1 WEBDL-1080p Ghost - [EHX].mkv,4169.36,1915.96,46.0,1920x800,1920x800,1,28,CQ
movie,N/A,The Shadow's Edge (2025) (1080p BluRay x265 SAMPA - [EHX].mkv,6747.8,2284.6,33.9,1920x804,1920x804,2,28,CQ
movie,N/A,Gallery.mkv,30.08,27.1,90.1,1920x1080,1920x1080,1,28,CQ
movie,N/A,Menu.mkv,7.67,6.4,83.4,1920x894,1920x894,1,28,CQ
movie,N/A,Trailer 2.mkv,29.02,27.3,94.1,1920x904,1920x904,1,28,CQ
movie,N/A,Trailer 3.mkv,35.52,32.77,92.3,1920x904,1920x904,1,28,CQ
movie,N/A,Trailer 4.mkv,64.25,45.06,70.1,1920x802,1920x802,1,28,CQ
movie,N/A,The Housemaid (2025) x265 EAC3 Atmos 8.0 Bluray-1080p Silence - [EHX].mkv,8112.35,1679.09,20.7,1920x800,1280x720,4,26,CQ
movie,N/A,Avatar - Fire and Ash (2025) x265 EAC3 Atmos 5.1 WEBDL-1080p Silence - [EHX].mkv,10010.8,6008.06,60.0,1920x1038,1920x1038,1,28,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E01 - Tojima Wants to Be a Kamen Rider x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1546.04,338.2,21.9,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E02 - I Am Tackle! x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1540.03,366.14,23.8,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E03 - I Love The Moment When Hate Turns To Love x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1537.81,346.86,22.6,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E04 - Who is the Strongest Kamen Rider x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1536.87,392.26,25.5,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E05 - Let Me Be V3 Too x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1541.16,425.49,27.6,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E05 - Let Me Be V3 Too x265 EAC3 WEBRip-1080p EMBER - [EHX].mkv,394.18,329.98,83.7,1920x1080,1920x1080,1,28,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E06 - Order Some Snacks x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1536.48,333.42,21.7,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E06 - Order Some Snacks x265 AAC WEBRip-1080p Erai-raws - [EHX].mkv,631.35,258.07,40.9,1920x1080,1920x1080,1,28,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E07 - Please Make Me a Part of Shocker x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1540.78,311.7,20.2,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E08 - What's a Kamen Rider Do When A Dangerous Enemy Appears x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1538.49,319.95,20.8,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E09 - Show Me Your Kamen Rider x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1539.78,432.1,28.1,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E10 - Risk Your Life x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1540.97,437.65,28.4,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E11 - Tackle is the Strongest x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1533.26,400.28,26.1,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E12 - I'll Take All You Riders On x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1537.32,337.51,22.0,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,"Tojima Wants to Be a Kamen Rider - S01E13 - I Will Fight, and Die, Against Shocker x264 AAC WEBDL-1080p VARYG - [EHX].mkv",1539.36,308.25,20.0,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E14 - I Want to Learn More About Humans x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1537.33,324.4,21.1,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,"Tojima Wants to Be a Kamen Rider - S01E15 - The Masked Idol, Heavy Chop x264 AAC WEBDL-1080p VARYG - [EHX].mkv",1542.42,363.47,23.6,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E16 - An Imposter Can't Beat the Real Deal x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1539.75,345.85,22.5,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E17 - Everyone In The World Will Join Shocker x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1533.98,347.43,22.6,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E18 - I'll Fight Shocker Too h264 EAC3 WEBDL-1080p VARYG - [EHX].mkv,913.78,357.07,39.1,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E19 - It'd Be an Honor to Die as a Rider x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1541.74,376.02,24.4,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E20 - I Was Craving a Battle With Shocker x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1539.51,319.82,20.8,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E21 - Becoming the Ultimate Monster x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1543.04,337.91,21.9,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E22 - Shocker Is on the Move x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1536.12,355.91,23.2,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,"Tojima Wants to Be a Kamen Rider - S01E23 - Let's Do This, Shocker! x264 AAC WEBDL-1080p VARYG - [EHX].mkv",1541.06,391.05,25.4,1920x1080,1920x1080,2,32,CQ
anime,Tojima Tanzaburo Wants to Be a Kamen Rider,Tojima Wants to Be a Kamen Rider - S01E24 - I Wouldn't Mind Dying Today x264 AAC WEBDL-1080p VARYG - [EHX].mkv,1539.7,431.3,28.0,1920x1080,1920x1080,2,32,CQ
movie,N/A,Doom (2005) Unrated x265 AAC 5.1 Bluray-1080p Tigole - [EHX].mkv,5768.6,1524.44,26.4,1920x816,1920x816,1,28,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S01E01 - Episode 1 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2441.61,542.45,22.2,1920x960,1280x720,1,26,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S01E02 - Episode 2 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2469.07,529.25,21.4,1920x960,1280x720,1,26,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S01E03 - Episode 3 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2498.13,515.15,20.6,1920x960,1280x720,1,26,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S02E01 - Episode 1 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2749.37,653.99,23.8,1920x1080,1280x720,1,26,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S02E02 - Episode 2 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2748.79,560.6,20.4,1920x1080,1280x720,1,26,CQ
tv,Karen Pirie (2022),Karen Pirie (2022) - S02E03 - Episode 3 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2767.03,711.31,25.7,1920x1080,1280x720,1,26,CQ
tv,Euphoria,Euphoria (2019) - S01E01 - Pilot (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1876.52,666.58,35.5,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E02 - Stuntin' Like My Daddy (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2154.31,828.19,38.4,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E03 - Made You Look (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2034.93,780.81,38.4,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E04 - Shook Ones Pt. II (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1985.95,765.04,38.5,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E05 - '03 Bonnie and Clyde (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1901.43,599.0,31.5,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E06 - The Next Episode (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1814.6,604.85,33.3,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E07 - The Trials and Tribulations of Trying to Pee While Depressed (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2147.61,751.78,35.0,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S01E08 - And Salt the Earth Behind You (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2307.9,817.98,35.4,1920x1080,1920x1080,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E01 - Trying to Get to Heaven Before They Close the Door (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2133.03,1471.94,69.0,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E02 - Out of Touch (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1987.03,1165.79,58.7,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E03 - Ruminations Big and Little Bullys (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2089.57,1381.63,66.1,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,"Euphoria (2019) - S02E04 - You Who Cannot See, Think of Those Who Can (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv",2160.77,1153.59,53.4,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E05 - Stand Still Like the Hummingbird (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,1883.31,1176.04,62.4,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E06 - A Thousand Little Trees of Blood (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2092.44,1355.37,64.8,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,Euphoria (2019) - S02E07 - The Theater and Its Double (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv,2046.74,1185.46,57.9,1920x1040,1920x1040,1,28,CQ
tv,Euphoria,"Euphoria (2019) - S02E08 - All My Life, My Heart Has Yearned for a Thing I Cannot Name (1080p AMZN WEB-DL x265 t3nzin) - [EHX].mkv",2149.38,1445.91,67.3,1920x1040,1920x1040,1,28,CQ
movie,N/A,Unknown (2011) (1080p BluRay x265 10bit Tigole) - [EHX].mkv,4300.35,1299.6,30.2,1920x800,1280x720,1,26,CQ
movie,N/A,Ferris Bueller's Day Off (1986) (1080p BluRay x265 r00t) - [EHX].mkv,5225.63,2750.29,52.6,1920x816,1920x816,3,28,CQ
movie,N/A,Getting the Class Together - The Cast of Ferris Buellers Day Off.mkv,284.54,188.0,66.1,720x480,720x480,1,26,CQ
movie,N/A,The Making of Ferris Bueller's Day Off.mkv,159.01,115.32,72.5,720x480,720x480,1,26,CQ
movie,N/A,The World According to Ben Stein.mkv,111.41,60.3,54.1,720x480,720x480,1,26,CQ
movie,N/A,Vintage Ferris Bueller - The Lost Tapes.mkv,105.03,76.72,73.0,720x480,720x480,1,26,CQ
movie,N/A,Who is Ferris Bueller.mkv,94.64,69.8,73.8,720x480,720x480,1,26,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E01 - 3AM x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1390.65,597.58,43.0,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E02 - Two Dead Men x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1637.5,713.87,43.6,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E03 - Kandahar x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1243.54,578.01,46.5,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E04 - Resupply x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1096.16,506.82,46.2,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E05 - Gunner x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1894.5,792.41,41.8,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E06 - The Judas Goat x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1471.89,577.72,39.3,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E07 - Crosshairs x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1141.14,494.77,43.4,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E08 - Cold Steel x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1361.55,581.97,42.7,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E09 - Front Toward Enemy x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1559.76,653.45,41.9,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E10 - Virtue of the Vicious x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1317.87,570.2,43.3,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E11 - Danger Close x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1218.59,561.95,46.1,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E12 - Home x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1404.58,616.96,43.9,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S01E13 - Memento Mori x265 AC3 WEBDL-1080p Vyndros - [EHX].mkv,1519.88,775.92,51.1,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E01 - Roadhouse Blues x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1039.87,568.95,54.7,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E02 - Fight or Flight x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1013.43,459.7,45.4,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E03 - Trouble the Water x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,889.57,483.43,54.3,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E04 - Scar Tissue x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1203.55,597.04,49.6,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E05 - One-Eyed Jacks x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1029.48,474.43,46.1,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E06 - Nakazat x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1134.52,571.64,50.4,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E07 - One Bad Day x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,910.02,475.39,52.2,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E08 - My Brother's Keeper x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1000.91,514.32,51.4,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E09 - Flustercluck x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1307.68,562.91,43.0,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E10 - The Dark Hearts of Men x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,942.91,447.9,47.5,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E11 - The Abyss x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1228.77,549.33,44.7,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E12 - Collision Course x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1156.6,595.24,51.5,1920x1080,1920x1080,1,28,CQ
tv,Marvel's The Punisher (2017),Marvel's The Punisher - S02E13 - The Whirlwind x265 EAC3 Atmos WEBDL-1080p Vyndros - [EHX].mkv,1127.57,493.39,43.8,1920x1080,1920x1080,1,28,CQ
tv,Spartacus,Spartacus - S01E01 - The Red Serpent x265 AAC Bluray-1080p Silence - [EHX].mkv,2172.8,882.35,40.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E02 - Sacramentum Gladiatorum x265 AAC Bluray-1080p Silence - [EHX].mkv,2085.44,767.44,36.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E03 - Legends x265 AAC Bluray-1080p Silence - [EHX].mkv,2140.54,799.18,37.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S01E04 - The Thing in the Pit x265 AAC Bluray-1080p Silence - [EHX].mkv,1929.66,748.01,38.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E05 - Shadow Games x265 AAC Bluray-1080p Silence - [EHX].mkv,2166.87,756.8,34.9,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E06 - Delicate Things x265 AAC Bluray-1080p Silence - [EHX].mkv,2169.87,780.62,36.0,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E07 - Great and Unfortunate Things x265 AAC Bluray-1080p Silence - [EHX].mkv,1966.65,671.34,34.1,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S01E08 - Mark of the Brotherhood x265 AAC Bluray-1080p Silence - [EHX].mkv,1971.43,673.21,34.1,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S01E09 - Whore x265 AAC Bluray-1080p Silence - [EHX].mkv,1990.39,701.91,35.3,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E10 - Party Favors x265 AAC Bluray-1080p Silence - [EHX].mkv,2047.89,789.49,38.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E11 - Old Wounds x265 AAC Bluray-1080p Silence - [EHX].mkv,2005.96,792.88,39.5,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S01E12 - Revelations x265 AAC Bluray-1080p Silence - [EHX].mkv,2188.12,761.93,34.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S01E13 - Kill Them All x265 AAC Bluray-1080p Silence - [EHX].mkv,2141.36,749.32,35.0,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E01 - Fugitivus x265 AAC Bluray-1080p Silence - [EHX].mkv,2228.46,730.01,32.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E02 - A Place in This World x265 AAC Bluray-1080p Silence - [EHX].mkv,2066.62,678.84,32.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E03 - The Greater Good x265 AAC Bluray-1080p Silence - [EHX].mkv,2087.81,762.8,36.5,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E04 - Empty Hands x265 AAC Bluray-1080p Silence - [EHX].mkv,2353.2,879.24,37.4,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E05 - Libertus x265 AAC Bluray-1080p Silence - [EHX].mkv,2202.52,836.49,38.0,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E06 - Chosen Path x265 AAC Bluray-1080p Silence - [EHX].mkv,2214.16,723.63,32.7,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E07 - Sacramentum x265 AAC Bluray-1080p Silence - [EHX].mkv,2235.69,706.52,31.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S02E08 - Balance x265 AAC Bluray-1080p Silence - [EHX].mkv,2205.22,696.16,31.6,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S02E09 - Monsters x265 AAC Bluray-1080p Silence - [EHX].mkv,2198.19,764.51,34.8,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Spartacus - S02E10 - Wrath of the Gods x265 AAC Bluray-1080p Silence - [EHX].mkv,2389.52,731.37,30.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E01 - Enemies of Rome x265 AAC Bluray-1080p Silence - [EHX].mkv,2034.53,748.9,36.8,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E02 - Wolves at the Gate x265 AAC Bluray-1080p Silence - [EHX].mkv,2139.02,781.89,36.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E03 - Men of Honor x265 AAC Bluray-1080p Silence - [EHX].mkv,2321.19,821.79,35.4,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E04 - Decimation x265 AAC Bluray-1080p Silence - [EHX].mkv,2246.65,784.12,34.9,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E05 - Blood Brothers x265 AAC Bluray-1080p Silence - [EHX].mkv,2149.93,809.26,37.6,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E06 - Spoils of War x265 AAC Bluray-1080p Silence - [EHX].mkv,2270.85,821.72,36.2,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E07 - Mors Indecepta x265 AAC Bluray-1080p Silence - [EHX].mkv,2181.67,898.73,41.2,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E08 - Separate Paths x265 AAC Bluray-1080p Silence - [EHX].mkv,2211.42,876.34,39.6,1920x1080,1280x720,3,26,CQ
tv,Spartacus,Spartacus - S03E09 - The Dead and the Dying x265 AAC Bluray-1080p Silence - [EHX].mkv,2395.15,916.75,38.3,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Spartacus - S03E10 - Victory x265 AAC Bluray-1080p Silence - [EHX].mkv,2402.18,1010.42,42.1,1920x1080,1280x720,2,26,CQ
tv,Spartacus,Andy Gets Plastered.mkv,88.32,57.64,65.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Battle Royale.mkv,212.92,119.12,55.9,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Blood and Sand - Behind-the-Scenes.mkv,308.32,205.57,66.7,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Exposing Your Ludus.mkv,155.33,109.09,70.2,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Gladiator Boot Camp.mkv,129.52,85.85,66.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Grime & Punishment - The Hole.mkv,232.35,121.23,52.2,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Legend Re-Imagined.mkv,91.14,55.85,61.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,"Oh, Those Randy Romans.mkv",121.2,76.35,63.0,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Shooting Green - The Shadow of Death.mkv,135.55,88.09,65.0,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Trailer.mkv,25.54,18.17,71.1,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Behind the Camera - Directing the Rebellion.mkv,156.99,92.74,59.1,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Blooper reel.mkv,76.51,39.88,52.1,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Burning Down the House - The VFX of Episode 205.mkv,339.28,245.57,72.4,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Famous Last Words.mkv,197.89,110.84,56.0,1920x1080,1280x720,1,26,CQ
tv,Spartacus,On Set with Liam McIntyre.mkv,201.42,131.31,65.2,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Starz Studios - Spartacus Vengeance.mkv,404.33,205.25,50.8,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Legend of Spartacus.mkv,251.32,184.87,73.6,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Making of Spartacus Vengeance.mkv,181.58,110.13,60.7,1920x1080,1280x720,1,26,CQ
tv,Spartacus,A Bloody Farewell.mkv,77.86,45.41,58.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,Adorning the Damned.mkv,107.44,52.04,48.4,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Legend Retold.mkv,217.24,122.16,56.2,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Mind Behind SPARTACUS.mkv,180.74,87.26,48.3,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Price of Being a Gladiator.mkv,89.15,45.31,50.8,1920x1080,1280x720,1,26,CQ
tv,Spartacus,The Spoils of War Revealed - Visual Effects.mkv,146.08,78.88,54.0,1920x1080,1280x720,1,26,CQ
tv,The Originals (2013),The Originals - S05E01 - Where You Left Your Heart x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,652.22,308.48,47.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E02 - One Wrong Turn On Bourbon x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,644.08,308.0,47.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E03 - Ne Me Quitte Pas x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,597.6,285.31,47.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E04 - Between the Devil and the Deep Blue Sea x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,655.17,324.83,49.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E05 - Don't It Just Break Your Heart x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,591.58,292.75,49.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),"The Originals - S05E06 - What, Will, I, Have, Left x265 AC3 HDTV-1080p ZMNT - [EHX].mkv",545.69,283.58,52.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E07 - God's Gonna Trouble the Water x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,644.17,317.57,49.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E08 - The Kindness of Strangers x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,565.44,276.33,48.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E09 - We Have Not Long to Love x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,627.93,309.28,49.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E10 - There in the Disappearing Light x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,573.55,281.84,49.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E11 - Til the Day I Die x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,572.21,295.56,51.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E12 - The Tale of Two Wolves x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,613.09,323.95,52.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S05E13 - When the Saints Go Marching In x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,518.53,266.36,51.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E01 - Always and Forever x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,652.83,287.8,44.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E02 - House of the Rising Son x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,770.41,349.89,45.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E03 - Tangled Up in Blue x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,747.72,348.55,46.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E04 - Girl in New Orleans x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,684.89,313.93,45.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E05 - Sinners and Saints x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,808.82,367.6,45.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E06 - Fruit of the Poisoned Tree x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,706.24,323.98,45.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E07 - Bloodletting x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,906.33,409.09,45.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E08 - The River in Reverse x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,590.73,299.73,50.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E09 - Reigning Pain in New Orleans x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,617.14,293.73,47.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E10 - The Casket Girls x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,641.71,324.05,50.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),"The Originals - S01E11 - Après Moi, Le Déluge x265 AC3 HDTV-1080p ZMNT - [EHX].mkv",734.33,371.09,50.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E12 - Dance Back from the Grave x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,899.46,400.74,44.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E13 - Crescent City x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,850.19,382.01,44.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E14 - Long Way Back from Hell x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,937.53,375.42,40.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E15 - Le Grand Guignol x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,883.96,389.2,44.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E16 - Farewell to Storyville x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,748.56,324.52,43.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E17 - Moon Over Bourbon Street x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,835.99,356.22,42.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E18 - The Big Uneasy x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,838.6,384.67,45.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E19 - An Unblinking Death x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,935.77,396.93,42.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E20 - A Closer Walk with Thee x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,877.5,379.61,43.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E21 - The Battle of New Orleans x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,974.3,400.59,41.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S01E22 - From a Cradle to a Grave x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,928.43,400.1,43.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E01 - Rebirth x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,1025.24,383.96,37.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E02 - Alive and Kicking x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,814.31,380.39,46.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E03 - Every Mother's Son x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,781.54,337.54,43.2,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E04 - Live and Let Die x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,833.09,381.67,45.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E05 - Red Door x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,902.84,406.59,45.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E06 - Wheel Inside the Wheel x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,888.5,369.68,41.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E07 - Chasing the Devil's Tail x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,796.7,358.5,45.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E08 - The Brothers That Care Forgot x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,832.45,355.9,42.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E09 - The Map of Moments x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,829.61,385.98,46.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E10 - Gonna Set Your Flag on Fire x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,716.65,319.37,44.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E11 - Brotherhood of the Damned x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,845.35,371.63,44.0,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E12 - Sanctuary x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,829.89,342.37,41.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E13 - The Devil Is Damned x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,892.6,404.02,45.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),"The Originals - S02E14 - I Love You, Goodbye x265 AC3 HDTV-1080p ZMNT - [EHX].mkv",847.52,353.94,41.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E15 - They All Asked for You x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,873.45,389.9,44.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E16 - Save My Soul x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,760.23,334.0,43.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E17 - Exquisite Corpse x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,989.11,401.99,40.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E18 - Night Has a Thousand Eyes x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,856.52,361.05,42.2,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E19 - When the Levee Breaks x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,836.11,377.98,45.2,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E20 - City Beneath the Sea x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,929.47,396.96,42.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E21 - Fire with Fire x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,936.37,405.98,43.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S02E22 - Ashes to Ashes x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,1006.53,396.97,39.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E01 - For the Next Millennium x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,813.36,364.96,44.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E02 - You Hung the Moon x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,776.94,352.22,45.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E03 - Ill See You in Hell or New Orleans x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,763.23,359.36,47.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E04 - A Walk on the Wild Side x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,806.79,379.9,47.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E05 - The Axeman's Letter x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,659.81,315.62,47.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E06 - Beautiful Mistake x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,762.0,332.1,43.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E07 - Out of the Easy x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,728.96,326.02,44.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E08 - The Other Girl in New Orleans x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,685.65,296.55,43.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E09 - Savior x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,815.12,371.72,45.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E10 - A Ghost Along the Mississippi x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,751.77,325.19,43.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E11 - Wild at Heart x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,689.62,311.65,45.2,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E12 - Dead Angels x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,729.53,305.08,41.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E13 - Heart Shaped Box x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,810.25,343.16,42.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E14 - A Streetcar Named Desire (2) x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,635.07,281.71,44.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E15 - An Old Friend Calls x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,675.27,287.44,42.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E16 - Alone with Everybody x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,769.2,337.68,43.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E17 - Behind the Black Horizon x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,814.22,357.81,43.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E18 - The Devil Comes Here and Sighs x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,743.43,333.78,44.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E19 - No More Heartbreaks x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,797.62,328.96,41.2,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E20 - Where Nothing Stays Buried x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,782.43,329.69,42.1,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),"The Originals - S03E21 - Give 'Em Hell, Kid x265 AC3 HDTV-1080p ZMNT - [EHX].mkv",835.96,330.93,39.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S03E22 - The Bloody Crown x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,734.55,334.26,45.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E01 - Gather Up the Killers x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,931.37,342.6,36.8,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E02 - No Quarter x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,1107.13,381.65,34.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E03 - Haunter of Ruins x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,1084.11,361.78,33.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E04 - Keepers of the House x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,995.0,345.39,34.7,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E05 - I Hear You Knocking x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,1019.88,380.65,37.3,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E06 - Bag of Cobras x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,809.92,288.01,35.6,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E07 - High Water and a Devil's Daughter x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,871.03,325.66,37.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E08 - Voodoo in My Blood x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,759.91,295.91,38.9,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E09 - Queen Death x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,924.05,327.8,35.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E10 - Phantomesque x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,880.79,329.05,37.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E11 - A Spirit Here That Won't Be Broken x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,948.22,336.63,35.5,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E12 - Voodoo Child x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,767.88,294.98,38.4,1920x1080,1280x720,1,30,CQ
tv,The Originals (2013),The Originals - S04E13 - The Feast of All Sinners x265 AC3 HDTV-1080p ZMNT - [EHX].mkv,836.05,312.72,37.4,1920x1080,1280x720,1,30,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E01 - Coming 'Round the Mountain (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1834.17,608.26,33.2,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E02 - Promises to Keep (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1788.0,512.82,28.7,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E03 - People Who Died (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1835.95,538.88,29.4,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E04 - Sins of Omission (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1752.73,425.46,24.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E05 - Damned (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1794.29,431.97,24.1,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E06 - #081693 (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1656.36,523.86,31.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E07 - My Way (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1787.78,498.06,27.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E08 - Belleville (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1454.79,414.58,28.5,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E09 - Teeth and Tissue (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1579.02,466.85,29.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown (2021) - S04E10 - Belly of the Beast (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1664.43,522.79,31.4,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E01 - The Mayor of Kingstown x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2795.82,743.57,26.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E02 - The End Begins x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2118.66,557.79,26.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E03 - Simply Murder x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2320.79,689.49,29.7,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E04 - The Price x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,1971.54,563.48,28.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E05 - Orion x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,1995.97,551.8,27.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E06 - Every Feather x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2144.15,594.42,27.7,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E07 - Along Came a Spider x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2409.16,628.68,26.1,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E08 - The Devil is Us x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2334.15,744.89,31.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E09 - The Lie of the Truth x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,1990.94,596.63,30.0,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S01E10 - This Piece of My Soul x265 EAC3 Bluray-1080p Ghost - [EHX].mkv,2151.7,724.44,33.7,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E01 - Never Missed a Pigeon x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1652.67,593.59,35.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E02 - Staring at the Devil x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1458.31,435.08,29.8,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E03 - Five at Five x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1166.34,371.93,31.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E04 - The Pool x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1231.43,403.92,32.8,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E05 - Kill Box x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1235.54,364.38,29.5,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E06 - Left With the Nose x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1186.59,322.55,27.2,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E07 - Drones x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1068.3,329.62,30.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E08 - Santa Jesus x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1479.87,433.16,29.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E09 - Peace in the Valley x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1173.13,343.62,29.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S02E10 - Little Green Ant x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1474.67,308.44,20.9,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E01 - Soldier's Heart x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1708.27,517.81,30.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E02 - Guts x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1337.44,356.23,26.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E03 - Barbarians at the Gate x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1259.31,384.99,30.6,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E04 - Rag Doll x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1272.69,353.19,27.8,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E05 - Iris x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1487.2,358.16,24.1,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E06 - Ecotone x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1195.73,331.25,27.7,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E07 - Marya Was Here x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1373.67,354.19,25.8,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E08 - Captain of the Sh-t out of Luck x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1443.89,382.38,26.5,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E09 - Home on the Range x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,1807.17,421.05,23.3,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Mayor of Kingstown - S03E10 - Comeuppance x265 EAC3 WEBDL-1080p Ghost - [EHX].mkv,2018.98,488.21,24.2,1920x960,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Behind the Story.mkv,2302.5,819.17,35.6,1920x1080,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Cast Favorite Scenes.mkv,165.13,72.29,43.8,1920x1080,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),People of Kingstown.mkv,98.87,32.71,33.1,1920x1080,1280x720,1,26,CQ
tv,Mayor of Kingstown (2021),Zero Sum Game The Finale.mkv,416.46,198.23,47.6,1920x1080,1280x720,1,26,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E01 - 'Til Death Do Us Part (1080p BluRay x265 Ghost) - [EHX].mkv,803.99,564.86,70.3,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E02 - A High Bar (1080p BluRay x265 Ghost) - [EHX].mkv,803.95,477.12,59.3,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E03 - So You Need a Crew (1080p BluRay x265 Ghost) - [EHX].mkv,803.48,534.11,66.5,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E04 - Finding Mr. Right (1080p BluRay x265 Ghost) - [EHX].mkv,774.3,431.71,55.8,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E05 - Being Harley Quinn (1080p BluRay x265 Ghost) - [EHX].mkv,803.53,490.21,61.0,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,"Harley Quinn (2019) - S01E06 - You're a Damn Good Cop, Jim Gordon (1080p BluRay x265 Ghost) - [EHX].mkv",803.63,433.08,53.9,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E07 - The Line (1080p BluRay x265 Ghost) - [EHX].mkv,803.99,469.51,58.4,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E08 - L.O.D.R.S.V.P (1080p BluRay x265 Ghost) - [EHX].mkv,803.23,481.86,60.0,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E09 - A Seat at the Table (1080p BluRay x265 Ghost) - [EHX].mkv,803.76,449.49,55.9,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E10 - Bensonhurst (1080p BluRay x265 Ghost) - [EHX].mkv,803.33,443.04,55.2,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E11 - Harley Quinn Highway (1080p BluRay x265 Ghost) - [EHX].mkv,802.69,539.05,67.2,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E12 - Devil's Snare (1080p BluRay x265 Ghost) - [EHX].mkv,802.69,534.32,66.6,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S01E13 - The Final Joke (1080p BluRay x265 Ghost) - [EHX].mkv,802.34,478.3,59.6,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E01 - New Gotham (1080p BluRay x265 Ghost) - [EHX].mkv,802.81,492.43,61.3,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E02 - Riddle U (1080p BluRay x265 Ghost) - [EHX].mkv,803.16,495.87,61.7,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E03 - Catwoman (1080p BluRay x265 Ghost) - [EHX].mkv,804.51,458.38,57.0,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E04 - Thawing Hearts (1080p BluRay x265 Ghost) - [EHX].mkv,803.41,447.73,55.7,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E05 - Batman's Back Man (1080p BluRay x265 Ghost) - [EHX].mkv,802.97,439.21,54.7,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E06 - All the Best Inmates Have Daddy Issues (1080p BluRay x265 Ghost) - [EHX].mkv,803.21,489.42,60.9,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E07 - There's No Place to Go But Down (1080p BluRay x265 Ghost) - [EHX].mkv,803.2,489.22,60.9,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E08 - Inner (Para) Demons (1080p BluRay x265 Ghost) - [EHX].mkv,803.68,489.95,61.0,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E09 - Bachelorette (1080p BluRay x265 Ghost) - [EHX].mkv,803.78,496.96,61.8,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E10 - Dye Hard (1080p BluRay x265 Ghost) - [EHX].mkv,802.7,494.12,61.6,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E11 - A Fight Worth Fighting For (1080p BluRay x265 Ghost) - [EHX].mkv,803.35,457.01,56.9,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,Harley Quinn (2019) - S02E12 - Lovers' Quarrel (1080p BluRay x265 Ghost) - [EHX].mkv,802.45,489.44,61.0,1920x1080,1920x1080,1,28,CQ
tv,Harley Quinn,"Harley Quinn (2019) - S02E13 - Something Borrowed, Something Green (1080p BluRay x265 Ghost) - [EHX].mkv",803.68,496.56,61.8,1920x1080,1920x1080,1,28,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E01 - One Ring Don't Make a Dynasty x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,4664.08,1446.42,31.0,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E02 - The Magic Is Back x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,3711.58,1178.77,31.8,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E03 - The Second Coming h264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,3467.93,1073.03,30.9,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E04 - The New World x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,4108.6,1280.27,31.2,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E05 - The Hamburger Hamlet x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,3737.86,1208.95,32.3,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E06 - 'beat L.A.' x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,3729.48,1169.87,31.4,1920x1080,1280x720,1,30,CQ
tv,Winning Time - The Rise of the Lakers Dynasty (2022),Winning Time - The Rise of the Lakers Dynasty - S02E07 - What Is and What Should Never Be x264 EAC3 Atmos WEBDL-1080p NTb - [EHX].mkv,4867.59,1576.8,32.4,1920x1080,1280x720,1,30,CQ
movie,N/A,Scott Pilgrim vs. the World (2010) x265 AAC 5.1 Bluray-1080p afm72 - [EHX].mkv,5104.23,2494.68,48.9,1920x1040,1920x1040,5,28,CQ
movie,N/A,La La Land (2016) x265 AAC 7.1 Bluray-1080p Tigole - [EHX].mkv,5066.96,2055.78,40.6,1920x754,1920x754,2,28,CQ
movie,N/A,Pacific Rim (2013) x264 DTS 5.1 Bluray-1080p 3Li - [EHX].mkv,11307.89,4143.41,36.6,1920x1080,1920x1080,2,32,CQ
movie,N/A,Deadpool & Wolverine (2024) x265 AC3 5.1 Bluray-1080p Radarr - [EHX].mkv,3989.24,1811.24,45.4,1920x800,1920x800,2,28,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E01 - Part One x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2239.24,496.66,22.2,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E02 - Part Two x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2011.0,391.54,19.5,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E03 - Part Three x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1754.75,369.66,21.1,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E04 - Part Four x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1877.7,322.6,17.2,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E05 - Part Five x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1933.03,418.72,21.7,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E06 - Part Six x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2198.91,365.38,16.6,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E07 - Part Seven x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1781.45,305.34,17.1,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E08 - Part Eight x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1852.37,309.85,16.7,1920x804,1280x720,1,26,CQ
tv,Masters of the Air (2024),Masters of the Air - S01E09 - Part Nine x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2797.17,654.05,23.4,1920x804,1280x720,1,26,CQ
tv,Shetland,Shetland.S10E01.1080p.WEB-DL-[Feranki1980] - [EHX].mkv,740.61,537.6,72.6,1920x972,1280x720,1,30,CQ
tv,Shetland,Shetland.S10E02.1080p.iP.WEB-DL.AAC2.0.H.264-RAWR-[Feranki1980] - [EHX].mkv,749.42,519.69,69.3,1920x972,1280x720,1,30,CQ
tv,Shetland,Shetland.S10E03.1080p.iP.WEB-DL.AAC2.0.H.264-RAWR-[Feranki1980] - [EHX].mkv,747.15,550.36,73.7,1920x972,1280x720,1,30,CQ
tv,Shetland,Shetland.S10E04.1080p.iP.WEB-DL.AAC2.0.H.264-RAWR-[Feranki1980] - [EHX].mkv,750.47,467.37,62.3,1920x972,1280x720,1,30,CQ
tv,Shetland,Shetland.S10E05.1080p.iP.WEB-DL.AAC2.0.H.264-RAWR-[Feranki1980] - [EHX].mkv,749.94,431.02,57.5,1920x972,1280x720,1,30,CQ
tv,Shetland,Shetland.S10E06.1080p.iP.WEB-DL.AAC2.0.H.264-RAWR-[Feranki1980] - [EHX].mkv,748.93,422.54,56.4,1920x972,1280x720,1,30,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E01 - The Fcking Cop (1080p BluRay x265 Panda) - [EHX].mkv,1663.93,826.84,49.7,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E02 - Welcome to Pixie Swallow (1080p BluRay x265 Panda) - [EHX].mkv,1604.7,762.57,47.5,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E03 - Steel City Nightfall (1080p BluRay x265 Panda) - [EHX].mkv,1609.56,710.05,44.1,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E04 - In the Crimson Halls of Kane Hill (1080p BluRay x265 Panda) - [EHX].mkv,1587.18,720.32,45.4,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E05 - The Fcking Dead (1080p BluRay x265 Panda) - [EHX].mkv,1593.85,762.82,47.9,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E06 - Booby Traps (1080p BluRay x265 Panda) - [EHX].mkv,1599.97,794.38,49.6,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E07 - The Gentleman's Agreement (1080p BluRay x265 Panda) - [EHX].mkv,1594.23,737.61,46.3,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E08 - A Fistful of Blood (1080p BluRay x265 Panda) - [EHX].mkv,1607.68,800.99,49.8,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E09 - The Chopsocky Special (1080p BluRay x265 Panda) - [EHX].mkv,1563.03,744.2,47.6,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E10 - Scar Tissue (1080p BluRay x265 Panda) - [EHX].mkv,1608.92,763.48,47.5,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E11 - Rise of the Primo (1080p BluRay x265 Panda) - [EHX].mkv,1610.62,858.93,53.3,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E12 - Faces of Blood Drive (1080p BluRay x265 Panda) - [EHX].mkv,1586.66,868.54,54.7,1920x1080,1280x720,1,26,CQ
tv,Blood Drive (2017),Blood Drive (2017) - S01E13 - Finish Line (1080p BluRay x265 Panda) - [EHX].mkv,1609.74,571.79,35.5,1920x1080,1280x720,1,26,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E01 - One Year Later (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1815.56,591.56,32.6,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E02 - Sagrona Teema (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1590.76,530.54,33.4,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E03 - Harvest (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1896.15,741.79,39.1,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E04 - Ever Been to Ghorman (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1931.59,504.66,26.1,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E05 - I Have Friends Everywhere (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1920.68,529.78,27.6,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E06 - What a Festive Evening (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1944.78,558.89,28.7,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E07 - Messenger (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1564.25,416.44,26.6,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E08 - Who Are You (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1680.24,674.59,40.1,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E09 - Welcome to the Rebellion (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,2085.22,591.13,28.3,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E10 - Make It Stop (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1720.73,593.4,34.5,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S02E11 - Who Else Knows (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1511.14,398.7,26.4,1920x804,1920x804,1,28,CQ
tv,Andor (2022),"Star Wars Andor (2022) - S02E12 - Jedha, Kyber, Erso (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv",1634.51,462.31,28.3,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E01 - Kassa (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1403.69,516.89,36.8,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E02 - That Would Be Me (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1275.08,411.33,32.3,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E03 - Reckoning (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1442.81,567.72,39.3,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E04 - Aldhani (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1681.32,577.87,34.4,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E05 - The Axe Forgets (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1547.05,493.15,31.9,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E06 - The Eye (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1814.08,662.95,36.5,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E07 - Announcement (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1798.35,518.47,28.8,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E08 - Narkina 5 (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1908.41,603.93,31.6,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E09 - Nobody's Listening! (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1679.27,518.56,30.9,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E10 - One Way Out (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1532.8,526.31,34.3,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E11 - Daughter of Ferrix (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1538.09,431.23,28.0,1920x804,1920x804,1,28,CQ
tv,Andor (2022),Star Wars Andor (2022) - S01E12 - Rix Road (1080p DSNP WEB-DL x265 t3nzin) - [EHX].mkv,1940.1,665.2,34.3,1920x804,1920x804,1,28,CQ
tv,Bad Monkey,Bad Monkey - S01E01 - The Floating-Human-Body-Parts Capital of America x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2143.49,700.34,32.7,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E02 - A Hundred Bucks Says You Wont x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1734.18,535.68,30.9,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E03 - Nobody Said He Was Alvin Einstein x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1921.78,665.32,34.6,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,"Bad Monkey - S01E04 - Nothings Wrong With It, I Just Dont Need It Anymore x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv",2158.57,681.35,31.6,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E05 - That Damn Arm Is Back x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1599.9,574.72,35.9,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,"Bad Monkey - S01E06 - Yo, Would You Tell Ms. Chase I Still Love Her Like Crazy x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv",1760.87,551.26,31.3,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E07 - A Total Cat Person x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1572.91,501.69,31.9,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E08 - The Russian Mob Is Very Active in Key West x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1622.45,494.85,30.5,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E09 - You Really Dont Want to Kill This Scrumptious Little Puppy x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1490.04,548.12,36.8,1920x960,1280x720,1,26,CQ
tv,Bad Monkey,Bad Monkey - S01E10 - Were in the Memory-Making Business x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1478.87,565.11,38.2,1920x960,1280x720,1,26,CQ
movie,N/A,Project Hail Mary (2026) h265 EAC3 Atmos 5.1 WEBDL-2160p RDNYB - [EHX].mkv,25055.44,3042.63,12.1,3840x2160,1920x1080,1,28,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E02 - Talented & Terrible - Culinary Pageant h264 AAC WEBDL-1080p RAWR - [EHX].mkv,4468.35,1054.7,23.6,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E03 - Talented & Terrible - The Da Vinci Cook h264 AAC WEBDL-1080p RAWR - [EHX].mkv,4280.04,1023.44,23.9,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E04 - Talented & Terrible - Flavor Freestyle h264 AAC WEBDL-1080p RAWR - [EHX].mkv,3062.58,751.94,24.6,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E05 - Talented & Terrible - Big Top Boot Camp h264 AAC WEBDL-1080p RAWR - [EHX].mkv,3079.97,696.2,22.6,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E06 - Talented & Terrible - Encores and Entrees h264 AAC WEBDL-1080p RAWR - [EHX].mkv,2808.21,735.21,26.2,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S29E07 - Talented & Terrible - Culinary Curtain Call h264 AAC WEBDL-1080p FREQUENCY - [EHX].mkv,3096.2,666.74,21.5,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),"Worst Cooks in America - S30E01 - Reality Check - Lights, Camera, Boot Camp h264 AAC WEBDL-1080p FREQUENCY - [EHX].mkv",5823.63,1405.72,24.1,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S30E02 - Reality Check - Hollywood's Next Culinary Star h264 AAC WEBDL-1080p CBFM - [EHX].mkv,4271.91,1034.9,24.2,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S30E03 - Reality Check - The Worst Lotus x265 EAC3 HDTV-1080p MeGusta - [EHX].mkv,1078.62,976.55,90.5,1920x1080,1280x720,1,26,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S30E04 - Reality Check - Culinary Outlaws x265 EAC3 HDTV-1080p MeGusta - [EHX].mkv,722.7,656.14,90.8,1920x1080,1280x720,1,26,CQ
tv,Worst Cooks in America (2010),"Worst Cooks in America - S30E05 - Reality Check - Glitz, Glam and Gourmet h264 EAC3 WEBDL-1080p EDITH - [EHX].mkv",3170.18,750.22,23.7,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S30E06 - Reality Check - Agents of Flavor h264 EAC3 WEBDL-1080p EDITH - [EHX].mkv,3148.53,750.47,23.8,1920x1080,1280x720,1,30,CQ
tv,Worst Cooks in America (2010),Worst Cooks in America - S30E07 - Reality Check - Bite Club h264 EAC3 WEBDL-1080p EDITH - [EHX].mkv,3153.19,692.22,22.0,1920x1080,1280x720,1,30,CQ
tv,Make Some Noise,"Make Some Noise - S04E05 - Caitlin, Nick, and Geoff Take You to Church - [EHX].mkv",927.06,461.66,49.8,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E06 - Josh, Anna, and Jiavani Make a Day Rate - [EHX].mkv",1066.9,552.48,51.8,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E07 - Ross, Echo, and Corin Try to Recruit You - [EHX].mkv",968.47,508.98,52.6,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E08 - Jacob, Kurt, and Angela Have Fun with Filters - [EHX].mkv",1133.02,587.73,51.9,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,Make Some Noise - S04E09 - Different Language Office - [EHX].mkv,1245.54,501.08,40.2,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E10 - Anna, Geoff, and Jeremy Act Out Kids' Prompts - [EHX].mkv",1007.84,508.76,50.5,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E11 - Ally, Brennan, and Talia Try to Get Through Lunch - [EHX].mkv",1236.42,554.63,44.9,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E12 - Ben, Lisa, and Colton Have a Party - [EHX].mkv",1405.3,654.99,46.6,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,"Make Some Noise - S04E13 - Jacob, Kimia, and Jeremy Impersonate Each Other - [EHX].mkv",1252.55,603.24,48.2,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,Make Some Noise - S04E14 - Eat an Animal Before It Eats You Show - [EHX].mkv,1020.35,450.22,44.1,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,Make Some Noise - S04E15 - The Noise Boys Hype Each Other Up - [EHX].mkv,1290.93,602.25,46.7,1920x1080,1920x1080,1,32,CQ
tv,Make Some Noise,Make Some Noise - S04E16 - Make Some Noise Season 4 Cut For Time - [EHX].mkv,1847.06,871.61,47.2,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E01 - It's a Banksy - [EHX].mkv,585.29,281.93,48.2,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E02 - Two Hours in the Tesla Diner - [EHX].mkv,640.65,315.11,49.2,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E03 - At the Strip Club With Your Dentist - [EHX].mkv,579.55,281.68,48.6,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E04 - In My Feels About the Cold War - [EHX].mkv,566.61,274.53,48.5,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E05 - Give It up for McBean - [EHX].mkv,684.43,354.38,51.8,1920x1080,1920x1080,1,32,CQ
tv,Dimension 20's Adventuring Party,Dimension 20's Adventuring Party - S24E06 - Zaeth is a Guided Missle - [EHX].mkv,635.99,315.73,49.6,1920x1080,1920x1080,1,32,CQ
tv,Shetland,Shetland - 1x01 - Red Bones (1) - [EHX].mkv,1786.03,355.61,19.9,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 1x02 - Red Bones (2) - [EHX].mkv,2008.56,395.36,19.7,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x01 - Raven Black (1) - [EHX].mkv,2438.95,434.27,17.8,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x02 - Raven Black (2) - [EHX].mkv,2374.69,416.86,17.6,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x03 - Dead Water (1) - [EHX].mkv,2448.49,549.86,22.5,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x04 - Dead Water (2) - [EHX].mkv,2267.17,469.62,20.7,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x05 - Blue Lightning (1) - [EHX].mkv,2242.65,410.37,18.3,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 2x06 - Blue Lightning (2) - [EHX].mkv,2324.61,424.86,18.3,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x01 - Episode 1 - [EHX].mkv,2836.64,520.21,18.3,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x02 - Episode 2 - [EHX].mkv,3016.83,547.02,18.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x03 - Episode 3 - [EHX].mkv,2786.69,495.28,17.8,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x04 - Episode 4 - [EHX].mkv,2788.17,453.53,16.3,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x05 - Episode 5 - [EHX].mkv,2721.46,419.41,15.4,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 3x06 - Episode 6 - [EHX].mkv,2734.36,449.01,16.4,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x01 - Episode 1 - [EHX].mkv,1847.61,389.46,21.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x02 - Episode 2 - [EHX].mkv,1884.3,398.76,21.2,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x03 - Episode 3 - [EHX].mkv,2055.46,431.0,21.0,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x04 - Episode 4 - [EHX].mkv,2563.94,548.04,21.4,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x05 - Episode 5 - [EHX].mkv,2618.41,529.71,20.2,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 4x06 - Episode 6 - [EHX].mkv,2551.99,487.53,19.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x01 - Episode 1 - [EHX].mkv,2175.39,447.96,20.6,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x02 - Episode 2 - [EHX].mkv,1930.68,380.52,19.7,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x03 - Episode 3 - [EHX].mkv,2231.29,476.87,21.4,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x04 - Episode 4 - [EHX].mkv,2171.84,384.35,17.7,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x05 - Episode 5 - [EHX].mkv,2194.03,351.3,16.0,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 5x06 - Episode 6 - [EHX].mkv,2047.55,329.29,16.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x01 - Episode 1 - [EHX].mkv,1772.15,393.86,22.2,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x02 - Episode 2 - [EHX].mkv,1763.73,381.19,21.6,1920x958,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x03 - Episode 3 - [EHX].mkv,1812.15,378.93,20.9,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x04 - Episode 4 - [EHX].mkv,1895.41,444.11,23.4,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x05 - Episode 5 - [EHX].mkv,1633.78,369.25,22.6,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 6x06 - Episode 6 - [EHX].mkv,1743.38,371.84,21.3,1920x958,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x01 - Episode 1 - [EHX].mkv,2610.02,482.27,18.5,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x02 - Episode 2 - [EHX].mkv,2247.16,383.55,17.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x03 - Episode 3 - [EHX].mkv,2266.94,383.24,16.9,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x04 - Episode 4 - [EHX].mkv,2577.64,416.21,16.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x05 - Episode 5 - [EHX].mkv,2397.76,359.82,15.0,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 7x06 - Episode 6 - [EHX].mkv,2474.1,426.78,17.2,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x01 - Episode 1 - [EHX].mkv,1824.43,366.91,20.1,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x02 - Episode 2 - [EHX].mkv,1553.08,313.85,20.2,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x03 - Episode 3 - [EHX].mkv,1621.35,326.89,20.2,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x04 - Episode 4 - [EHX].mkv,1495.52,295.7,19.8,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x05 - Episode 5 - [EHX].mkv,1521.28,298.26,19.6,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 8x06 - Episode 6 - [EHX].mkv,1454.73,317.37,21.8,1920x1080,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x01 - Episode 1 - [EHX].mkv,1626.66,350.51,21.5,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x02 - Episode 2 - [EHX].mkv,1626.12,341.97,21.0,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x03 - Episode 3 - [EHX].mkv,1560.74,334.41,21.4,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x04 - Episode 4 - [EHX].mkv,1573.49,327.56,20.8,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x05 - Episode 5 - [EHX].mkv,1479.96,297.96,20.1,1920x960,1280x720,1,26,CQ
tv,Shetland,Shetland - 9x06 - Episode 6 - [EHX].mkv,1395.64,302.41,21.7,1920x960,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E01 - Pilot (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,619.43,311.78,50.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E02 - The Aftermath (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,622.99,296.59,47.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E03 - Blind Date (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,512.97,244.42,47.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E04 - Jack the Writer (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,569.21,268.55,47.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E05 - Jack-Tor (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,606.78,312.55,51.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E06 - Jack Meets Dennis (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,490.48,232.39,47.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E07 - Tracy Does Conan (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,686.13,302.5,44.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E08 - The Break-Up (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,486.46,244.63,50.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E09 - The Baby Show (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,529.08,259.27,49.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E10 - The Rural Juror (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,607.79,270.47,44.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E11 - The Head and the Hair (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,496.91,235.81,47.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E12 - Black Tie (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,480.02,240.58,50.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E13 - Up All Night (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,528.69,251.67,47.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E14 - The “C” Word (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,611.65,268.59,43.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E15 - Hard Ball (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,564.51,269.5,47.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E16 - The Source Awards (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,567.92,257.8,45.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E17 - The Fighting Irish (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,514.07,241.25,46.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E18 - Fireworks (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,558.39,275.88,49.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E19 - Corporate Crush (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,557.87,244.85,43.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E20 - Cleveland (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,539.64,252.13,46.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S01E21 - Hiatus (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,605.32,255.01,42.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E01 - Seinfeld Vision (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,568.97,258.66,45.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E02 - Jack Gets in the Game (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,590.69,266.71,45.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E03 - The Collection (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,607.98,257.13,42.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E04 - Rosemary's Baby (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,622.95,269.44,43.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E05 - Greenzo (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,523.51,247.39,47.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E06 - Somebody to Love (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,436.4,216.6,49.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E07 - Cougars (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,573.58,266.53,46.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E08 - Secrets & Lies (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,522.23,241.46,46.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E09 - Episode 209 (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,633.94,295.98,46.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E10 - Episode 210 (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,533.66,253.84,47.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E11 - MILF Island (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,407.13,198.99,48.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E12 - Subway Hero (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,585.17,264.58,45.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E13 - Succession (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,479.66,224.32,46.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E14 - Sandwich Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,494.43,228.96,46.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S02E15 - Cooter (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,463.87,228.42,49.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E01 - Do-Over (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,675.88,279.04,41.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E02 - Believe in the Stars (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,584.34,245.88,42.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E03 - The One with the Cast of Night Court (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,558.44,238.96,42.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E04 - Gavin Volure (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,504.32,215.01,42.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E05 - Reunion (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,512.35,236.64,46.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E06 - Christmas Special (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,617.35,239.32,38.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E07 - Señor Macho Solo (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,542.79,227.47,41.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E08 - Flu Shot (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,494.2,211.13,42.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E09 - Retreat to Move Forward (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,556.74,224.61,40.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E10 - Generalissimo (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,515.93,210.15,40.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E11 - St. Valentine's Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,466.02,179.3,38.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E12 - Larry King (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,457.86,182.84,39.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S03E13 - Goodbye, My Friend (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",474.62,189.23,39.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E14 - The Funcooker (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,515.2,197.72,38.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E15 - The Bubble (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,523.91,202.6,38.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S03E16 - Apollo, Apollo (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",562.72,202.58,36.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E17 - Cutbacks (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,482.13,179.14,37.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E18 - Jackie Jormp-Jomp (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,532.49,193.32,36.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E19 - The Ones (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,536.75,184.12,34.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E20 - The Natural Order (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,576.49,193.6,33.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E21 - Mamma Mia (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,651.76,207.01,31.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S03E22 - Kidney Now! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,659.56,218.94,33.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E01 - Season 4 (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,702.73,262.83,37.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E02 - Into the Crevasse (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,615.33,235.74,38.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E03 - Stone Mountain (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,497.09,199.93,40.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E04 - Audition Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,581.58,235.13,40.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E05 - The Problem Solvers (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,482.28,181.28,37.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E06 - Sun Tea (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,611.09,212.09,34.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E07 - Dealbreakers Talk Show #0001 (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,490.67,180.0,36.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E08 - Secret Santa (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,501.55,190.51,38.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E09 - Klaus and Greta (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,462.47,165.2,35.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E10 - Black Light Attack! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,464.96,181.33,39.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E11 - Winter Madness (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,523.27,188.52,36.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E12 - Verna (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,515.65,165.74,32.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E13 - Anna Howard Shaw Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,515.26,176.9,34.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E14 - Future Husband (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,502.52,164.11,32.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S04E15 - Don Geiss, America, and Hope (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",536.92,153.04,28.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E16 - Floyd (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,539.01,152.82,28.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E17 - Lee Marvin vs. Derek Jeter (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,635.3,169.7,26.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E18 - Khonani (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,523.96,154.83,29.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E19 - Argus (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,528.38,150.83,28.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E20 - The Moms (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,679.28,175.61,25.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E21 - Emmanuelle Goes to Dinosaur Land (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,726.07,177.69,24.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S04E22 - I Do Do (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,725.29,184.12,25.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E01 - The Fabian Strategy (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,543.68,175.34,32.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S05E02 - When It Rains, It Pours (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",667.57,218.66,32.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E03 - Let's Stay Together (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,518.81,171.54,33.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E04 - Live Show (East Coast) (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,1068.95,453.0,42.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E05 - Reaganing (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,631.88,211.82,33.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E06 - Gentleman's Intermission (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,462.05,152.43,33.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E07 - Brooklyn Without Limits (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,487.01,157.02,32.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E08 - College (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,522.02,171.79,32.9,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E09 - Chain Reaction of Mental Anguish (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,448.51,142.09,31.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E10 - Christmas Attack Zone (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,504.04,148.92,29.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E11 - Mrs. Donaghy (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,537.33,160.1,29.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E12 - Operation Righteous Cowboy Lightning (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,549.14,166.23,30.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E13 - Que Sorpresa! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,553.04,161.53,29.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E14 - Double-Edged Sword (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,486.71,144.05,29.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E15 - It's Never Too Late for Now (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,641.65,182.79,28.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E16 - TGS Hates Women (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,579.59,169.4,29.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E17 - Queen of Jordan (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,734.45,289.83,39.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E18 - Plan B (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,532.16,155.79,29.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E19 - I Heart Connecticut (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,574.89,167.63,29.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E20 - 100 (1) (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,676.41,209.56,31.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E21 - 100 (2) (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,508.25,149.64,29.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E22 - Everything Sunny All the Time Always (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,630.52,189.99,30.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S05E23 - Respawn (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,692.59,198.43,28.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E01 - Dance Like Nobody's Watching (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,670.36,246.07,36.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E02 - Idiots are People Two! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,628.17,241.75,38.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E03 - Idiots are People Three! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,553.49,214.75,38.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E04 - The Ballad of Kenneth Parcell (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,670.39,244.21,36.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E05 - Today You Are a Man (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,793.58,257.54,32.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S06E06-E07 - Hey, Baby, What's Wrong (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",1384.64,487.86,35.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E08 - The Tuxedo Begins (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,711.17,254.63,35.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E09 - Leap Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,803.59,280.91,35.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E10 - Alexis Goodlooking and the Case of the Missing Whisky (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,701.69,245.91,35.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E11 - Standards and Practices (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,635.65,232.3,36.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E12 - St. Patrick's Day (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,717.66,253.56,35.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E13 - Grandmentor (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,597.52,227.33,38.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E14 - Kidnapped by Danger (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,709.92,253.58,35.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E15 - The Shower Principle (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,713.21,256.55,36.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E16 - Nothing Left to Lose (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,832.17,287.65,34.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E17 - Meet the Woggels! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,710.81,263.97,37.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E18 - Murphy Brown Lied to Us (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,590.18,225.91,38.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E19 - Live from Studio 6H (East Coast) (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,1130.2,497.92,44.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E20 - Queen of Jordan II Mystery of the Phantom Pooper (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,739.62,346.32,46.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E21 - The Return of Avery Jessup (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,614.72,241.11,39.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S06E22 - What Will Happen to the Gang Next Year (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,597.94,247.0,41.3,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E01 - The Beginning of the End (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,582.72,244.52,42.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E02 - Governor Dunston (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,619.59,260.05,42.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E03 - Stride of Pride (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,671.13,264.61,39.4,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E04 - Unwindulax (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,830.65,283.76,34.2,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E05 - There's No I in America (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,452.37,201.55,44.6,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E06 - Aunt Phatso vs. Jack Donaghy (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,603.79,235.89,39.1,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),"30 Rock (2006) - S07E07 - Mazel Tov, Dummies! (1080p AMZN WEBRip x265 Silence) - [EHX].mkv",628.2,254.34,40.5,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E08 - My Whole Life is Thunder (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,573.33,233.6,40.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E09 - Game Over (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,541.5,215.68,39.8,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E10 - Florida (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,803.14,254.29,31.7,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E11 - A Goon's Deed in a Weary World (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,548.41,235.67,43.0,1920x1080,1280x720,1,26,CQ
tv,30 Rock (2006),30 Rock (2006) - S07E12-E13 - Hogcock! and Last Lunch (1080p AMZN WEBRip x265 Silence) - [EHX].mkv,1337.22,495.83,37.1,1920x1080,1280x720,1,26,CQ
tv,Rick and Morty,Rick and Morty - S01E01 - Pilot h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,388.66,294.39,75.7,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E02 - Lawnmower Dog h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,428.75,330.44,77.1,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E03 - Anatomy Park h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,496.8,358.51,72.2,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E04 - M. Night Shaym-Aliens! h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,625.93,370.1,59.1,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E05 - Meeseeks and Destroy h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,376.17,297.14,79.0,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E06 - Rick Potion #9 h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,428.03,336.61,78.6,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S01E07 - Raising Gazorpazorp h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,428.81,305.99,71.4,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E09 - Something Ricked This Way Comes h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,381.91,285.31,74.7,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S01E10 - Close Rick-Counters of the Rick Kind h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,563.59,393.07,69.7,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S01E11 - Ricksy Business h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,482.21,348.21,72.2,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E01 - A Rickle in Time h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,738.83,467.74,63.3,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E02 - Mortynight Run h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,664.13,440.28,66.3,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S02E03 - Auto Erotic Assimilation h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,473.12,332.51,70.3,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E04 - Total Rickall h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,522.01,371.03,71.1,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S02E05 - Get Schwifty h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,449.3,322.98,71.9,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E06 - The Ricks Must Be Crazy h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,520.87,368.41,70.7,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S02E07 - Big Trouble in Little Sanchez h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,410.98,309.36,75.3,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E08 - Interdimensional Cable 2 - Tempting Fate h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,398.73,308.1,77.3,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E09 - Look Who's Purging Now h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,357.11,264.86,74.2,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S02E10 - The Wedding Squanchers h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,445.56,307.05,68.9,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E01 - The Rickshank Rickdemption h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,473.36,352.96,74.6,1920x1080,1920x1080,3,28,CQ
tv,Rick and Morty,Rick and Morty - S03E02 - Rickmancing the Stone h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,347.09,265.74,76.6,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E03 - Pickle Rick h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,372.74,272.6,73.1,1920x1080,1920x1080,4,28,CQ
tv,Rick and Morty,Rick and Morty - S03E04 - Vindicators 3 - The Return of Worldender h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,383.73,295.68,77.1,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E05 - The Whirly Dirly Conspiracy h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,449.76,337.6,75.1,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E06 - Rest and Ricklaxation h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,362.78,280.89,77.4,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E07 - The Ricklantis Mixup h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,351.59,271.39,77.2,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E08 - Morty's Mind Blowers h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,364.09,280.28,77.0,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E09 - The ABC's of Beth h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,319.93,255.32,79.8,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S03E10 - The Rickchurian Mortydate h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,335.26,257.54,76.8,1920x1080,1920x1080,2,28,CQ
tv,Rick and Morty,Rick and Morty - S04E01 - Edge of Tomorty - Rick Die Rickpeat h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,370.99,297.11,80.1,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E02 - The Old Man and the Seat h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,284.37,229.56,80.7,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E03 - One Crew Over the Crewcoo's Morty h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,303.42,240.43,79.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E04 - Claw and Hoarder - Special Ricktim's Morty h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,329.97,263.37,79.8,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E05 - Rattlestar Ricklactica h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,295.87,245.8,83.1,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E06 - Never Ricking Morty h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,348.97,276.02,79.1,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E07 - Promortyus h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,397.76,303.08,76.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E08 - The Vat of Acid Episode h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,313.57,256.2,81.7,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E09 - Childrick of Mort h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,436.34,336.87,77.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S04E10 - Star Mort - Rickturn of the Jerri h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,339.49,270.91,79.8,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E01 - Mort Dinner Rick Andre h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,369.6,302.91,82.0,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E02 - Mortyplicity h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,355.2,288.35,81.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E03 - A Rickconvenient Mort h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,539.75,380.64,70.5,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E04 - Rickdependence Spray h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,303.01,247.26,81.6,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E05 - Amortycan Grickfitti h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,342.24,268.19,78.4,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E06 - Rick & Morty's Thanksploitation Spectacular h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,429.56,338.68,78.8,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E07 - Gotron Jerrysis Rickvangelion h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,361.95,284.13,78.5,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E08 - Rickternal Friendshine of the Spotless Mort h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,341.13,274.1,80.4,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E09 - Forgetting Sarick Mortshall h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,319.26,254.03,79.6,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S05E10 - Rickmurai Jack h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,420.75,318.91,75.8,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E01 - Solaricks h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,312.7,244.74,78.3,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E02 - Rick - A Mort Well Lived h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,304.22,231.31,76.0,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E03 - Bethic Twinstinct h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,219.22,185.28,84.5,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E04 - Night Family h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,484.49,257.86,53.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E05 - Final DeSmithation h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,378.16,287.36,76.0,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E06 - JuRicksic Mort h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,301.06,241.73,80.3,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E07 - Full Meta Jackrick h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,495.23,347.25,70.1,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E08 - Analyze Piss h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,326.54,262.67,80.4,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E09 - A Rick in King Mortur's Mort h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,338.94,258.22,76.2,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S06E10 - Ricktional Mortpoon's Rickmas Mortcation h265 AAC Bluray-1080p SEPH1 - [EHX].mkv,258.4,214.42,83.0,1920x1080,1920x1080,1,28,CQ
tv,Rick and Morty,Rick and Morty - S07E01 - [EHX].mkv,639.33,352.41,55.1,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E02 - [EHX].mkv,677.88,343.25,50.6,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E03 - [EHX].mkv,638.63,298.37,46.7,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E04 - [EHX].mkv,631.08,281.44,44.6,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E05 - [EHX].mkv,641.12,441.61,68.9,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E06 - [EHX].mkv,670.36,307.97,45.9,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E07 - [EHX].mkv,640.18,352.19,55.0,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E08 - [EHX].mkv,640.49,429.79,67.1,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E09 - [EHX].mkv,637.41,361.63,56.7,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S07E10 - [EHX].mkv,700.58,329.79,47.1,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E01 - [EHX].mkv,878.85,343.22,39.1,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E02 - [EHX].mkv,783.22,404.17,51.6,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E03 - [EHX].mkv,792.25,361.16,45.6,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E04 - [EHX].mkv,782.85,386.15,49.3,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E05 - [EHX].mkv,755.47,406.12,53.8,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E06 - [EHX].mkv,758.77,378.57,49.9,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E07 - [EHX].mkv,839.63,354.81,42.3,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E08 - [EHX].mkv,816.0,299.14,36.7,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E09 - [EHX].mkv,837.89,335.35,40.0,1920x1080,1920x1080,6,32,CQ
tv,Rick and Morty,Rick and Morty - S08E10 - [EHX].mkv,872.92,347.55,39.8,1920x1080,1920x1080,6,32,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E01 - Never the New (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,2355.56,700.59,29.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E02 - Money Isn't Everything (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1342.48,406.31,30.3,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E03 - Face the Music (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1619.88,401.44,24.8,1920x1080,1280x720,1,26,CQ
tv,Murderbot (2025),Murderbot.S01E01.FreeCommerce.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1439.26,340.69,23.7,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E02.Eye.Contact.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1142.8,260.67,22.8,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E03.Risk.Assessment.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1060.32,251.35,23.7,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E04.Escape.Velocity.Protocol.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1027.77,266.28,25.9,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E05.Rogue.War.Tracker.Infinite.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1029.85,245.2,23.8,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E06.Command.Feed.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1056.52,246.88,23.4,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E07.Complementary.Species.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1378.03,311.81,22.6,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E08.Foreign.Object.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1121.12,269.56,24.0,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E09.All.Systems.Red.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1783.14,383.7,21.5,3840x1606,1920x1080,1,28,CQ
tv,Murderbot (2025),Murderbot.S01E10.The.Perimeter.2160p.10bit.ATVP.WEB-DL.DDP5.1.HEVC-Vyndros - [EHX].mkv,1517.16,358.92,23.7,3840x1606,1920x1080,1,28,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E01 - Who is in Charge Here(1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1647.28,372.02,22.6,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E02 - What the Papers Say (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1680.97,366.48,21.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E03 - Love is Never Easy (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1831.99,398.47,21.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E04 - Marriage is a Gamble (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1857.12,444.66,23.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E05 - A Different World (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1690.86,414.97,24.5,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E06 - If You Want to Cook an Omelette (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1873.59,341.94,18.3,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E07 - Ex-Communicated (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1818.67,336.2,18.5,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S03E08 - My Mind is Made Up (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,2126.51,499.37,23.5,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E04 - A Long Ladder (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1659.63,406.14,24.5,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E05 - Charity Has Two Functions (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1395.33,369.05,26.4,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E06 - Heads Have Rolled for Less (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1578.11,428.13,27.1,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E07 - Irresistible Change (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1347.89,346.94,25.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E08 - Tucked Up in Newport (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1450.68,443.96,30.6,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S01E09 - Let the Tournament Begin (1080p HMAX WEB-DL x265 Ghost) - [EHX].mkv,1795.71,490.98,27.3,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E01 - You Don't Even Like Opera (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1849.4,479.91,25.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E02 - Some Sort of Trick (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1681.46,418.24,24.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E03 - Head to Head (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1753.25,381.43,21.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E04 - His Grace the Duke (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1627.35,354.66,21.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E05 - Close Enough to Touch (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1803.63,407.18,22.6,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E06 - Warning Shots (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1735.19,397.37,22.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E07 - Wonders Never Cease (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1657.78,328.61,19.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Gilded Age (2022) - S02E08 - In Terms of Winning and Losing (1080p AMZN WEB-DL x265 Ghost) - [EHX].mkv,1815.74,357.34,19.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Behind the Gilded Curtain.mkv,51.96,28.16,54.2,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - Ada Brook.mkv,22.94,8.88,38.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - Agnes Van Rhijn.mkv,29.61,14.94,50.5,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - Bertha Russell.mkv,25.6,14.48,56.6,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - George Russell.mkv,26.56,10.29,38.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - Marian Brook.mkv,24.26,13.06,53.8,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Recap - Peggy Scott.mkv,18.42,7.78,42.2,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Character Superlatives.mkv,38.87,17.08,43.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Season 2 - Testing the Cast on 1800s Etiquette.mkv,66.61,32.43,48.7,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Behind the Scenes.mkv,46.27,27.46,59.3,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Meet the Russell Household.mkv,145.78,63.12,43.3,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,Meet the Van Rhijn Household.mkv,210.26,83.95,39.9,1920x1080,1280x720,1,26,CQ
tv,The Gilded Age,The Black Elite of New York.mkv,83.86,39.24,46.8,1920x1080,1280x720,1,26,CQ
tv,Detroiters (2017),Detroiters - S01E01 - Pilot h264 EAC3 WEBDL-1080p Cinefeel - [EHX].mkv,1617.57,281.4,17.4,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E02 - Hog Riders h264 EAC3 WEBDL-1080p Cine - [EHX].mkv,1306.41,266.15,20.4,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E03 - Sam the Man h264 EAC3 WEBDL-1080p Cin - [EHX].mkv,1353.1,231.54,17.1,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E04 - Devereux Wigs h264 EAC3 WEBDL-1080p C - [EHX].mkv,1226.19,236.65,19.3,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E05 - Happy Birthday Mr. Duvet h264 EAC3 WEBDL-1080p Cinefeel - [EHX].mkv,1693.07,281.46,16.6,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E06 - 3rd Floor h264 EAC3 WEBDL-1080p Cinef - [EHX].mkv,1397.62,280.39,20.1,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E07 - Smilin' Jack h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,2149.76,299.81,13.9,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E08 - Dream Cruise h264 EAC3 WEBDL-1080p Ci - [EHX].mkv,1165.75,264.61,22.7,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E09 - Husky Boys h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1870.09,237.62,12.7,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S01E10 - Quick Rick Mahorn in Dearborn h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1811.98,268.63,14.8,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E01 - April in the D h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1711.3,271.81,15.9,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E02 - Jefferson Porger h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1799.67,276.48,15.4,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E03 - Duvet Family Reunion h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1809.03,354.4,19.6,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E04 - Trevor h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1971.51,296.49,15.0,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E05 - Farmer Zack h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1794.2,275.27,15.3,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E06 - Mort Crim h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1889.63,258.37,13.7,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E07 - Lois h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1713.12,282.41,16.5,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E08 - Hark Motors h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1636.59,255.79,15.6,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E09 - Little Caesars h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1892.36,266.37,14.1,1920x1080,1280x720,1,30,CQ
tv,Detroiters (2017),Detroiters - S02E10 - Royals h264 EAC3 WEBDL-1080p DiMEPiECE - [EHX].mkv,1941.62,259.28,13.4,1920x1080,1280x720,1,30,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E01 - Episode 1 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1982.73,441.85,22.3,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E02 - Episode 2 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1841.38,378.38,20.5,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E03 - Episode 3 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1751.82,343.95,19.6,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E04 - Episode 4 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1721.93,326.18,18.9,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E05 - Episode 5 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1713.0,336.91,19.7,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E06 - Episode 6 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1721.37,308.46,17.9,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E07 - Episode 7 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1595.21,298.66,18.7,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E08 - Episode 8 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1662.14,470.52,28.3,1920x804,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E09 - Episode 9 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,1648.34,416.46,25.3,1920x804,1280x720,1,26,CQ
tv,The Gilded Age,Behind the Scenes.mkv,27.46,24.94,90.8,1280x720,1280x720,1,26,CQ
tv,The Gilded Age,Meet the Russell Household.mkv,63.12,58.41,92.5,1280x720,1280x720,1,26,CQ
tv,The Day of the Jackal (2024),The Day of the Jackal - S01E10 - Episode 10 x265 EAC3 Atmos WEBDL-1080p Ghost - [EHX].mkv,2149.17,438.33,20.4,1920x804,1280x720,1,26,CQ
tv,Gen V (2023),Gen V - S01E01 - God U x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,2051.12,823.55,40.2,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E02 - First Day x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1713.19,660.32,38.5,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E03 - #ThinkBrink x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1801.66,678.1,37.6,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E04 - The Whole Truth x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1637.82,573.9,35.0,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E05 - Welcome to the Monster Club x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1429.56,540.6,37.8,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E06 - Jumanji x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1407.65,549.23,39.0,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E07 - Sick x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1691.08,685.68,40.5,1920x800,1920x800,1,28,CQ
tv,Gen V (2023),Gen V - S01E08 - Guardians of Godolkin x265 EAC3 WEBDL-1080p Silence - [EHX].mkv,1356.4,554.18,40.9,1920x800,1920x800,1,28,CQ
tv,The Eternaut,The Eternaut - S01E01 - A Night of Cards x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,2793.09,421.9,15.1,1920x1080,1280x720,2,30,CQ
tv,The Eternaut,The Eternaut - S01E02 - Step Into the Sun x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,2814.92,473.91,16.8,1920x1080,1280x720,2,30,CQ
tv,The Eternaut,The Eternaut - S01E03 - Magnetism x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,3866.87,642.06,16.6,1920x1080,1280x720,2,30,CQ
tv,The Eternaut,The Eternaut - S01E04 - The Creed x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,3543.99,588.84,16.6,1920x1080,1280x720,2,30,CQ
tv,The Eternaut,The Eternaut - S01E05 - Horizon x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,3313.0,546.04,16.5,1920x1080,1280x720,2,30,CQ
tv,The Eternaut,The Eternaut - S01E06 - Cold Tomato Juice x264 EAC3 Atmos WEBDL-1080p EDITH - [EHX].mkv,4224.26,734.41,17.4,1920x1080,1280x720,2,30,CQ
tv,Government Cheese (2025),Government Cheese - S01E01 - The Gospel of Kenny Sharp x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,932.27,423.16,45.4,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E02 - Trial and Error x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,678.93,313.19,46.1,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E03 - Two Doors x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,429.54,189.7,44.2,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E04 - A Long Road Home x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,656.74,312.79,47.6,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),"Government Cheese - S01E05 - Father Facts, Figures, and Failures x265 AC3 HDTV-1080p ELiTE - [EHX].mkv",887.0,335.28,37.8,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E06 - Parable of Drawing in the Net x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,683.34,328.12,48.0,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E07 - The Woman on the Roof x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,617.7,270.56,43.8,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E08 - An Evening with Abraham Cohen x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,599.14,261.67,43.7,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E09 - R&D x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,573.82,241.84,42.1,1920x1038,1280x720,1,26,CQ
tv,Government Cheese (2025),Government Cheese - S01E10 - St. Hampton x265 AC3 HDTV-1080p ELiTE - [EHX].mkv,733.06,294.47,40.2,1920x1038,1280x720,1,26,CQ
tv,Adventuring Academy,Adventuring Academy - S07E01 - Bandaid on a Bowling Ball (with Vic Michaelis) - [EHX].mkv,2625.24,1161.67,44.3,1920x1080,1920x1080,1,32,CQ
movie,N/A,Boy Kills World 2023 2160p AMZN WEB-DL DDP5 1 H 265-BYNDR - [EHX].mkv,12911.95,1926.43,14.9,3840x1600,1920x1080,1,32,CQ

Can't render this file because it has a wrong number of fields in line 14.

View File

@ -207,7 +207,34 @@ def get_audio_streams(input_file: Path):
return streams return streams
def choose_audio_bitrate(channels: int, bitrate_kbps: int, audio_config: dict, is_1080_class: bool) -> tuple: def find_nearest_bitrate(source_bitrate_kbps: int, candidate_bitrates: list, threshold_kbs: int = 10) -> int:
"""
Check if source bitrate is within threshold of a standard bitrate.
If within -threshold kbs of a standard bitrate, return that standard bitrate.
Otherwise return 0 (meaning copy the source).
Args:
source_bitrate_kbps: Source bitrate in kbps
candidate_bitrates: List of standard bitrates in bits/sec (e.g., [128000, 192000])
threshold_kbs: Tolerance in kbps (default 10)
Returns:
Standard bitrate (in bits/sec) if within threshold, else 0
"""
source_bps = source_bitrate_kbps * 1000
threshold_bps = threshold_kbs * 1000
for candidate_bps in candidate_bitrates:
candidate_kbps = candidate_bps / 1000
# Check if source is within -threshold to +0 of the candidate
if source_bps >= (candidate_bps - threshold_bps) and source_bps <= candidate_bps:
logger.debug(f"Source bitrate {source_bitrate_kbps}kbps is within -{threshold_kbs}kbps of target {candidate_kbps:.0f}kbps - using standard bitrate")
return candidate_bps
return 0 # No match within threshold
def choose_audio_bitrate(channels: int, bitrate_kbps: int, audio_config: dict, is_1080_class: bool, is_commentary: bool = False) -> tuple:
""" """
Choose audio codec and bitrate based on channel count, detected bitrate, and resolution. Choose audio codec and bitrate based on channel count, detected bitrate, and resolution.
@ -216,46 +243,79 @@ def choose_audio_bitrate(channels: int, bitrate_kbps: int, audio_config: dict, i
- target_bitrate_bps: target bitrate in bits/sec (0 if using "copy") - target_bitrate_bps: target bitrate in bits/sec (0 if using "copy")
Rules: Rules:
Commentary tracks: Always use "low" stereo bitrate (e.g., 128kbps)
Stereo + 1080p: Stereo + 1080p:
- Above 192k encode to 192k with AAC - Above 192k encode to 192k with AAC
- At/below 192k preserve (copy) - At/below 192k check if within -10kbps of standard bitrate, else preserve (copy)
Stereo + 720p: Stereo + 720p:
- Above 160k encode to 160k with AAC - Above 160k encode to 160k with AAC
- At/below 160k preserve (copy) - At/below 160k check if within -10kbps of standard bitrate, else preserve (copy)
Multi-channel (5.1+): Multi-channel (5.1+):
- Below minimum threshold preserve original (copy) - Below minimum threshold check if within -10kbps of standard bitrate, else preserve (copy)
- Low to medium use EAC3 codec - Low to medium use EAC3 codec
""" """
# Commentary tracks always use low stereo bitrate
if is_commentary:
low_br = audio_config["stereo"]["low"]
return ("aac", low_br)
# Normalize to 2ch or 6ch output # Normalize to 2ch or 6ch output
output_channels = 6 if channels >= 6 else 2 output_channels = 6 if channels >= 6 else 2
if output_channels == 2: if output_channels == 2:
# Stereo logic - use AAC # Stereo logic - use AAC
stereo_bitrates = [
audio_config["stereo"]["low"],
audio_config["stereo"]["medium"],
audio_config["stereo"]["high"]
]
if is_1080_class: if is_1080_class:
# 1080p+ stereo # 1080p+ stereo
high_br = audio_config["stereo"]["high"] high_br = audio_config["stereo"]["high"]
if bitrate_kbps > (high_br / 1000): # Above 192k if bitrate_kbps > (high_br / 1000): # Above 192k
return ("aac", high_br) return ("aac", high_br)
else: else:
# Preserve original # Check if within -10kbps of a standard bitrate
return ("copy", 0) matched_br = find_nearest_bitrate(bitrate_kbps, stereo_bitrates)
if matched_br > 0:
return ("aac", matched_br)
else:
# Preserve original
return ("copy", 0)
else: else:
# 720p stereo # 720p stereo
medium_br = audio_config["stereo"]["medium"] medium_br = audio_config["stereo"]["medium"]
if bitrate_kbps > (medium_br / 1000): # Above 160k if bitrate_kbps > (medium_br / 1000): # Above 160k
return ("aac", medium_br) return ("aac", medium_br)
else: else:
# Preserve original # Check if within -10kbps of a standard bitrate
return ("copy", 0) matched_br = find_nearest_bitrate(bitrate_kbps, stereo_bitrates)
if matched_br > 0:
return ("aac", matched_br)
else:
# Preserve original
return ("copy", 0)
else: else:
# Multi-channel (6ch+) logic - use EAC3 # Multi-channel (6ch+) logic - use EAC3
multi_bitrates = [
audio_config["multi_channel"]["low"],
audio_config["multi_channel"]["medium"]
]
low_br = audio_config["multi_channel"]["low"] low_br = audio_config["multi_channel"]["low"]
medium_br = audio_config["multi_channel"]["medium"] medium_br = audio_config["multi_channel"]["medium"]
# If below the lowest threshold, copy the original audio instead of re-encoding # Check if source is within -10kbps of a standard bitrate
matched_br = find_nearest_bitrate(bitrate_kbps, multi_bitrates)
if matched_br > 0:
# Within threshold of a standard bitrate, use that one with EAC3
return ("eac3", matched_br)
# Not within threshold, apply normal logic
if bitrate_kbps < (low_br / 1000): if bitrate_kbps < (low_br / 1000):
logger.info(f"Multi-channel audio {bitrate_kbps}kbps < {low_br/1000:.0f}k minimum - copying original to avoid artifical inflation") logger.info(f"Multi-channel audio {bitrate_kbps}kbps < {low_br/1000:.0f}k minimum - copying original to avoid artifical inflation")
return ("copy", 0) return ("copy", 0)
@ -287,13 +347,14 @@ def filter_audio_streams(input_file: Path, streams: list) -> list:
for stream_info in streams: for stream_info in streams:
index, channels, bitrate, language, metadata, title = stream_info index, channels, bitrate, language, metadata, title = stream_info
# Check if commentary (in title or metadata) # Check if special audio (commentary or descriptive) in title or metadata
is_commentary = "comment" in str(title).lower() or "comment" in str(metadata).lower() is_special_audio = ("comment" in str(title).lower() or "comment" in str(metadata).lower() or
"descriptive" in str(title).lower() or "descriptive" in str(metadata).lower())
# Determine if English (check language field or assume first is English if no language set) # Determine if English (check language field or assume first is English if no language set)
is_english = (language and "eng" in language.lower()) or (not language) is_english = (language and "eng" in language.lower()) or (not language)
if is_commentary: if is_special_audio:
commentary_tracks.append((index, channels, bitrate, stream_info)) commentary_tracks.append((index, channels, bitrate, stream_info))
elif is_english: elif is_english:
english_tracks.append((index, channels, bitrate, stream_info)) english_tracks.append((index, channels, bitrate, stream_info))

View File

@ -75,6 +75,30 @@ def load_config_xml(path: Path) -> dict:
reduction_ratio_elem = general.find("reduction_ratio_threshold") if general is not None else None reduction_ratio_elem = general.find("reduction_ratio_threshold") if general is not None else None
reduction_ratio_threshold = float(reduction_ratio_elem.text) if reduction_ratio_elem is not None else 0.5 reduction_ratio_threshold = float(reduction_ratio_elem.text) if reduction_ratio_elem is not None else 0.5
# Extract general section as nested dict for other settings
general_dict = {}
if general is not None:
# Subtitles
subtitles_elem = general.find("subtitles")
if subtitles_elem is not None:
general_dict["subtitles"] = {
"enabled": subtitles_elem.find("enabled").text.lower() == "true" if subtitles_elem.find("enabled") is not None else True,
"extensions": subtitles_elem.find("extensions").text if subtitles_elem.find("extensions") is not None else ".vtt,.srt,.ass,.ssa,.sub",
"codec": subtitles_elem.find("codec").text if subtitles_elem.find("codec") is not None else "srt"
}
# Audio filter
audio_filter_elem = general.find("audio_filter")
if audio_filter_elem is not None:
general_dict["audio_filter"] = {
"enabled": audio_filter_elem.find("enabled").text.lower() == "true" if audio_filter_elem.find("enabled") is not None else False
}
# Default language for undefined audio tracks
default_language_elem = general.find("default_language")
if default_language_elem is not None:
general_dict["default_language"] = default_language_elem.text if default_language_elem.text else "eng"
# --- Path Mappings --- # --- Path Mappings ---
path_mappings = [] path_mappings = []
for m in root.findall("path_mappings/map"): for m in root.findall("path_mappings/map"):
@ -164,6 +188,7 @@ def load_config_xml(path: Path) -> dict:
"ignore_tags": [tag.strip() for tag in ignore_tags], "ignore_tags": [tag.strip() for tag in ignore_tags],
"reduction_ratio_threshold": reduction_ratio_threshold, "reduction_ratio_threshold": reduction_ratio_threshold,
"path_mappings": path_mappings, "path_mappings": path_mappings,
"general": general_dict,
"encode": {"cq": cq, "fallback": fallback, "filters": filters}, "encode": {"cq": cq, "fallback": fallback, "filters": filters},
"audio": audio, "audio": audio,
"services": services "services": services

View File

@ -5,6 +5,7 @@ import subprocess
from pathlib import Path from pathlib import Path
from core.audio_handler import get_audio_streams, choose_audio_bitrate, filter_audio_streams, prompt_user_audio_selection, prompt_for_title_stripping from core.audio_handler import get_audio_streams, choose_audio_bitrate, filter_audio_streams, prompt_user_audio_selection, prompt_for_title_stripping
from core.video_handler import calculate_crop_dimensions
from core.logger_helper import setup_logger from core.logger_helper import setup_logger
logger = setup_logger(Path(__file__).parent.parent / "logs") logger = setup_logger(Path(__file__).parent.parent / "logs")
@ -13,7 +14,7 @@ logger = setup_logger(Path(__file__).parent.parent / "logs")
def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, scale_height: int, def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, scale_height: int,
src_width: int, src_height: int, filter_flags: str, audio_config: dict, src_width: int, src_height: int, filter_flags: str, audio_config: dict,
method: str, bitrate_config: dict, encoder: str = "nvenc", subtitle_files: list = None, audio_language: str = None, method: str, bitrate_config: dict, encoder: str = "nvenc", subtitle_files: list = None, audio_language: str = None,
audio_filter_config: dict = None, test_mode: bool = False, strip_all_titles: bool = False, src_bit_depth: int = None, unforce_subs: bool = False, no_encode: bool = False, start_time: str = None, end_time: str = None): audio_filter_config: dict = None, test_mode: bool = False, strip_all_titles: bool = False, src_bit_depth: int = None, unforce_subs: bool = False, no_encode: bool = False, color_bit: int = None, crop_height: int = None, audio_titles: dict = None, audio_channels: dict = None):
""" """
Execute FFmpeg encoding/re-muxing with structured console output. Execute FFmpeg encoding/re-muxing with structured console output.
@ -23,21 +24,6 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
cq: Quality value (0-63, lower=better) for CQ mode cq: Quality value (0-63, lower=better) for CQ mode
scale_width/height: Target resolution dimensions scale_width/height: Target resolution dimensions
src_width/height: Source resolution dimensions src_width/height: Source resolution dimensions
filter_flags: Scaling filter algorithm
audio_config: Audio configuration dict
method: Encoding method ("CQ" or "Bitrate")
bitrate_config: Bitrate configuration
encoder: Video codec ("hevc", "av1", or "nvenc")
subtitle_files: List of external subtitle file paths
audio_language: Language code to tag audio streams
audio_filter_config: Audio filtering configuration
test_mode: If True, only encode first 15 minutes
strip_all_titles: If True, strip title metadata from audio
src_bit_depth: Source bit depth (8/10/12)
unforce_subs: If True, remove forced flag from subtitles
no_encode: If True, copy streams instead of encoding
start_time: Start time for trimming (e.g., "00:58:15.250")
end_time: End time for trimming (duration from start, e.g., "00:30:00")
filter_flags: Scaling filter algorithm (lanczos, bicubic, etc) filter_flags: Scaling filter algorithm (lanczos, bicubic, etc)
audio_config: Audio bitrate configuration dict audio_config: Audio bitrate configuration dict
method: Encoding method - "CQ" or "Bitrate" method: Encoding method - "CQ" or "Bitrate"
@ -51,6 +37,10 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
src_bit_depth: Source bit depth (8/10/12) for encoder auto-selection src_bit_depth: Source bit depth (8/10/12) for encoder auto-selection
unforce_subs: If True, remove forced flag from subtitle tracks unforce_subs: If True, remove forced flag from subtitle tracks
no_encode: If True, copy video/audio (re-mux only, skip encoding) no_encode: If True, copy video/audio (re-mux only, skip encoding)
color_bit: If specified (8 or 10), forces HEVC color bit depth. 8-bit uses yuv420p, 10-bit uses p010le.
crop_height: If specified, crop video to this height (centered). E.g., 816 for 1920x816 from 1920x1080 source.
audio_titles: Dict mapping stream index to custom title. E.g., {1: "Commentary"} sets stream 1 title to "Commentary".
audio_channels: Dict mapping stream index to channel count. E.g., {0: 2, 1: 6} forces track 0 to stereo, track 1 to 5.1. Only 2 or 6 allowed.
Returns: Returns:
tuple: (orig_size_bytes, output_size_bytes, reduction_ratio) tuple: (orig_size_bytes, output_size_bytes, reduction_ratio)
@ -99,8 +89,18 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
encoder_pix_fmt = "p010le" encoder_pix_fmt = "p010le"
encoder_bit_depth = "10-bit" encoder_bit_depth = "10-bit"
# Auto-select encoder based on detected source bit depth if provided # Handle --color-bit override if specified (only for HEVC)
if src_bit_depth is not None: if color_bit is not None and encoder == "hevc":
if color_bit == 8:
encoder_pix_fmt = "yuv420p"
encoder_bit_depth = "8-bit"
logger.info(f"Using --color-bit {color_bit}: HEVC NVENC 8-bit (yuv420p)")
elif color_bit == 10:
encoder_pix_fmt = "p010le"
encoder_bit_depth = "10-bit"
logger.info(f"Using --color-bit {color_bit}: HEVC NVENC 10-bit (p010le)")
# Auto-select encoder based on detected source bit depth if provided (only if --color-bit not specified)
elif src_bit_depth is not None and color_bit is None:
if src_bit_depth >= 10: if src_bit_depth >= 10:
# Source is 10-bit or higher - use HEVC NVENC # Source is 10-bit or higher - use HEVC NVENC
encoder_name = "HEVC NVENC" encoder_name = "HEVC NVENC"
@ -124,10 +124,26 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
# Build simple console summary # Build simple console summary
audio_summary_lines = [] audio_summary_lines = []
for (index, channels, avg_bitrate, src_lang, meta_bitrate, title, codec_name) in streams: for (index, channels, avg_bitrate, src_lang, meta_bitrate, title, codec_name) in streams:
# Normalize to 2ch or 6ch output # Determine final title (considering custom titles override)
final_title = audio_titles.get(index, title) if audio_titles else title
# Check if this is a commentary track (original or custom title)
is_commentary = final_title and "commentary" in final_title.lower()
# Determine output channels: audio_channels override takes precedence
is_1080_class = scale_height >= 1080 or scale_width >= 1920 is_1080_class = scale_height >= 1080 or scale_width >= 1920
output_channels = 6 if is_1080_class and channels >= 6 else 2 if audio_channels and index in audio_channels:
codec, br = choose_audio_bitrate(output_channels, avg_bitrate, audio_config, is_1080_class) # User explicitly specified channel count for this stream
output_channels = audio_channels[index]
channels_override = True
elif is_commentary:
output_channels = 2 # Commentary always stereo
channels_override = False
else:
output_channels = 6 if is_1080_class and channels >= 6 else 2
channels_override = False
codec, br = choose_audio_bitrate(output_channels, avg_bitrate, audio_config, is_1080_class, is_commentary)
if codec == "copy": if codec == "copy":
action = "COPY" action = "COPY"
@ -143,34 +159,41 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
lang_info = f"{src_lang}{audio_language}" if audio_language else src_lang lang_info = f"{src_lang}{audio_language}" if audio_language else src_lang
# Include title in display if present # Include title in display if present
title_info = f" [{title}]" if title else "" title_info = f" [{final_title}]" if final_title else ""
line = f" - Stream #{index}: {channels}ch→{output_channels}ch | {lang_info} | Detected: {codec_name} {avg_bitrate}kbps | Output: {output_codec} {output_bitrate} ({action}){title_info}" # Add override note if channels were forced
override_note = " [FORCED]" if channels_override else ""
line = f" - Stream #{index}: {channels}ch→{output_channels}ch | {lang_info} | Detected: {codec_name} {avg_bitrate}kbps | Output: {output_codec} {output_bitrate} ({action}){title_info}{override_note}"
audio_summary_lines.append(line) audio_summary_lines.append(line)
cmd = ["ffmpeg","-y"] cmd = ["ffmpeg","-y","-i",str(input_file)]
# Add trim parameters if splitting
if start_time:
cmd.extend(["-ss", start_time])
cmd.extend(["-i", str(input_file)])
# Add subtitle inputs if present # Add subtitle inputs if present
if subtitle_files: if subtitle_files:
for sub_file in subtitle_files: for sub_file in subtitle_files:
cmd.extend(["-i", str(sub_file)]) cmd.extend(["-i", str(sub_file)])
# Add trim duration if needed (for split end_time) # In test mode, only encode first 15 minutes
if end_time: if test_mode:
cmd.extend(["-t", end_time])
elif test_mode:
# In test mode, only encode first 15 minutes
cmd.extend(["-t", "900"]) # 900 seconds = 15 minutes cmd.extend(["-t", "900"]) # 900 seconds = 15 minutes
# Only add scale filter if encoding (not copying) # Build video filters (crop and/or scale)
video_filters = []
# Add crop filter first (if specified)
if crop_height and not no_encode:
crop_dims = calculate_crop_dimensions(src_height, crop_height)
if crop_dims["ffmpeg_filter"]:
video_filters.append(crop_dims["ffmpeg_filter"])
print(f" Applying crop: {crop_dims['ffmpeg_filter']} ({src_height}p → {crop_height}p)")
# Add scale filter (if encoding, not copying)
if not no_encode: if not no_encode:
cmd.extend([ video_filters.append(f"scale={scale_width}:{scale_height}:flags={filter_flags}:force_original_aspect_ratio=decrease")
"-vf",f"scale={scale_width}:{scale_height}:flags={filter_flags}:force_original_aspect_ratio=decrease"])
# Combine all filters with commas (ffmpeg filter chain syntax)
if video_filters:
filter_chain = ",".join(video_filters)
cmd.extend(["-vf", filter_chain])
cmd.extend(["-map","0:v:0"]) # Map only first actual video stream (skips attached pictures) cmd.extend(["-map","0:v:0"]) # Map only first actual video stream (skips attached pictures)
@ -203,26 +226,48 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
cmd += ["-b:v", vb, "-maxrate", maxrate, "-bufsize", bufsize] cmd += ["-b:v", vb, "-maxrate", maxrate, "-bufsize", bufsize]
for i, (index, channels, avg_bitrate, src_lang, meta_bitrate, title, codec_name) in enumerate(streams): for i, (index, channels, avg_bitrate, src_lang, meta_bitrate, title, codec_name) in enumerate(streams):
# Normalize to 2ch or 6ch output # Determine final title (considering custom titles override)
final_title = audio_titles.get(index, title) if audio_titles else title
# Debug: Log what we're working with
if i == 0: # Only log once per file
logger.debug(f"audio_titles dict received: {audio_titles}")
logger.debug(f"Stream {index}: original_title='{title}', final_title='{final_title}', audio_titles_present={audio_titles is not None}")
# Check if this is a commentary track (original or custom title)
is_commentary = final_title and "commentary" in final_title.lower()
# Determine output channels: audio_channels override takes precedence
# BUT: Commentary tracks ALWAYS max out at 2ch (stereo) unless explicitly overridden
is_1080_class = scale_height >= 1080 or scale_width >= 1920 is_1080_class = scale_height >= 1080 or scale_width >= 1920
output_channels = 6 if is_1080_class and channels >= 6 else 2 if audio_channels and index in audio_channels:
# User explicitly specified channel count for this stream
output_channels = audio_channels[index]
logger.info(f"Stream #{index}: Audio channels override applied: {channels}ch → {output_channels}ch")
elif is_commentary:
output_channels = 2 # Commentary always stereo
else:
output_channels = 6 if is_1080_class and channels >= 6 else 2
# If no_encode is True, always copy audio # If no_encode is True, always copy audio
if no_encode: if no_encode:
codec, br = "copy", avg_bitrate codec, br = "copy", avg_bitrate
else: else:
codec, br = choose_audio_bitrate(output_channels, avg_bitrate, audio_config, is_1080_class) codec, br = choose_audio_bitrate(output_channels, avg_bitrate, audio_config, is_1080_class, is_commentary)
# Check if title should be stripped (for this stream or globally) # Check if title should be stripped (for this stream or globally)
# Preserve any stream with "commentary" in the title, regardless of strip_all_titles # Preserve any stream with "commentary" or "descriptive" in the title, regardless of strip_all_titles
is_commentary = title and "commentary" in title.lower() is_special_audio = title and ("commentary" in title.lower() or "descriptive" in title.lower())
should_strip = strip_all_titles and not is_commentary should_strip = strip_all_titles and not is_special_audio
# Log title stripping decisions for debugging (debug level, not info) # Log title stripping decisions for debugging (debug level, not info)
logger.debug(f"Stream {index}: title='{title}', is_commentary={is_commentary}, strip_all_titles={strip_all_titles}, should_strip={should_strip}") logger.debug(f"Stream {index}: title='{final_title}', is_commentary={is_commentary}, is_special_audio={is_special_audio}, strip_all_titles={strip_all_titles}, should_strip={should_strip}")
if strip_all_titles and is_commentary: if is_commentary:
logger.debug(f"Stream {index}: ✓ Preserving title '{title}' (contains 'commentary')") logger.info(f"Stream #{index}: Commentary track detected (forcing 2ch stereo)")
if strip_all_titles and is_special_audio:
logger.debug(f"Stream {index}: ✓ Preserving title '{title}' (special audio track)")
if codec == "copy": if codec == "copy":
# Preserve original audio # Preserve original audio
@ -230,8 +275,11 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
# Only add language metadata if explicitly provided # Only add language metadata if explicitly provided
if audio_language: if audio_language:
cmd += [f"-metadata:s:a:{i}", f"language={audio_language}"] cmd += [f"-metadata:s:a:{i}", f"language={audio_language}"]
# Strip title metadata if requested (but preserve commentary tracks) # Apply custom title if provided for this stream (takes precedence)
if should_strip: if audio_titles and index in audio_titles:
cmd += [f"-metadata:s:a:{i}", f"title={audio_titles[index]}"]
# Strip title metadata if requested (but preserve commentary tracks and custom titles)
elif should_strip:
cmd += [f"-metadata:s:a:{i}", "title="] cmd += [f"-metadata:s:a:{i}", "title="]
else: else:
# Re-encode with target bitrate # Re-encode with target bitrate
@ -255,8 +303,11 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
# Only add language metadata if explicitly provided # Only add language metadata if explicitly provided
if audio_language: if audio_language:
cmd += [f"-metadata:s:a:{i}", f"language={audio_language}"] cmd += [f"-metadata:s:a:{i}", f"language={audio_language}"]
# Strip title metadata if requested (but preserve commentary tracks) # Apply custom title if provided for this stream (takes precedence)
if should_strip: if audio_titles and index in audio_titles:
cmd += [f"-metadata:s:a:{i}", f"title={audio_titles[index]}"]
# Strip title metadata if requested (but preserve commentary tracks and custom titles)
elif should_strip:
cmd += [f"-metadata:s:a:{i}", "title="] cmd += [f"-metadata:s:a:{i}", "title="]
# Add subtitle codec and metadata if subtitles are present # Add subtitle codec and metadata if subtitles are present
if subtitle_files: if subtitle_files:
@ -266,7 +317,9 @@ def run_ffmpeg(input_file: Path, output_file: Path, cq: int, scale_width: int, s
if unforce_subs: if unforce_subs:
cmd += ["-disposition:s:" + str(i), "-forced"] cmd += ["-disposition:s:" + str(i), "-forced"]
else: else:
cmd += ["-c:s", "copy"] # Convert mov_text (MP4 subtitles) to subrip (MKV-compatible)
# Use "copy" for other formats like subrip, ass, ssa, webvtt that work in MKV
cmd += ["-c:s", "subrip"]
# For embedded subtitles, still apply -disposition if unforce_subs is enabled # For embedded subtitles, still apply -disposition if unforce_subs is enabled
if unforce_subs: if unforce_subs:
# Apply to all embedded subtitle streams # Apply to all embedded subtitle streams

View File

@ -3,7 +3,6 @@
import csv import csv
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import time import time
@ -49,82 +48,6 @@ def get_default_cq(folder: Path, config: dict, resolution: str, encoder: str = "
return cq_config.get(key, 28) # Default fallback to 28 return cq_config.get(key, 28) # Default fallback to 28
def get_media_context(file: Path, root_folder: Path) -> dict:
"""
Extract media context from file path for structured logging.
Parses directory structure to identify show name, media type (TV/Movie),
season/episode numbers for grouping logs later.
Args:
file: File path to analyze
root_folder: Root processing folder to use as reference
Returns:
dict with keys: media_type, show_name, season (optional), episode (optional), video_filename
Examples:
P:\\tv\\Breaking Bad\\season01\\episode01.mkv
{"media_type": "tv", "show_name": "Breaking Bad", "season": "01", "episode": "01"}
P:\\movies\\Inception.mkv
{"media_type": "movie", "show_name": "Inception"}
"""
parts = file.parts
root_parts = root_folder.parts
context = {
"video_filename": file.name,
"media_type": None,
"show_name": None,
"season": None,
"episode": None
}
# Find where media type (tv/movie/anime) appears in path
path_lower = str(file).lower()
if "\\tv\\" in path_lower or "/tv/" in path_lower:
context["media_type"] = "tv"
elif "\\anime\\" in path_lower or "/anime/" in path_lower:
context["media_type"] = "anime"
elif "\\movies\\" in path_lower or "/movies/" in path_lower:
context["media_type"] = "movie"
else:
# Default to movie if path structure unclear
context["media_type"] = "other"
# Extract show name (directory immediately after media type)
try:
for i, part in enumerate(parts):
part_lower = part.lower()
if part_lower in ("tv", "anime", "movies"):
# Next part is show name
if i + 1 < len(parts):
context["show_name"] = parts[i + 1]
# For TV/anime, check if there's a season folder
if context["media_type"] in ("tv", "anime") and i + 2 < len(parts):
season_part = parts[i + 2].lower()
# Pattern: "season01", "s01", "season 1", etc.
import re
season_match = re.search(r's(?:eason)?\s*(\d+)', season_part)
if season_match:
context["season"] = season_match.group(1).zfill(2)
# Extract episode from filename
# Pattern: "e01", "episode01", "01", etc.
filename_lower = file.stem.lower()
ep_match = re.search(r'e(?:pisode)?\s*(\d+)', filename_lower)
if ep_match:
context["episode"] = ep_match.group(1).zfill(2)
break
except Exception as e:
logger.warning(f"Could not parse media context from {file}: {e}")
return context
def _cleanup_temp_files(temp_input: Path, temp_output: Path): def _cleanup_temp_files(temp_input: Path, temp_output: Path):
"""Helper function to clean up temporary input and output files.""" """Helper function to clean up temporary input and output files."""
try: try:
@ -142,80 +65,6 @@ def _cleanup_temp_files(temp_input: Path, temp_output: Path):
logger.warning(f"Could not delete temp output {temp_output.name}: {e}") logger.warning(f"Could not delete temp output {temp_output.name}: {e}")
def encode_with_split(temp_input: Path, temp_output: Path, cq: int, scale_width: int, scale_height: int,
src_width: int, src_height: int, filter_flags: str, audio_config: dict,
method: str, bitrate_config: dict, split_time: str, processing_folder: Path,
encoder: str = "hevc", src_bit_depth: int = 10, subtitle_files: list = None,
audio_language: str = None, audio_filter_config: dict = None,
strip_all_titles: bool = False, unforce_subs: bool = False) -> tuple:
"""
Encode video with split at specified timestamp, creating part1 and part2 files with full encoding.
Args:
temp_input: Source file path
temp_output: Base output file path (will create part1 and part2 versions)
cq: Quality value for encoding
split_time: Timestamp to split at (e.g., "00:58:15.250")
processing_folder: Folder where temp files are stored
encoder: Video encoder ("hevc" or "av1")
src_bit_depth: Source bit depth for encoder selection
subtitle_files: List of external subtitle paths
audio_language: Language code to tag audio
audio_filter_config: Audio filtering configuration
strip_all_titles: Strip title metadata from audio
unforce_subs: Remove forced subtitle flags
Returns:
tuple: (orig_size, part1_size + part2_size, combined_reduction_ratio, [part1_file, part2_file])
"""
orig_size = temp_input.stat().st_size
# Create part1 and part2 output paths
part1_output = processing_folder / temp_output.name.replace(".mkv", "_part1.mkv")
part2_output = processing_folder / temp_output.name.replace(".mkv", "_part2.mkv")
print(f"\n🎬 SPLIT MODE: Encoding two parts at {split_time}")
logger.info(f"Encoding with split at {split_time}: creating {part1_output.name} and {part2_output.name}")
# Part 1: from start to split_time
print(f"📍 Part 1: 00:00:00 → {split_time}")
try:
part1_size, _, _ = run_ffmpeg(
temp_input, part1_output, cq, scale_width, scale_height, src_width, src_height,
filter_flags, audio_config, method, bitrate_config, encoder, subtitle_files,
audio_language, audio_filter_config, False, strip_all_titles, src_bit_depth,
unforce_subs, False, start_time=None, end_time=split_time
)
print(f"✓ Part 1 encoded: {part1_output.stat().st_size / 1e6:.2f} MB")
logger.info(f"Part 1 complete: {part1_output.stat().st_size / 1e6:.2f} MB")
except Exception as e:
logger.error(f"Part 1 encoding failed: {e}")
raise
# Part 2: from split_time to end
print(f"📍 Part 2: {split_time} → end")
try:
part2_size, _, _ = run_ffmpeg(
temp_input, part2_output, cq, scale_width, scale_height, src_width, src_height,
filter_flags, audio_config, method, bitrate_config, encoder, subtitle_files,
audio_language, audio_filter_config, False, strip_all_titles, src_bit_depth,
unforce_subs, False, start_time=split_time, end_time=None
)
print(f"✓ Part 2 encoded: {part2_output.stat().st_size / 1e6:.2f} MB")
logger.info(f"Part 2 complete: {part2_output.stat().st_size / 1e6:.2f} MB")
except Exception as e:
logger.error(f"Part 2 encoding failed: {e}")
raise
# Calculate combined size and return
combined_size = part1_output.stat().st_size + part2_output.stat().st_size
reduction_ratio = combined_size / orig_size
print(f"\n✅ Split encoding complete: {orig_size / 1e6:.2f} MB → {combined_size / 1e6:.2f} MB ({reduction_ratio:.1%})")
return orig_size, combined_size, reduction_ratio, [part1_output, part2_output]
def should_skip_file(file: Path, no_encode: bool, unforce_subs: bool, force_process: bool, ignore_tags: list, travel_output_folder: Path) -> tuple: def should_skip_file(file: Path, no_encode: bool, unforce_subs: bool, force_process: bool, ignore_tags: list, travel_output_folder: Path) -> tuple:
""" """
Determine if a file should be skipped from processing based on multiple criteria. Determine if a file should be skipped from processing based on multiple criteria.
@ -249,9 +98,9 @@ def should_skip_file(file: Path, no_encode: bool, unforce_subs: bool, force_proc
return False, None return False, None
def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str, config: dict, tracker_file: Path, test_mode: bool = False, audio_language: str = None, filter_audio: bool = None, audio_select: str = None, encoder: str = "hevc", strip_all_titles: bool = False, travel_output_folder: Path = None, unforce_subs: bool = False, no_encode: bool = False, force_process: bool = False, replace_file: bool = False, wait_seconds: int = 0, split_time: str = None, target_file: Path = None): def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str, config: dict, tracker_file: Path, test_mode: bool = False, audio_language: str = None, filter_audio: bool = None, audio_select: str = None, encoder: str = "hevc", strip_all_titles: bool = False, travel_output_folder: Path = None, unforce_subs: bool = False, no_encode: bool = False, force_process: bool = False, replace_file: bool = False, wait_seconds: int = 0, color_bit: int = None, crop_height: int = None, audio_titles: dict = None, audio_channels: dict = None, title_suffix: str = None, default_language: str = None, no_replace_und: bool = False):
""" """
Process video files in folder with appropriate encoding settings. Process all video files in folder with appropriate encoding settings.
Args: Args:
folder: Input folder path folder: Input folder path
@ -269,11 +118,14 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
unforce_subs: If True, remove forced flag from all subtitle tracks. unforce_subs: If True, remove forced flag from all subtitle tracks.
no_encode: If True, skip encoding and copy video/audio streams as-is. Useful with --unforce-subs for re-muxing only. no_encode: If True, skip encoding and copy video/audio streams as-is. Useful with --unforce-subs for re-muxing only.
force_process: If True, process files even if they match ignore_tags (e.g., already encoded files). force_process: If True, process files even if they match ignore_tags (e.g., already encoded files).
crop_height: Optional crop height in pixels (e.g., 816 for 1920x816 crop from 1920x1080 source). If None, no crop applied.
replace_file: If True, replace original file instead of creating suffix version. Requires no_encode=True. replace_file: If True, replace original file instead of creating suffix version. Requires no_encode=True.
wait_seconds: Seconds to wait after each successful file (for Plex detection). 0 = no wait. wait_seconds: Seconds to wait after each successful file (for Plex detection). 0 = no wait.
travel_output_folder: If provided, move encoded files to this folder instead of original location. travel_output_folder: If provided, move encoded files to this folder instead of original location.
split_time: If provided, split video at this timestamp (e.g., "00:58:15.250"). Creates part1 and part2 files. color_bit: If specified (8 or 10), forces HEVC color bit depth. 8-bit uses yuv420p, 10-bit uses p010le. Only valid with hevc encoder.
target_file: If provided, only process this specific file (instead of all files in folder). title_suffix: Optional text to insert before main suffix (e.g., "1080p" or "v2"). If None, uses config file setting.
default_language: Default language code for undefined (und) audio tracks (e.g., 'eng', 'spa'). If None, uses config default.
no_replace_und: If True, disable replacement of undefined language tags with default language.
""" """
if not folder.exists(): if not folder.exists():
print(f"❌ Folder not found: {folder}") print(f"❌ Folder not found: {folder}")
@ -284,6 +136,11 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
bitrate_config = config["encode"]["fallback"] bitrate_config = config["encode"]["fallback"]
filters_config = config["encode"]["filters"] filters_config = config["encode"]["filters"]
suffix = config["suffix"] suffix = config["suffix"]
# Use provided title_suffix, or get from config, or use empty string
if title_suffix is None:
title_suffix = config.get("title_suffix", "")
# Create combined suffix (title_suffix appears before main suffix)
combined_suffix = title_suffix + suffix if title_suffix else suffix
extensions = config["extensions"] extensions = config["extensions"]
ignore_tags = config["ignore_tags"] ignore_tags = config["ignore_tags"]
reduction_ratio_threshold = config["reduction_ratio_threshold"] reduction_ratio_threshold = config["reduction_ratio_threshold"]
@ -303,7 +160,35 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
processing_folder = Path(config["processing_folder"]) processing_folder = Path(config["processing_folder"])
processing_folder.mkdir(parents=True, exist_ok=True) processing_folder.mkdir(parents=True, exist_ok=True)
# ===== Handle default language for undefined (und) audio tracks =====
# Determine effective default language
effective_default_lang = None
if not no_replace_und: # Only if replacement is enabled
# Priority: CLI arg > config setting > 'und' (disabled)
if default_language:
effective_default_lang = default_language
print(f"✅ Using CLI default language: {effective_default_lang}")
logger.info(f"Default language from CLI: {effective_default_lang}")
else:
# Get from config
config_default_lang = config.get("general", {}).get("default_language", "eng")
if config_default_lang and config_default_lang != "und":
effective_default_lang = config_default_lang
print(f"✅ Using config default language: {effective_default_lang}")
logger.info(f"Default language from config: {effective_default_lang}")
if no_replace_und:
print(f"⏸️ Undefined (und) language tag replacement is DISABLED (--no-replace-und)")
logger.info("und→default language replacement is disabled")
elif effective_default_lang:
print(f" Will replace 'und' audio language with: {effective_default_lang}")
logger.info(f"und→default language enabled: und → {effective_default_lang}")
else:
print(f" und audio language replacement is disabled or configured as 'und'")
logger.info("und→default language disabled (configured as 'und')")
# Determine if we're in smart mode (no explicit mode specified) # Determine if we're in smart mode (no explicit mode specified)
is_smart_mode = transcode_mode not in ["cq", "bitrate"] # Default/smart mode is_smart_mode = transcode_mode not in ["cq", "bitrate"] # Default/smart mode
is_forced_cq = transcode_mode == "cq" is_forced_cq = transcode_mode == "cq"
is_forced_bitrate = transcode_mode == "bitrate" is_forced_bitrate = transcode_mode == "bitrate"
@ -324,18 +209,7 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
print(f"{'='*60}\n") print(f"{'='*60}\n")
skipped_count = 0 skipped_count = 0
# If target_file is specified, only process that file; otherwise process all files in folder for file in folder.rglob("*"):
if target_file:
files_to_process = [target_file]
print(f"📄 Processing single file: {target_file.name}\n")
else:
files_to_process = folder.rglob("*")
for file in files_to_process:
# Skip hidden files/directories (starting with . or ._)
if file.name.startswith('.') or file.name.startswith('._'):
continue
if file.suffix.lower() not in extensions: if file.suffix.lower() not in extensions:
continue continue
@ -352,11 +226,8 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
logger.info(f"Skipped {skipped_count} file(s)") logger.info(f"Skipped {skipped_count} file(s)")
skipped_count = 0 skipped_count = 0
# Extract media context for structured logging
media_context = get_media_context(file, folder)
print("="*60) print("="*60)
logger.info(f"Processing: {file.name}", extra=media_context) logger.info(f"Processing: {file.name}")
print(f"📁 Processing: {file.name}") print(f"📁 Processing: {file.name}")
temp_input = (processing_folder / file.name).resolve() temp_input = (processing_folder / file.name).resolve()
@ -459,8 +330,9 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
content_cq = encoder_cq_config.get(cq_key, 32) content_cq = encoder_cq_config.get(cq_key, 32)
file_cq = cq if cq is not None else content_cq file_cq = cq if cq is not None else content_cq
# Output file with suffix in processing folder (always .mkv container) # Output file with title_suffix (if any) and main suffix in processing folder (always .mkv container)
temp_output = (processing_folder / f"{file.stem}{suffix}.mkv").resolve() combined_suffix = title_suffix + suffix if title_suffix else suffix
temp_output = (processing_folder / f"{file.stem}{combined_suffix}.mkv").resolve()
# Determine which method to try first # Determine which method to try first
if is_forced_bitrate: if is_forced_bitrate:
@ -486,46 +358,26 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
# Use config file setting (if present) # Use config file setting (if present)
audio_filter_config = config.get("general", {}).get("audio_filter", {}) audio_filter_config = config.get("general", {}).get("audio_filter", {})
# Handle split encoding if split_time is provided # ===== Determine effective audio language to apply =====
if split_time: # Priority: CLI --language > (detected und + default_language) > detected language
orig_size, out_size, reduction_ratio, split_output_files = encode_with_split( effective_audio_language = audio_language
temp_input, temp_output, file_cq, res_width, res_height, src_width, src_height,
filter_flags, audio_config, method, bitrate_config, split_time, processing_folder, # If no explicit CLI language, check if we should replace 'und' with default
actual_encoder, src_bit_depth, [subtitle_file] if subtitle_file else None, if not audio_language and effective_default_lang:
audio_language, audio_filter_config, strip_all_titles, unforce_subs # Get audio streams to check their languages
) streams = get_audio_streams(temp_input)
# For split mode, we need to process both files separately in the save logic if streams:
# For now, save both files and mark them as processed # Check if the first (or any primary) audio stream is 'und'
print(f"📦 Processing split files: {[f.name for f in split_output_files]}") first_stream_lang = streams[0][3] # 4th element is language
consecutive_failures = 0 if first_stream_lang == "und":
effective_audio_language = effective_default_lang
# Save both parts logger.info(f"First audio stream is 'und', replacing with default language: {effective_audio_language}")
for part_num, part_file in enumerate(split_output_files, 1): print(f"🔄 Audio stream detected as 'und', will tag as: {effective_audio_language}")
part_media_context = {**media_context, "split_part": part_num, "split_time": split_time}
dest_file = file.parent / part_file.name
shutil.move(part_file, dest_file)
print(f"✅ Part {part_num} saved: {dest_file.name}")
logger.info(f"Part {part_num} saved: {dest_file.name}", extra=part_media_context)
# Track in CSV
with open(tracker_file, "a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
f_type = "tv" if is_tv else ("anime" if is_anime else "movie")
show = file.parent.name
for part_num in [1, 2]:
writer.writerow([
f"{f_type}_split", show, f"{file.stem}_part{part_num}.mkv",
orig_size / 1e6, (out_size / 2) / 1e6, reduction_ratio * 100,
f"{src_width}x{src_height}", f"{res_width}x{res_height}", 0,
file_cq, "Split"
])
continue # Move to next file
orig_size, out_size, reduction_ratio = run_ffmpeg( orig_size, out_size, reduction_ratio = run_ffmpeg(
temp_input, temp_output, file_cq, res_width, res_height, src_width, src_height, temp_input, temp_output, file_cq, res_width, res_height, src_width, src_height,
filter_flags, audio_config, method, bitrate_config, actual_encoder, [subtitle_file] if subtitle_file else None, audio_language, filter_flags, audio_config, method, bitrate_config, actual_encoder, [subtitle_file] if subtitle_file else None, effective_audio_language,
audio_filter_config, test_mode, strip_all_titles, src_bit_depth, unforce_subs, no_encode audio_filter_config, test_mode, strip_all_titles, src_bit_depth, unforce_subs, no_encode, color_bit, crop_height, audio_titles, audio_channels
) )
# Check if encode met size target # Check if encode met size target
@ -567,7 +419,7 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
'subtitle_file': subtitle_file, 'subtitle_file': subtitle_file,
'src_bit_depth': src_bit_depth, 'src_bit_depth': src_bit_depth,
'encoder': actual_encoder, 'encoder': actual_encoder,
'media_context': media_context 'effective_audio_language': effective_audio_language
}) })
consecutive_failures += 1 consecutive_failures += 1
if consecutive_failures >= max_consecutive: if consecutive_failures >= max_consecutive:
@ -619,7 +471,7 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
'file_cq': file_cq, 'file_cq': file_cq,
'is_tv': is_tv, 'is_tv': is_tv,
'subtitle_file': subtitle_file, 'subtitle_file': subtitle_file,
'media_context': media_context 'effective_audio_language': effective_audio_language
}) })
consecutive_failures += 1 consecutive_failures += 1
if consecutive_failures >= max_consecutive: if consecutive_failures >= max_consecutive:
@ -652,7 +504,7 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
_save_successful_encoding( _save_successful_encoding(
file, temp_input, temp_output, orig_size, out_size, file, temp_input, temp_output, orig_size, out_size,
reduction_ratio, method, src_width, src_height, res_width, res_height, reduction_ratio, method, src_width, src_height, res_width, res_height,
file_cq, tracker_file, folder, is_tv, suffix, config, test_mode, subtitle_file, travel_output_folder, replace_file, wait_seconds, media_context file_cq, tracker_file, folder, is_tv, suffix, config, test_mode, subtitle_file, travel_output_folder, replace_file, wait_seconds, combined_suffix
) )
# In test mode, stop after first successful file # In test mode, stop after first successful file
@ -705,8 +557,8 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
file_data['res_width'], file_data['res_height'], file_data['res_width'], file_data['res_height'],
file_data['src_width'], file_data['src_height'], file_data['src_width'], file_data['src_height'],
filter_flags, audio_config, "Bitrate", bitrate_config, file_data.get('encoder', encoder), filter_flags, audio_config, "Bitrate", bitrate_config, file_data.get('encoder', encoder),
[file_data.get('subtitle_file')] if file_data.get('subtitle_file') else None, audio_language, None, test_mode, strip_all_titles, [file_data.get('subtitle_file')] if file_data.get('subtitle_file') else None, file_data.get('effective_audio_language'), None, test_mode, strip_all_titles,
file_data.get('src_bit_depth'), unforce_subs, no_encode file_data.get('src_bit_depth'), unforce_subs, no_encode, color_bit, crop_height, audio_titles, audio_channels
) )
# Check if bitrate also failed # Check if bitrate also failed
@ -730,8 +582,7 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
file_data['res_width'], file_data['res_height'], file_data['res_width'], file_data['res_height'],
file_data['file_cq'], tracker_file, file_data['file_cq'], tracker_file,
folder, file_data['is_tv'], suffix, config, False, folder, file_data['is_tv'], suffix, config, False,
file_data.get('subtitle_file'), travel_output_folder, replace_file, wait_seconds, file_data.get('subtitle_file'), travel_output_folder, replace_file, wait_seconds, combined_suffix
file_data.get('media_context')
) )
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@ -780,12 +631,9 @@ def process_folder(folder: Path, cq: int, transcode_mode: str, resolution: str,
def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size, def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size,
reduction_ratio, method, src_width, src_height, res_width, res_height, reduction_ratio, method, src_width, src_height, res_width, res_height,
file_cq, tracker_file, folder, is_tv, suffix, config=None, test_mode=False, subtitle_file=None, travel_output_folder=None, replace_file: bool = False, wait_seconds: int = 0, media_context: dict = None): file_cq, tracker_file, folder, is_tv, suffix, config=None, test_mode=False, subtitle_file=None, travel_output_folder=None, replace_file: bool = False, wait_seconds: int = 0, combined_suffix: str = None):
"""Helper function to save successfully encoded files with [EHX] tag and clean up subtitle files.""" """Helper function to save successfully encoded files with [EHX] tag and clean up subtitle files."""
if media_context is None:
media_context = {}
# In test mode, show ratio and skip file move/cleanup # In test mode, show ratio and skip file move/cleanup
if test_mode: if test_mode:
orig_size_mb = round(orig_size / 1e6, 2) orig_size_mb = round(orig_size / 1e6, 2)
@ -801,21 +649,24 @@ def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size
print(f"Method: {method} (CQ={file_cq if method == 'CQ' else 'N/A'})") print(f"Method: {method} (CQ={file_cq if method == 'CQ' else 'N/A'})")
print(f"{'='*60}") print(f"{'='*60}")
print(f"📁 Encoded file location: {temp_output}") print(f"📁 Encoded file location: {temp_output}")
logger.info(f"TEST MODE - File: {file.name} | Ratio: {percentage}% | Method: {method}", extra=media_context) logger.info(f"TEST MODE - File: {file.name} | Ratio: {percentage}% | Method: {method}")
return return
# Check if file is in a Featurettes folder - if so, remove suffix from destination filename # Check if file is in a Featurettes folder - if so, remove suffix from destination filename
folder_parts = [p.lower() for p in file.parent.parts] folder_parts = [p.lower() for p in file.parent.parts]
is_featurette = "featurettes" in folder_parts is_featurette = "featurettes" in folder_parts
# Use provided combined_suffix if available, otherwise use regular suffix
effective_suffix = combined_suffix if combined_suffix else suffix
if replace_file: if replace_file:
# Use original filename (no suffix) # Use original filename (no suffix)
dest_file = file.parent / file.name dest_file = file.parent / file.name
elif is_featurette: elif is_featurette:
# Remove suffix from temp_output.name for Featurettes # Remove effective suffix from temp_output.name for Featurettes
output_name = temp_output.name output_name = temp_output.name
if suffix in output_name: if effective_suffix in output_name:
output_name = output_name.replace(suffix, "") output_name = output_name.replace(effective_suffix, "")
dest_file = file.parent / output_name dest_file = file.parent / output_name
else: else:
dest_file = file.parent / temp_output.name dest_file = file.parent / temp_output.name
@ -828,11 +679,11 @@ def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size
travel_dest_dir.mkdir(parents=True, exist_ok=True) travel_dest_dir.mkdir(parents=True, exist_ok=True)
dest_file = travel_dest_dir / temp_output.name dest_file = travel_dest_dir / temp_output.name
print(f"🧳 Travel mode: Moving to {dest_file}") print(f"🧳 Travel mode: Moving to {dest_file}")
logger.info(f"Travel mode destination: {dest_file}", extra=media_context) logger.info(f"Travel mode destination: {dest_file}")
shutil.move(temp_output, dest_file) shutil.move(temp_output, dest_file)
print(f"🚚 Moved {temp_output.name}{dest_file.name}") print(f"🚚 Moved {temp_output.name}{dest_file.name}")
logger.info(f"Moved {temp_output.name}{dest_file.name}", extra=media_context) logger.info(f"Moved {temp_output.name}{dest_file.name}")
# Classify file type based on folder (folder_parts already defined earlier) # Classify file type based on folder (folder_parts already defined earlier)
if "tv" in folder_parts: if "tv" in folder_parts:
@ -871,11 +722,10 @@ def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size
]) ])
# Enhanced logging with all conversion details # Enhanced logging with all conversion details
log_context = {**media_context, "method": method, "original_size_mb": orig_size_mb, "output_size_mb": proc_size_mb, "reduction_pct": 100 - percentage} logger.info(f"\n✅ CONVERSION COMPLETE: {dest_file.name}")
logger.info(f"✅ CONVERSION COMPLETE: {dest_file.name}", extra=log_context) logger.info(f" Type: {f_type.upper()} | Show: {show}")
logger.info(f" Type: {f_type.upper()} | Show: {show}", extra=log_context) logger.info(f" Size: {orig_size_mb}MB → {proc_size_mb}MB ({percentage}% of original, {100-percentage:.1f}% reduction)")
logger.info(f" Size: {orig_size_mb}MB → {proc_size_mb}MB ({percentage}% of original, {100-percentage:.1f}% reduction)", extra=log_context) logger.info(f" Method: {method} | Status: SUCCESS")
logger.info(f" Method: {method} | Status: SUCCESS", extra=log_context)
print(f"📝 Logged conversion: {dest_file.name} ({percentage}%), method={method}") print(f"📝 Logged conversion: {dest_file.name} ({percentage}%), method={method}")
try: try:
@ -883,9 +733,9 @@ def _save_successful_encoding(file, temp_input, temp_output, orig_size, out_size
# Keep original file if in travel mode, replace mode, or if in Featurettes folder # Keep original file if in travel mode, replace mode, or if in Featurettes folder
if travel_output_folder: if travel_output_folder:
logger.info(f"Travel mode: Kept original file {file.name}", extra=media_context) logger.info(f"Travel mode: Kept original file {file.name}")
elif replace_file: elif replace_file:
logger.info(f"Replace mode: Original file has been replaced with processed version at {file.name}", extra=media_context) logger.info(f"Replace mode: Original file has been replaced with processed version at {file.name}")
elif not is_featurette: elif not is_featurette:
file.unlink() file.unlink()
logger.info(f"Deleted original and processing copy for {file.name}") logger.info(f"Deleted original and processing copy for {file.name}")

View File

@ -230,3 +230,42 @@ def has_forced_subtitles(input_file: Path) -> bool:
except Exception as e: except Exception as e:
logger.warning(f"Failed to check forced subtitles for {input_file.name}: {e}") logger.warning(f"Failed to check forced subtitles for {input_file.name}: {e}")
return False return False
def calculate_crop_dimensions(src_height: int, target_height: int) -> dict:
"""
Calculate crop dimensions to center-crop video to target height.
Maintains width, crops from top and bottom equally.
Args:
src_height: Source video height in pixels
target_height: Target crop height in pixels
Returns:
dict with:
- "ffmpeg_filter": FFmpeg crop filter string or empty if no crop needed
- "crop_top": Pixels to crop from top
- "crop_bottom": Pixels to crop from bottom
"""
if target_height >= src_height or target_height <= 0:
return {
"ffmpeg_filter": "",
"crop_top": 0,
"crop_bottom": 0
}
# Calculate pixels to remove total
pixels_to_remove = src_height - target_height
# Crop equally from top and bottom (centered crop)
crop_amount = pixels_to_remove // 2
# Note: FFmpeg crop filter is crop=width:height:x:y
# We assume width stays the same (1920), and y is the vertical offset (crop_amount)
# For 1920x1080 -> 1920x816: crop=1920:816:0:132
# where 132 = (1080 - 816) / 2
return {
"ffmpeg_filter": f"crop=-2:{target_height}:0:{crop_amount}",
"crop_top": crop_amount,
"crop_bottom": crop_amount
}

10
dropout_paths.txt Normal file
View File

@ -0,0 +1,10 @@
"P:\tv\Adventuring Academy" --title-suffix " WebRip-1080p"
"P:\tv\Dimension 20's Adventuring Party" --title-suffix " WebRip-1080p"
"P:\tv\Dimension 20" --title-suffix " WebRip-1080p"
"P:\tv\Crowd Control" --title-suffix " WebRip-1080p"
"P:\tv\Game Changer" --title-suffix " WebRip-1080p"
"P:\tv\Make Some Noise" --title-suffix " WebRip-1080p"
"P:\tv\Parlor Room" --title-suffix " WebRip-1080p"
"P:\tv\Smartypants" --title-suffix " WebRip-1080p"
"P:\tv\Um, Actually" --title-suffix " WebRip-1080p"
"P:\tv\Very Important People" --title-suffix " WebRip-1080p"

View File

@ -1,832 +0,0 @@
#!/usr/bin/env python3
"""
GUI Path Manager for Batch Video Transcoder
Allows easy browsing of folders and appending to paths.txt with encoding options.
"""
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from pathlib import Path
import os
import subprocess
import re
import json
from core.config_helper import load_config_xml
from core.logger_helper import setup_logger
logger = setup_logger(Path(__file__).parent.parent / "logs")
class PathManagerGUI:
def __init__(self, root):
self.root = root
self.root.title("Batch Transcoder - Path Manager")
self.root.geometry("1100x700")
# Load config
config_path = Path(__file__).parent.parent / "config.xml"
self.config = load_config_xml(config_path)
self.path_mappings = self.config.get("path_mappings", {})
# Paths file
self.paths_file = Path(__file__).parent.parent / "paths.txt"
self.transcode_bat = Path(__file__).parent.parent / "transcode.bat"
# Current selected folder
self.selected_folder = None
self.current_category = None
self.recently_added = None # Track recently added folder for highlighting
self.status_timer = None # Track status message timer
self.added_folders = set() # Folders that are in paths.txt
# Cache for folder data - split per category
self.cache_dir = Path(__file__).parent.parent / ".cache"
self.cache_dir.mkdir(exist_ok=True)
self.folder_cache = {} # Only current category in memory: {folder_path: size}
self.scan_in_progress = False
self.scanned_categories = set() # Track which categories have been scanned
# Lazy loading
self.all_folders = [] # All folders for current category
self.loaded_items = 0 # How many items are currently loaded
self.items_per_batch = 100 # Load 100 items at a time
# Load existing paths
self._load_existing_paths()
# Build UI
self._build_ui()
# Handle window close
self.root.protocol("WM_DELETE_WINDOW", self._on_closing)
def _build_ui(self):
"""Build the GUI layout."""
# Top frame for category selection and transcode launcher
top_frame = ttk.Frame(self.root)
top_frame.pack(fill=tk.X, padx=10, pady=10)
left_top = ttk.Frame(top_frame)
left_top.pack(side=tk.LEFT, fill=tk.X, expand=True)
ttk.Label(left_top, text="Category:").pack(side=tk.LEFT, padx=5)
self.category_var = tk.StringVar(value="tv")
categories = ["tv", "anime", "movies"]
for cat in categories:
ttk.Radiobutton(
left_top, text=cat.upper(), variable=self.category_var,
value=cat, command=self._on_category_change
).pack(side=tk.LEFT, padx=5)
ttk.Button(left_top, text="Refresh", command=self._refresh_with_cache_clear).pack(side=tk.LEFT, padx=5)
# Right side of top frame - transcode launcher
right_top = ttk.Frame(top_frame)
right_top.pack(side=tk.RIGHT)
if self.transcode_bat.exists():
ttk.Button(
right_top, text="▶ Run transcode.bat", command=self._run_transcode
).pack(side=tk.RIGHT, padx=5)
# Main content frame
main_frame = ttk.Frame(self.root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Left side - folder tree
left_frame = ttk.LabelFrame(main_frame, text="Folders (sorted by size)")
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
# Treeview for folders with add button column
self.tree = ttk.Treeview(left_frame, columns=("size", "add", "remove"), height=20)
self.tree.column("#0", width=180)
self.tree.column("size", width=80)
self.tree.column("add", width=50)
self.tree.column("remove", width=50)
self.tree.heading("#0", text="Folder Name")
self.tree.heading("size", text="Size")
self.tree.heading("add", text="Add")
self.tree.heading("remove", text="Remove")
scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=self._on_scrollbar)
self.tree.configure(yscroll=scrollbar.set)
self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# Configure tags for folder status
self.tree.tag_configure("added", background="#90EE90") # Light green for added
self.tree.tag_configure("not_added", background="white") # White for not added
self.tree.tag_configure("recently_added", background="#FFD700") # Gold for recently added
self.tree.bind("<Double-1>", self._on_folder_expand)
self.tree.bind("<<TreeviewSelect>>", self._on_folder_select)
self.tree.bind("<Button-1>", self._on_tree_click)
# Right side - options and preview
right_frame = ttk.LabelFrame(main_frame, text="Encoding Options & Preview")
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
# Mode selection
mode_frame = ttk.LabelFrame(right_frame, text="Mode (--m)")
mode_frame.pack(fill=tk.X, padx=5, pady=5)
self.mode_var = tk.StringVar(value="default")
for mode in ["default", "cq", "bitrate"]:
ttk.Radiobutton(mode_frame, text=mode, variable=self.mode_var, value=mode,
command=self._update_preview).pack(anchor=tk.W, padx=5)
# Resolution selection
res_frame = ttk.LabelFrame(right_frame, text="Resolution (--r)")
res_frame.pack(fill=tk.X, padx=5, pady=5)
self.resolution_var = tk.StringVar(value="none")
for res in ["none", "480", "720", "1080"]:
label = "Auto" if res == "none" else res + "p"
ttk.Radiobutton(res_frame, text=label, variable=self.resolution_var, value=res,
command=self._update_preview).pack(anchor=tk.W, padx=5)
# CQ value
cq_frame = ttk.LabelFrame(right_frame, text="CQ Value (--cq, optional)")
cq_frame.pack(fill=tk.X, padx=5, pady=5)
self.cq_var = tk.StringVar(value="")
cq_entry = ttk.Entry(cq_frame, textvariable=self.cq_var, width=10)
cq_entry.pack(anchor=tk.W, padx=5, pady=3)
cq_entry.bind("<KeyRelease>", lambda e: self._update_preview())
# Preview frame
preview_frame = ttk.LabelFrame(right_frame, text="Command Preview")
preview_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
self.preview_text = tk.Text(preview_frame, height=8, width=40, wrap=tk.WORD, bg="lightgray")
self.preview_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
self.preview_text.config(state=tk.DISABLED)
# Bottom frame - action buttons and status
bottom_frame = ttk.Frame(self.root)
bottom_frame.pack(fill=tk.X, padx=10, pady=10)
button_frame = ttk.Frame(bottom_frame)
button_frame.pack(side=tk.LEFT)
ttk.Button(button_frame, text="View paths.txt", command=self._view_paths_file).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Clear paths.txt", command=self._clear_paths_file).pack(side=tk.LEFT, padx=5)
# Status label (for silent feedback)
self.status_label = ttk.Label(bottom_frame, text="", foreground="green")
self.status_label.pack(side=tk.LEFT, padx=10)
# Load cache and populate initial category
self._load_cache()
self._refresh_folders(use_cache=True)
# Only scan once per category on first view
if self.current_category not in self.scanned_categories:
self.root.after(100, self._scan_folders_once)
def _on_category_change(self):
"""Handle category radio button change."""
self.current_category = self.category_var.get()
# Load cache for this category
self._load_cache()
# Show cached data first
self._refresh_folders(use_cache=True)
# Only scan once per category on first view
if self.current_category not in self.scanned_categories:
self.root.after(100, self._scan_folders_once)
def _load_cache(self):
"""Load folder cache for current category from disk (lazy)."""
category = self.category_var.get()
cache_file = self.cache_dir / f".cache_{category}.json"
self.folder_cache.clear()
# Don't fully load cache yet - just verify it exists
if not cache_file.exists():
logger.info(f"No cache file for {category}")
else:
logger.info(f"Cache file exists for {category}")
def _parse_cache_lazily(self, limit=None):
"""Parse cache file lazily and return folders."""
category = self.category_var.get()
cache_file = self.cache_dir / f".cache_{category}.json"
folders = []
if cache_file.exists():
try:
with open(cache_file, "r", encoding="utf-8") as f:
cache_dict = json.load(f)
# Convert to list and sort
for folder_path_str, size in cache_dict.items():
folder_path = Path(folder_path_str)
if folder_path.exists():
folders.append((folder_path.name, folder_path, size))
# Early exit if limit reached
if limit and len(folders) >= limit:
break
# Sort by size descending (only what we loaded)
folders.sort(key=lambda x: x[2], reverse=True)
except Exception as e:
logger.error(f"Failed to parse cache: {e}")
return folders
def _save_cache(self):
"""Save current category's folder cache to disk."""
category = self.category_var.get()
cache_file = self.cache_dir / f".cache_{category}.json"
try:
with open(cache_file, "w", encoding="utf-8") as f:
json.dump(self.folder_cache, f, indent=2)
except Exception as e:
logger.error(f"Failed to save {category} cache: {e}")
def _refresh_with_cache_clear(self):
"""Refresh and clear cache to force full scan."""
category = self.category_var.get()
cache_file = self.cache_dir / f".cache_{category}.json"
# Delete cache file for this category
if cache_file.exists():
cache_file.unlink()
self.folder_cache.clear()
self.scanned_categories.discard(category) # Reset so it will scan again
self._refresh_folders(use_cache=False)
def _scan_folders_once(self):
"""Scan folders once per category on first load."""
if self.scan_in_progress:
return
category = self.category_var.get()
if category in self.scanned_categories:
return # Already scanned this category
self.scan_in_progress = True
try:
category_mapping = {
"tv": "P:\\tv",
"anime": "P:\\anime",
"movies": "P:\\movies"
}
base_key = category_mapping.get(category)
if not base_key or base_key not in self.path_mappings:
return
base_path = Path(base_key)
if not base_path.exists():
return
# Scan folders and update cache
new_cache = {}
for entry in os.scandir(base_path):
if entry.is_dir(follow_symlinks=False):
size = self._get_folder_size(Path(entry))
new_cache[str(Path(entry))] = size
# Update cache and save
self.folder_cache = new_cache
self._save_cache()
self.scanned_categories.add(category)
# Update UI if still on same category
if self.category_var.get() == category:
self._refresh_folders(use_cache=True)
finally:
self.scan_in_progress = False
def _scan_folders_background(self):
"""Scan folders in background and update cache."""
if self.scan_in_progress:
return
self.scan_in_progress = True
try:
category = self.category_var.get()
category_mapping = {
"tv": "P:\\tv",
"anime": "P:\\anime",
"movies": "P:\\movies"
}
base_key = category_mapping.get(category)
if not base_key or base_key not in self.path_mappings:
return
base_path = Path(base_key)
if not base_path.exists():
return
# Scan folders and update cache
new_cache = {}
for entry in os.scandir(base_path):
if entry.is_dir(follow_symlinks=False):
size = self._get_folder_size(Path(entry))
new_cache[str(Path(entry))] = size
# Update cache and save
self.folder_cache[category] = new_cache
self._save_cache()
# Update UI if still on same category
if self.category_var.get() == category:
self._refresh_folders(use_cache=True)
finally:
self.scan_in_progress = False
# Schedule next continuous scan
self.background_scan_timer = self.root.after(
self.background_scan_interval,
self._continuous_background_scan
)
# Schedule next continuous scan
self.background_scan_timer = self.root.after(
self.background_scan_interval,
self._continuous_background_scan
)
def _load_existing_paths(self):
"""Load existing paths from paths.txt and extract folder paths."""
self.added_folders.clear()
if not self.paths_file.exists():
return
try:
with open(self.paths_file, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
# Extract the path (last argument in the command)
# Format: --m mode --r res --cq val "path" or just "path"
# Find all quoted strings
matches = re.findall(r'"([^"]*)"', line)
if matches:
# Last quoted string is the path
path = matches[-1]
self.added_folders.add(path)
except Exception as e:
logger.error(f"Failed to load existing paths: {e}")
def _get_folder_size(self, path: Path) -> int:
"""Calculate total size of folder in bytes."""
total = 0
try:
for entry in os.scandir(path):
if entry.is_file(follow_symlinks=False):
total += entry.stat().st_size
elif entry.is_dir(follow_symlinks=False):
total += self._get_folder_size(Path(entry))
except PermissionError:
pass
return total
def _format_size(self, bytes_size: int) -> str:
"""Format bytes to human readable size."""
for unit in ["B", "KB", "MB", "GB", "TB"]:
if bytes_size < 1024:
return f"{bytes_size:.1f} {unit}"
bytes_size /= 1024
return f"{bytes_size:.1f} PB"
def _refresh_folders(self, use_cache=False):
"""Refresh the folder tree from cache or disk."""
# Clear existing items
for item in self.tree.get_children():
self.tree.delete(item)
self.all_folders = []
self.loaded_items = 0
category = self.category_var.get()
# Map category to path mapping key
category_mapping = {
"tv": "P:\\tv",
"anime": "P:\\anime",
"movies": "P:\\movies"
}
base_key = category_mapping.get(category)
if not base_key or base_key not in self.path_mappings:
messagebox.showwarning("Info", f"No mapping found for {category}")
return
base_path = Path(base_key)
# Check if path exists
if not base_path.exists():
messagebox.showerror("Error", f"Path not found: {base_path}")
return
# Get folders from cache or disk
if use_cache:
# Parse cache lazily - only load what we need initially
folders = self._parse_cache_lazily(limit=None) # Get all but parse efficiently
else:
# Scan from disk
folders = []
try:
for entry in os.scandir(base_path):
if entry.is_dir(follow_symlinks=False):
size = self._get_folder_size(Path(entry))
folders.append((entry.name, Path(entry), size))
except PermissionError:
messagebox.showerror("Error", f"Permission denied accessing {base_path}")
return
# Update cache with fresh scan
cache_dict = {str(f[1]): f[2] for f in folders}
self.folder_cache = cache_dict
self._save_cache()
# Sort by size descending
folders.sort(key=lambda x: x[2], reverse=True)
# Store all folders and load first batch only
self.all_folders = folders
self._load_more_items()
def _on_folder_expand(self, event):
"""Handle folder double-click to show contents."""
selection = self.tree.selection()
if not selection:
return
item = selection[0]
tags = self.tree.item(item, "tags")
if not tags:
return
folder_path = Path(tags[0])
# Check if already expanded
if self.tree.get_children(item):
# Toggle: remove children
for child in self.tree.get_children(item):
self.tree.delete(child)
else:
# Add file/folder contents
try:
entries = []
for entry in os.scandir(folder_path):
if entry.is_file():
size = entry.stat().st_size
entries.append((entry.name, "File", size))
elif entry.is_dir():
size = self._get_folder_size(Path(entry))
entries.append((entry.name, "Folder", size))
# Sort by size descending
entries.sort(key=lambda x: x[2], reverse=True)
for name, type_str, size in entries:
size_str = self._format_size(size)
self.tree.insert(item, "end", text=f"[{type_str}] {name}", values=(size_str,))
except PermissionError:
messagebox.showerror("Error", f"Permission denied accessing {folder_path}")
def _on_folder_select(self, event):
"""Handle folder selection to update preview."""
selection = self.tree.selection()
if not selection:
return
item = selection[0]
tags = self.tree.item(item, "tags")
if tags:
self.selected_folder = tags[0]
self._update_preview()
def _on_tree_click(self, event):
"""Handle click on '+' or '-' button in add column."""
item = self.tree.identify("item", event.x, event.y)
column = self.tree.identify_column(event.x) # Only takes x coordinate
# Column #2 is the "add" column (columns are #0=name, #1=size, #2=add, #3=remove)
if item and column == "#2":
tags = self.tree.item(item, "tags")
if tags:
folder_path = tags[0]
values = self.tree.item(item, "values")
if len(values) > 1:
button_text = values[1] # Get button text
if "[+]" in button_text:
# Immediately update UI for snappy response
size_val = values[0]
self.tree.item(item, values=(size_val, "", "[-]"), tags=(folder_path, "added"))
# Add to paths.txt asynchronously
self.selected_folder = folder_path
self.root.after(0, self._add_to_paths_file_async, folder_path)
# Column #3 is the "remove" column
elif item and column == "#3":
tags = self.tree.item(item, "tags")
if tags:
folder_path = tags[0]
# Immediately update UI for snappy response
values = self.tree.item(item, "values")
size_val = values[0]
self.tree.item(item, values=(size_val, "[+]", ""), tags=(folder_path, "not_added"))
# Remove from paths.txt asynchronously
self.root.after(0, self._remove_from_paths_file_async, folder_path)
def _add_to_paths_file_async(self, folder_path):
"""Add to paths.txt without blocking UI."""
self.selected_folder = folder_path
self._add_to_paths_file()
# Silently reload in background
self._load_existing_paths()
def _remove_from_paths_file_async(self, folder_path):
"""Remove from paths.txt without blocking UI."""
self._remove_from_paths_file(folder_path)
def _update_preview(self):
"""Update the command preview."""
if not self.selected_folder:
preview_text = "No folder selected"
else:
folder_path = self.selected_folder
# Build command
cmd_parts = ['py main.py']
# Add mode if not default
mode = self.mode_var.get()
if mode != "default":
cmd_parts.append(f'--m {mode}')
# Add resolution if specified
resolution = self.resolution_var.get()
if resolution != "none":
cmd_parts.append(f'--r {resolution}')
# Add CQ if specified
cq = self.cq_var.get().strip()
if cq:
cmd_parts.append(f'--cq {cq}')
# Add path
cmd_parts.append(f'"{folder_path}"')
preview_text = " ".join(cmd_parts)
self.preview_text.config(state=tk.NORMAL)
self.preview_text.delete("1.0", tk.END)
self.preview_text.insert("1.0", preview_text)
self.preview_text.config(state=tk.DISABLED)
def _add_to_paths_file(self):
"""Append the current command to paths.txt."""
if not self.selected_folder:
messagebox.showwarning("Warning", "Please select a folder first")
return
folder_path = self.selected_folder
# Check if already in file
if folder_path in self.added_folders:
self._show_status(f"Already added: {Path(folder_path).name}")
return
# Build command line - start fresh
cmd_parts = []
# Add mode if not default
mode = self.mode_var.get()
if mode != "default":
cmd_parts.append(f'--m {mode}')
# Add resolution if specified
resolution = self.resolution_var.get()
if resolution != "none":
cmd_parts.append(f'--r {resolution}')
# Add CQ if specified
cq = self.cq_var.get().strip()
if cq:
cmd_parts.append(f'--cq {cq}')
# Add folder path
cmd_parts.append(f'"{folder_path}"')
line = " ".join(cmd_parts)
# Append to paths.txt
try:
# Check if file exists and has content
if self.paths_file.exists() and self.paths_file.stat().st_size > 0:
# Read last character to check if it ends with newline
with open(self.paths_file, "rb") as f:
f.seek(-1, 2) # Seek to last byte
last_char = f.read(1)
needs_newline = last_char != b'\n'
else:
needs_newline = False
# Write to file
with open(self.paths_file, "a", encoding="utf-8") as f:
if needs_newline:
f.write("\n")
f.write(line + "\n")
# Add to tracked set
self.added_folders.add(folder_path)
# Silent success - show status label instead of popup
self.recently_added = folder_path
self._show_status(f"✓ Added: {Path(folder_path).name}")
logger.info(f"Added to paths.txt: {line}")
# Clear timer if exists
if self.status_timer:
self.root.after_cancel(self.status_timer)
# Clear status after 3 seconds
self.status_timer = self.root.after(3000, self._clear_status)
except Exception as e:
messagebox.showerror("Error", f"Failed to write to paths.txt: {e}")
logger.error(f"Failed to write to paths.txt: {e}")
def _remove_from_paths_file(self, folder_path):
"""Remove a folder from paths.txt."""
if not self.paths_file.exists():
messagebox.showwarning("Warning", "paths.txt does not exist")
return
try:
with open(self.paths_file, "r", encoding="utf-8") as f:
lines = f.readlines()
# Filter out lines containing this folder path
new_lines = []
found = False
for line in lines:
if f'"{folder_path}"' in line or f"'{folder_path}'" in line:
found = True
else:
new_lines.append(line)
if not found:
messagebox.showwarning("Warning", "Path not found in paths.txt")
return
# Write back
with open(self.paths_file, "w", encoding="utf-8") as f:
f.writelines(new_lines)
# Remove from tracked set
self.added_folders.discard(folder_path)
self._show_status(f"✓ Removed: {Path(folder_path).name}")
logger.info(f"Removed from paths.txt: {folder_path}")
# Clear timer if exists
if self.status_timer:
self.root.after_cancel(self.status_timer)
# Clear status after 3 seconds
self.status_timer = self.root.after(3000, self._clear_status)
except Exception as e:
messagebox.showerror("Error", f"Failed to remove from paths.txt: {e}")
logger.error(f"Failed to remove from paths.txt: {e}")
def _show_status(self, message):
"""Show status message in label."""
self.status_label.config(text=message, foreground="green")
def _clear_status(self):
"""Clear status message after delay."""
self.status_label.config(text="")
self.status_timer = None
def _run_transcode(self):
"""Launch transcode.bat in a new command window."""
if not self.transcode_bat.exists():
messagebox.showerror("Error", f"transcode.bat not found at {self.transcode_bat}")
return
try:
# Launch in new cmd window
subprocess.Popen(
['cmd', '/c', f'"{self.transcode_bat}"'],
cwd=str(self.transcode_bat.parent),
creationflags=subprocess.CREATE_NEW_CONSOLE
)
logger.info("Launched transcode.bat")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch transcode.bat: {e}")
logger.error(f"Failed to launch transcode.bat: {e}")
def _view_paths_file(self):
"""Open paths.txt in a new window."""
if not self.paths_file.exists():
messagebox.showinfo("Info", "paths.txt does not exist yet")
return
try:
with open(self.paths_file, "r", encoding="utf-8") as f:
content = f.read()
# Create new window
view_window = tk.Toplevel(self.root)
view_window.title("paths.txt")
view_window.geometry("800x400")
text_widget = tk.Text(view_window, wrap=tk.WORD)
text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
text_widget.insert("1.0", content)
# Add close button
ttk.Button(view_window, text="Close", command=view_window.destroy).pack(pady=5)
except Exception as e:
messagebox.showerror("Error", f"Failed to read paths.txt: {e}")
def _clear_paths_file(self):
"""Clear the paths.txt file."""
if not self.paths_file.exists():
messagebox.showinfo("Info", "paths.txt does not exist")
return
if messagebox.askyesno("Confirm", "Are you sure you want to clear paths.txt?"):
try:
self.paths_file.write_text("", encoding="utf-8")
messagebox.showinfo("Success", "paths.txt has been cleared")
logger.info("paths.txt cleared")
except Exception as e:
messagebox.showerror("Error", f"Failed to clear paths.txt: {e}")
def _on_closing(self):
"""Handle window closing - cleanup timers."""
self.root.destroy()
def _on_scrollbar(self, *args):
"""Handle scrollbar movement - load more items when scrolling."""
self.tree.yview(*args)
# Check if we need to load more items
if self.all_folders and self.loaded_items < len(self.all_folders):
# Get scroll position
first_visible = self.tree.yview()[0]
last_visible = self.tree.yview()[1]
# If we're past 70% scrolled, load more
if last_visible > 0.7:
self._load_more_items()
def _load_more_items(self):
"""Load next batch of items into tree."""
start = self.loaded_items
end = min(start + self.items_per_batch, len(self.all_folders))
for i in range(start, end):
folder_name, folder_path, size = self.all_folders[i]
size_str = self._format_size(size)
folder_path_str = str(folder_path)
# Determine button and tag
if folder_path_str in self.added_folders:
add_btn = ""
remove_btn = "[-]"
tag = "added"
else:
add_btn = "[+]"
remove_btn = ""
tag = "not_added"
self.tree.insert("", "end", text=folder_name, values=(size_str, add_btn, remove_btn),
tags=(folder_path_str, tag))
self.loaded_items = end
def main():
root = tk.Tk()
app = PathManagerGUI(root)
root.mainloop()
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

27109
logs/conversion.log.3 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -103,3 +103,44 @@
2026-04-09 09:18:43 | Blue mountain state S00E04 Making the Squad.mkv | CQ failed: Size threshold not met (111.3%) 2026-04-09 09:18:43 | Blue mountain state S00E04 Making the Squad.mkv | CQ failed: Size threshold not met (111.3%)
2026-04-09 09:41:36 | Blue Mountain State (2010) - S01E05 - There's Only One Second Best (1080p x265 Panda).mkv | CQ failed: Size threshold not met (99.7%) 2026-04-09 09:41:36 | Blue Mountain State (2010) - S01E05 - There's Only One Second Best (1080p x265 Panda).mkv | CQ failed: Size threshold not met (99.7%)
2026-04-09 13:31:23 | Malcolm in the Middle (2000) - S02E01 - Traffic Jam (2) (1080p AMZN WEB-DL x265 Silence).mkv | CQ failed: Size threshold not met (98.6%) 2026-04-09 13:31:23 | Malcolm in the Middle (2000) - S02E01 - Traffic Jam (2) (1080p AMZN WEB-DL x265 Silence).mkv | CQ failed: Size threshold not met (98.6%)
2026-04-16 11:18:35 | Without a Paddle (2004) AVC TrueHD 5.1 Remux-1080p FraMeSToR.mkv | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-04-22 22:30:37 | Jury Duty (2023) - S02E01 - Onboarding (1080p AMZN WEB-DL x265 Silence)_new.mkv | Unexpected error: too many values to unpack (expected 7)
2026-04-22 22:30:40 | Jury Duty (2023) - S02E02 - Team Building (1080p AMZN WEB-DL x265 Silence)_new.mkv | Unexpected error: too many values to unpack (expected 7)
2026-04-22 23:06:42 | Making Of.mkv | CQ failed: Size threshold not met (101.0%)
2026-04-22 23:07:00 | Trailer 1.mkv | CQ failed: Size threshold not met (95.3%)
2026-04-23 21:23:32 | Euphoria (US) - S03E01 - Andale x265 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (105.1%)
2026-04-23 21:30:28 | Euphoria (US) - S03E02 - America My Dream AV1 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (115.3%)
2026-04-23 21:31:15 | costumes of euphoria.mkv | CQ failed: Size threshold not met (150.2%)
2026-04-24 09:15:19 | Behind the Scenes.mkv | CQ failed: Size threshold not met (121.5%)
2026-04-24 09:15:39 | Liam Neeson - Known Action Hero.mkv | CQ failed: Size threshold not met (106.2%)
2026-04-26 01:14:50 | Inside “Mayor of Kingstown”.mkv | Unexpected error: 'charmap' codec can't decode byte 0x9d in position 123: character maps to <undefined>
2026-04-26 01:15:50 | Perdition Making “Mayor of Kingstown”.mkv | Unexpected error: 'charmap' codec can't decode byte 0x9d in position 136: character maps to <undefined>
2026-04-26 08:46:22 | Winning Time - The Rise of the Lakers Dynasty - S01E01 - The Swan x265 AAC Bluray-1080p RARBG.mp4 | CQ failed: Size threshold not met (106.3%)
2026-04-26 08:50:30 | Winning Time - The Rise of the Lakers Dynasty - S01E02 - Is That All There Is x265 AAC Bluray-1080p RARBG.mp4 | CQ failed: Size threshold not met (110.7%)
2026-04-26 08:54:21 | Winning Time - The Rise of the Lakers Dynasty - S01E03 - The Good Life x265 AAC Bluray-1080p RARBG.mp4 | CQ failed: Size threshold not met (110.8%)
2026-04-26 13:19:46 | Behind the Scenes - Drift Space.mkv | CQ failed: Size threshold not met (117.1%)
2026-04-26 13:22:05 | Behind the Scenes - The Digital Artistry of Pacific Rim.mkv | CQ failed: Size threshold not met (159.0%)
2026-04-26 13:23:27 | Behind the Scenes - The Shatterdome.mkv | CQ failed: Size threshold not met (158.1%)
2026-04-29 16:02:32 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (100.1%)
2026-04-29 16:03:27 | Star Wars Andor (2022) - S02E01 - One Year Later (1080p DSNP WEB-DL x265 t3nzin).mkv | Unexpected error: 'charmap' codec can't decode byte 0x8d in position 286: character maps to <undefined>
2026-04-29 16:04:08 | Star Wars Andor (2022) - S02E02 - Sagrona Teema (1080p DSNP WEB-DL x265 t3nzin).mkv | Unexpected error: 'charmap' codec can't decode byte 0x8d in position 25: character maps to <undefined>
2026-04-30 20:59:09 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (100.1%)
2026-04-30 20:59:14 | Star Wars Andor (2022) - S02E01 - One Year Later (1080p DSNP WEB-DL x265 t3nzin).mkv | Unexpected error: 'charmap' codec can't decode byte 0x8d in position 176: character maps to <undefined>
2026-04-30 20:59:18 | Star Wars Andor (2022) - S02E02 - Sagrona Teema (1080p DSNP WEB-DL x265 t3nzin).mkv | Unexpected error: 'charmap' codec can't decode byte 0x8d in position 387: character maps to <undefined>
2026-04-30 21:02:00 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (100.1%)
2026-04-30 21:05:05 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | Unexpected error: Size threshold not met (132.7%)
2026-04-30 21:07:37 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | Unexpected error: Size threshold not met (100.1%)
2026-04-30 21:31:15 | Andor - S00E01 - A Disney+ Day Special Look x265 EAC3 HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (132.7%)
2026-05-12 19:59:11 | Worst Cooks in America - S29E01 - Talented & Terrible - Boot Camp's Got Talent x265 AAC HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (97.7%)
2026-05-14 22:16:20 | Shetland - 1x01 - Red Bones (1).mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-14 22:29:03 | Shetland - 1x01 - Red Bones (1).mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-14 22:34:06 | Shetland - 1x01 - Red Bones (1).mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-16 21:24:33 | Rick and Morty - S01E01 - Pilot h265 AAC Bluray-1080p SEPH1.mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-16 21:24:44 | Rick and Morty - S01E02 - Lawnmower Dog h265 AAC Bluray-1080p SEPH1.mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-16 21:24:55 | Rick and Morty - S01E03 - Anatomy Park h265 AAC Bluray-1080p SEPH1.mp4 | CQ error: Command '['ffmpeg', '-y', '-i', 'C:\\Users\\Tyler\\Documents\\GitHub\\conversion_project\\processing
2026-05-16 22:16:49 | Rick and Morty - S01E08 - Rixty Minutes h265 AAC Bluray-1080p SEPH1.mp4 | Unexpected error: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\U
2026-05-17 01:21:22 | Rick and Morty - S00E180 - The Great Yokai Battle of Akihabara x265 AAC HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (119.4%)
2026-05-17 01:22:45 | Rick and Morty - S00E187 - Summer's Sleepover x265 AAC HDTV-1080p MeGusta.mkv | CQ failed: Size threshold not met (127.2%)
2026-05-17 14:14:13 | Season 2 - Step Back in Time on Set of “The Gilded Age”.mkv | Unexpected error: 'charmap' codec can't decode byte 0x9d in position 151: character maps to <undefined>
2026-05-17 14:14:54 | Designing “The Gilded Age”.mkv | Unexpected error: 'charmap' codec can't decode byte 0x9d in position 122: character maps to <undefined>
2026-05-17 16:00:53 | Designing “The Gilded Age”.mkv | Unexpected error: 'charmap' codec can't decode byte 0x9d in position 122: character maps to <undefined>

611
main.py
View File

@ -6,6 +6,7 @@ Main entry point for batch video encoding with intelligent audio and resolution
import argparse import argparse
import csv import csv
import shlex
from pathlib import Path from pathlib import Path
from core.config_helper import load_config_xml from core.config_helper import load_config_xml
@ -64,6 +65,220 @@ def normalize_input_path(input_path: str, path_mappings: dict) -> Path:
logger.info(f"Using path as-is: {result}") logger.info(f"Using path as-is: {result}")
return result return result
# =============================
# BATCH PROCESSING
# =============================
def parse_batch_file(file_path: Path) -> list:
"""
Parse batch file (.txt or .csv) and extract paths with optional per-row parameters.
Formats:
- Simple list (.txt): One path per line, optional space-separated parameters
Example: P:\movies\Movie1 --r 720 --cq 28
- CSV (.csv): First column is path, remaining columns are optional parameters
Example: "P:\movies\Movie1","--r 720","--cq 28"
Args:
file_path: Path to batch file
Returns:
List of tuples: [(path_str, params_str), ...]
"""
batch_items = []
if file_path.suffix.lower() == ".csv":
# CSV format
with open(file_path, "r", encoding="utf-8") as f:
reader = csv.reader(f)
for row_idx, row in enumerate(reader):
if not row or not row[0].strip():
continue # Skip empty rows
path_str = row[0].strip()
# Skip header row (if it starts with "path")
if row_idx == 0 and path_str.lower().startswith("path"):
continue
# Combine remaining columns as parameters
params = " ".join(col.strip() for col in row[1:] if col.strip())
batch_items.append((path_str, params))
else:
# Simple list format (.txt or others)
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith("#"):
continue
# Split path from parameters
# Handle quoted paths like: "C:\path with spaces" --r 720
if line.startswith('"'):
# Find closing quote
end_quote = line.find('"', 1)
if end_quote != -1:
path_str = line[1:end_quote]
params = line[end_quote+1:].strip()
else:
path_str = line
params = ""
else:
# Unquoted path, split on first space
parts = line.split(None, 1)
path_str = parts[0]
params = parts[1] if len(parts) > 1 else ""
batch_items.append((path_str, params))
return batch_items
def merge_batch_args(base_args, batch_params_str: str) -> argparse.Namespace:
"""
Merge batch file row parameters with base CLI parameters.
Row parameters override base parameters for that specific path.
Args:
base_args: Base argparse.Namespace from CLI
batch_params_str: Parameter string from batch file row
Returns:
New argparse.Namespace with merged parameters
"""
# Create a copy of base args
merged = argparse.Namespace(**vars(base_args))
if not batch_params_str:
return merged
# Parse row parameters as if they were CLI arguments
try:
param_list = shlex.split(batch_params_str)
except ValueError:
# If shlex fails, try simple split
param_list = batch_params_str.split()
# Build a parser just for these arguments (reuse the same one)
# We'll manually apply known arguments
i = 0
while i < len(param_list):
arg = param_list[i]
if arg == "--cq":
if i + 1 < len(param_list):
merged.cq = int(param_list[i + 1])
i += 2
else:
i += 1
elif arg in ["--m", "--mode"]:
if i + 1 < len(param_list):
merged.transcode_mode = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--encoder":
if i + 1 < len(param_list):
merged.encoder = param_list[i + 1]
i += 2
else:
i += 1
elif arg in ["--r", "--resolution"]:
if i + 1 < len(param_list):
merged.resolution = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--test":
merged.test_mode = True
i += 1
elif arg == "--language":
if i + 1 < len(param_list):
merged.audio_language = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--filter-audio":
merged.filter_audio = True
i += 1
elif arg == "--audio-select":
if i + 1 < len(param_list):
merged.audio_select = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--audio-titles":
if i + 1 < len(param_list):
merged.audio_titles = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--audio-channels":
if i + 1 < len(param_list):
merged.audio_channels = param_list[i + 1]
i += 2
else:
i += 1
elif arg == "--keep-all-titles":
merged.strip_all_titles = False
i += 1
elif arg == "--strip-all-titles":
merged.strip_all_titles = True
i += 1
elif arg == "--unforce-subs":
merged.unforce_subs = True
i += 1
elif arg == "--no-encode":
merged.no_encode = True
i += 1
elif arg == "--force-process":
merged.force_process = True
i += 1
elif arg == "--replace":
merged.replace_file = True
i += 1
else:
i += 1
return merged
def parse_audio_dict(audio_str: str, dict_type: str) -> dict:
"""
Parse audio titles or channels string into dictionary.
Args:
audio_str: String like "0:English,1:Commentary" or "0:2,1:6"
dict_type: "titles" or "channels"
Returns:
Dictionary mapping stream indices to values, or empty dict on error
"""
if not audio_str:
return {}
result = {}
try:
pairs = audio_str.split(",")
for pair in pairs:
stream_idx, value = pair.split(":")
stream_idx = int(stream_idx.strip())
if dict_type == "channels":
# Validate channels: only 2 or 6 allowed
channels = int(value.strip())
if channels not in (2, 6):
logger.warning(f"Invalid channel count: {channels}. Only 2 or 6 allowed. Skipping.")
continue
result[stream_idx] = channels
else: # titles
result[stream_idx] = value.strip()
except (ValueError, IndexError) as e:
logger.warning(f"Error parsing audio {dict_type}: {e}")
return result
# ============================= # =============================
# Setup # Setup
# ============================= # =============================
@ -96,7 +311,7 @@ Examples:
""" """
) )
parser.add_argument("folder", help="Input folder containing video files") parser.add_argument("folder", nargs="?", default=None, help="Input folder containing video files (required unless using --paths-file)")
parser.add_argument("--cq", type=int, help="Override default CQ value") parser.add_argument("--cq", type=int, help="Override default CQ value")
parser.add_argument( parser.add_argument(
"--m", "--mode", dest="transcode_mode", default="cq", "--m", "--mode", dest="transcode_mode", default="cq",
@ -129,6 +344,14 @@ Examples:
"--audio-select", dest="audio_select", default=None, "--audio-select", dest="audio_select", default=None,
help="Pre-select audio streams to keep (comma-separated, e.g., 1,2). Skips interactive prompt" help="Pre-select audio streams to keep (comma-separated, e.g., 1,2). Skips interactive prompt"
) )
parser.add_argument(
"--audio-titles", dest="audio_titles", default=None,
help="Set custom titles for audio streams (e.g., '0:English,1:Commentary'). Format: stream_index:title,stream_index:title"
)
parser.add_argument(
"--audio-channels", dest="audio_channels", default=None,
help="Set channel count for specific audio streams (e.g., '0:2,1:6'). Format: stream_index:channels,stream_index:channels. Only 2 or 6 channels allowed"
)
parser.add_argument( parser.add_argument(
"--keep-all-titles", dest="strip_all_titles", default=True, action="store_false", "--keep-all-titles", dest="strip_all_titles", default=True, action="store_false",
help="Preserve title metadata on audio tracks (default: titles are stripped)" help="Preserve title metadata on audio tracks (default: titles are stripped)"
@ -153,10 +376,6 @@ Examples:
"--wait", "-w", dest="wait_seconds", type=int, nargs='?', const=-1, default=None, "--wait", "-w", dest="wait_seconds", type=int, nargs='?', const=-1, default=None,
help="Wait after each file (default: 30s with --no-encode, 0s otherwise). Gives Plex time to detect changes" help="Wait after each file (default: 30s with --no-encode, 0s otherwise). Gives Plex time to detect changes"
) )
parser.add_argument(
"--split", dest="split_time", default=None,
help="Split video at timestamp (e.g., 00:58:15.250). Creates two separate encodes: part1 and part2"
)
parser.add_argument( parser.add_argument(
"--travel", dest="travel_mode", default=False, action="store_true", "--travel", dest="travel_mode", default=False, action="store_true",
help="Travel mode: force 720p resolution and CQ+2, requires --output flag" help="Travel mode: force 720p resolution and CQ+2, requires --output flag"
@ -165,34 +384,333 @@ Examples:
"--output", dest="output_folder", default=None, "--output", dest="output_folder", default=None,
help="Output folder for travel mode (creates subfolder based on input folder name)" help="Output folder for travel mode (creates subfolder based on input folder name)"
) )
parser.add_argument(
"--paths-file", dest="paths_file", default=None,
help="Batch mode: Read paths from file (.txt or .csv). One path per line with optional per-row parameters"
)
args = parser.parse_args() args = parser.parse_args()
# Load configuration # Load configuration
config_path = Path(__file__).parent / "config.xml" config_path = Path(__file__).parent / "config.xml"
config = load_config_xml(config_path) config = load_config_xml(config_path)
# Normalize input path (handle Linux paths, mixed separators, etc.) # =============================
input_path = normalize_input_path(args.folder, config.get("path_mappings", {})) # BATCH MODE
# =============================
# Verify path exists and determine if it's a file or folder if args.paths_file:
if not input_path.exists(): paths_file = Path(args.paths_file)
print(f"❌ Path not found: {input_path}") if not paths_file.exists():
logger.error(f"Path not found: {input_path}") print(f"❌ Paths file not found: {paths_file}")
logger.error(f"Paths file not found: {paths_file}")
return
# Track what we've already processed
processed_items = set()
batch_queue = []
completed = 0
failed = 0
total_attempted = 0
print("=" * 80)
print(f"BATCH MODE: Processing paths from {paths_file.name}")
print(f" File will be rechecked after each item for new additions")
print("=" * 80)
logger.info(f"BATCH MODE: Starting batch processing from {paths_file}")
logger.info("File monitoring enabled - will check for new additions after each item")
# Initial load
batch_items = parse_batch_file(paths_file)
if not batch_items:
print(f"❌ No valid paths found in {paths_file}")
logger.error(f"No valid paths in batch file: {paths_file}")
return
print(f"📋 Found {len(batch_items)} initial path(s)\n")
# Create item signatures for tracking (path + params combo)
for path_str, params_str in batch_items:
item_sig = f"{path_str}|{params_str}"
if item_sig not in processed_items:
batch_queue.append((path_str, params_str))
batch_num = 1
# Process batch items with recheck after each
while batch_queue:
path_str, params_str = batch_queue.pop(0)
item_sig = f"{path_str}|{params_str}"
total_attempted += 1
print()
print("-" * 80)
print(f"BATCH [{batch_num}]: {path_str}")
if params_str:
print(f"Parameters: {params_str}")
print("-" * 80)
logger.info(f"[BATCH {batch_num}] Processing: {path_str}")
try:
# Normalize path
folder = normalize_input_path(path_str, config.get("path_mappings", {}))
# Check if folder exists
if not folder.exists():
print(f"❌ [BATCH {batch_num}] Folder not found: {folder}")
logger.error(f"[BATCH {batch_num}] Folder not found: {folder}")
processed_items.add(item_sig)
failed += 1
batch_num += 1
# Recheck file for new items
print(f"\n🔄 Rechecking {paths_file.name} for new additions...")
new_batch_items = parse_batch_file(paths_file)
for path, params in new_batch_items:
sig = f"{path}|{params}"
if sig not in processed_items and sig not in [f"{p}|{pr}" for p, pr in batch_queue]:
batch_queue.append((path, params))
print(f" ✨ New item found: {path}")
continue
# Merge batch parameters with base CLI parameters
merged_args = merge_batch_args(args, params_str)
# Handle travel mode
travel_output_folder = None
if merged_args.travel_mode:
if not merged_args.output_folder:
print(f"❌ [BATCH {batch_num}] --travel requires --output folder")
logger.error(f"[BATCH {batch_num}] --travel requires --output folder")
processed_items.add(item_sig)
failed += 1
batch_num += 1
# Recheck file for new items
print(f"\n🔄 Rechecking {paths_file.name} for new additions...")
new_batch_items = parse_batch_file(paths_file)
for path, params in new_batch_items:
sig = f"{path}|{params}"
if sig not in processed_items and sig not in [f"{p}|{pr}" for p, pr in batch_queue]:
batch_queue.append((path, params))
print(f" ✨ New item found: {path}")
continue
output_base = Path(merged_args.output_folder)
input_folder_name = folder.name
travel_output_folder = output_base / input_folder_name
travel_output_folder.mkdir(parents=True, exist_ok=True)
merged_args.resolution = "720"
default_cq = get_default_cq(folder, config, "720", merged_args.encoder)
merged_args.cq = default_cq + 2
# Validate --replace requires --no-encode
if merged_args.replace_file and not merged_args.no_encode:
print(f"❌ [BATCH {batch_num}] --replace requires --no-encode")
logger.error(f"[BATCH {batch_num}] --replace requires --no-encode")
processed_items.add(item_sig)
failed += 1
batch_num += 1
# Recheck file for new items
print(f"\n🔄 Rechecking {paths_file.name} for new additions...")
new_batch_items = parse_batch_file(paths_file)
for path, params in new_batch_items:
sig = f"{path}|{params}"
if sig not in processed_items and sig not in [f"{p}|{pr}" for p, pr in batch_queue]:
batch_queue.append((path, params))
print(f" ✨ New item found: {path}")
continue
# Set wait time
if merged_args.wait_seconds is None:
merged_args.wait_seconds = 0
elif merged_args.wait_seconds == -1:
merged_args.wait_seconds = 30 if merged_args.no_encode else 0
# Parse audio dicts from merged args
audio_titles_dict = parse_audio_dict(merged_args.audio_titles, "titles") if merged_args.audio_titles else {}
audio_channels_dict = parse_audio_dict(merged_args.audio_channels, "channels") if merged_args.audio_channels else {}
# Process folder
process_folder(
folder, merged_args.cq, merged_args.transcode_mode, merged_args.resolution,
config, TRACKER_FILE, merged_args.test_mode, merged_args.audio_language,
merged_args.filter_audio, merged_args.audio_select, merged_args.encoder,
merged_args.strip_all_titles, travel_output_folder, merged_args.unforce_subs,
merged_args.no_encode, merged_args.force_process, merged_args.replace_file,
merged_args.wait_seconds, audio_titles=audio_titles_dict, audio_channels=audio_channels_dict
)
print(f"✓ [BATCH {batch_num}] Completed: {folder.name}")
logger.info(f"[BATCH {batch_num}] Completed successfully")
processed_items.add(item_sig)
completed += 1
batch_num += 1
# Recheck file for new items after successful completion
print(f"\n🔄 Rechecking {paths_file.name} for new additions...")
new_batch_items = parse_batch_file(paths_file)
new_count = 0
for path, params in new_batch_items:
sig = f"{path}|{params}"
if sig not in processed_items and sig not in [f"{p}|{pr}" for p, pr in batch_queue]:
batch_queue.append((path, params))
print(f" ✨ New item found: {path}")
new_count += 1
if new_count == 0:
print(f" (no new additions)")
except Exception as e:
print(f"❌ [BATCH {batch_num}] Error: {e}")
logger.error(f"[BATCH {batch_num}] Error: {e}", exc_info=True)
processed_items.add(item_sig)
failed += 1
batch_num += 1
# Recheck file for new items even on error
print(f"\n🔄 Rechecking {paths_file.name} for new additions...")
try:
new_batch_items = parse_batch_file(paths_file)
new_count = 0
for path, params in new_batch_items:
sig = f"{path}|{params}"
if sig not in processed_items and sig not in [f"{p}|{pr}" for p, pr in batch_queue]:
batch_queue.append((path, params))
print(f" ✨ New item found: {path}")
new_count += 1
if new_count == 0:
print(f" (no new additions)")
except Exception as recheck_error:
print(f"⚠️ Error rechecking file: {recheck_error}")
logger.warning(f"Error during file recheck: {recheck_error}")
# Final check for any items added while processing the last batch
print()
print("=" * 80)
print("✓ BATCH QUEUE COMPLETE - Performing final file check...")
print("=" * 80)
final_items = parse_batch_file(paths_file)
final_new = []
for path, params in final_items:
sig = f"{path}|{params}"
if sig not in processed_items:
final_new.append((path, params))
if final_new:
print(f"📋 Found {len(final_new)} new item(s) added during processing!\n")
for path_str, params_str in final_new:
item_sig = f"{path_str}|{params_str}"
total_attempted += 1
print("-" * 80)
print(f"BATCH [{batch_num}]: {path_str}")
if params_str:
print(f"Parameters: {params_str}")
print("-" * 80)
logger.info(f"[BATCH {batch_num}] Processing: {path_str}")
try:
folder = normalize_input_path(path_str, config.get("path_mappings", {}))
if not folder.exists():
print(f"❌ [BATCH {batch_num}] Folder not found: {folder}")
logger.error(f"[BATCH {batch_num}] Folder not found: {folder}")
failed += 1
batch_num += 1
continue
merged_args = merge_batch_args(args, params_str)
travel_output_folder = None
if merged_args.travel_mode:
if not merged_args.output_folder:
print(f"❌ [BATCH {batch_num}] --travel requires --output folder")
logger.error(f"[BATCH {batch_num}] --travel requires --output folder")
failed += 1
batch_num += 1
continue
output_base = Path(merged_args.output_folder)
input_folder_name = folder.name
travel_output_folder = output_base / input_folder_name
travel_output_folder.mkdir(parents=True, exist_ok=True)
merged_args.resolution = "720"
default_cq = get_default_cq(folder, config, "720", merged_args.encoder)
merged_args.cq = default_cq + 2
if merged_args.replace_file and not merged_args.no_encode:
print(f"❌ [BATCH {batch_num}] --replace requires --no-encode")
logger.error(f"[BATCH {batch_num}] --replace requires --no-encode")
failed += 1
batch_num += 1
continue
if merged_args.wait_seconds is None:
merged_args.wait_seconds = 0
elif merged_args.wait_seconds == -1:
merged_args.wait_seconds = 30 if merged_args.no_encode else 0
# Parse audio dicts from merged args
audio_titles_dict = parse_audio_dict(merged_args.audio_titles, "titles") if merged_args.audio_titles else {}
audio_channels_dict = parse_audio_dict(merged_args.audio_channels, "channels") if merged_args.audio_channels else {}
process_folder(
folder, merged_args.cq, merged_args.transcode_mode, merged_args.resolution,
config, TRACKER_FILE, merged_args.test_mode, merged_args.audio_language,
merged_args.filter_audio, merged_args.audio_select, merged_args.encoder,
merged_args.strip_all_titles, travel_output_folder, merged_args.unforce_subs,
merged_args.no_encode, merged_args.force_process, merged_args.replace_file,
merged_args.wait_seconds, audio_titles=audio_titles_dict, audio_channels=audio_channels_dict
)
print(f"✓ [BATCH {batch_num}] Completed: {folder.name}")
logger.info(f"[BATCH {batch_num}] Completed successfully")
completed += 1
batch_num += 1
except Exception as e:
print(f"❌ [BATCH {batch_num}] Error: {e}")
logger.error(f"[BATCH {batch_num}] Error: {e}", exc_info=True)
failed += 1
batch_num += 1
else:
print("(no new items found)")
# Final summary
print()
print("=" * 80)
print(f"✓ BATCH PROCESSING COMPLETE")
print(f" Total items processed: {total_attempted}")
print(f" ✓ Succeeded: {completed}")
if failed > 0:
print(f" ❌ Failed: {failed}")
print("=" * 80)
logger.info(f"Batch processing finished: {completed} succeeded, {failed} failed out of {total_attempted}")
return return
# Handle file vs folder input # =============================
target_file = None # SINGLE MODE
if input_path.is_file(): # =============================
# Single file target if not args.folder:
target_file = input_path parser.print_help()
folder = input_path.parent return
print(f"📄 Target file: {target_file.name}")
logger.info(f"Processing single file: {target_file.name}") # Normalize input path (handle Linux paths, mixed separators, etc.)
else: folder = normalize_input_path(args.folder, config.get("path_mappings", {}))
# Folder target (process all files)
folder = input_path # Verify folder exists
print(f"📁 Target folder: {folder}") if not folder.exists():
logger.info(f"Processing folder: {folder}") print(f"❌ Folder not found: {folder}")
logger.error(f"Folder not found: {folder}")
return
# Handle travel mode # Handle travel mode
travel_output_folder = None travel_output_folder = None
@ -227,6 +745,45 @@ Examples:
logger.error("--replace flag used without --no-encode") logger.error("--replace flag used without --no-encode")
return return
# Parse audio titles from CLI argument
audio_titles_dict = {}
if args.audio_titles:
try:
# Format: "0:English,1:Commentary,2:Descriptive Audio"
pairs = args.audio_titles.split(",")
for pair in pairs:
stream_idx, title = pair.split(":")
audio_titles_dict[int(stream_idx.strip())] = title.strip()
logger.info(f"Audio titles: {audio_titles_dict}")
except (ValueError, IndexError):
print("❌ Invalid --audio-titles format. Use: '0:English,1:Commentary'")
logger.error(f"Invalid audio titles format: {args.audio_titles}")
return
# Parse audio channels from CLI argument
audio_channels_dict = {}
if args.audio_channels:
try:
# Format: "0:2,1:6" (stream_index:channel_count)
pairs = args.audio_channels.split(",")
for pair in pairs:
stream_idx, channels = pair.split(":")
stream_idx = int(stream_idx.strip())
channels = int(channels.strip())
# Validate that only 2 or 6 channels are allowed
if channels not in (2, 6):
print(f"❌ Invalid channel count: {channels}. Only 2 or 6 channels allowed")
logger.error(f"Invalid channel count: {channels}. Only 2 or 6 channels allowed")
return
audio_channels_dict[stream_idx] = channels
logger.info(f"Audio channels: {audio_channels_dict}")
except (ValueError, IndexError):
print("❌ Invalid --audio-channels format. Use: '0:2,1:6'")
logger.error(f"Invalid audio channels format: {args.audio_channels}")
return
# Set wait time default: 30s if --no-encode and --wait used, 0 otherwise # Set wait time default: 30s if --no-encode and --wait used, 0 otherwise
# -1 means --wait was used without a value (use intelligent default) # -1 means --wait was used without a value (use intelligent default)
if args.wait_seconds is None: if args.wait_seconds is None:
@ -234,8 +791,8 @@ Examples:
elif args.wait_seconds == -1: elif args.wait_seconds == -1:
args.wait_seconds = 30 if args.no_encode else 0 # --wait used without value args.wait_seconds = 30 if args.no_encode else 0 # --wait used without value
# Process folder or single file # Process folder
process_folder(folder, args.cq, args.transcode_mode, args.resolution, config, TRACKER_FILE, args.test_mode, args.audio_language, args.filter_audio, args.audio_select, args.encoder, args.strip_all_titles, travel_output_folder, args.unforce_subs, args.no_encode, args.force_process, args.replace_file, args.wait_seconds, args.split_time, target_file) process_folder(folder, args.cq, args.transcode_mode, args.resolution, config, TRACKER_FILE, args.test_mode, args.audio_language, args.filter_audio, args.audio_select, args.encoder, args.strip_all_titles, travel_output_folder, args.unforce_subs, args.no_encode, args.force_process, args.replace_file, args.wait_seconds, audio_titles=audio_titles_dict, audio_channels=audio_channels_dict)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -1,7 +1,19 @@
"P:\movies\Nobody 2 (2025)" --strip-all-titles # Batch Encoding Paths - Simple List Format
"P:\movies\The French Dispatch (2021)" --strip-all-titles # Each line: path [optional parameters]
"P:\movies\Let's Be Cops (2014)" --strip-all-titles # Example formats:
"P:\movies\The Secret World of Arrietty (2010)" --strip-all-titles # P:\movies\Movie1
"P:\movies\Akira (1988)" --strip-all-titles # P:\movies\Movie2 --r 720
"P:\movies\Space Sweepers (2021)" --strip-all-titles # P:\movies\Movie3 --r 720 --cq 28 --encoder av1
"P:\movies\John Carter (2012)" --strip-all-titles
"P:\movies\Mad Max - Fury Road - Black & Chrome Edition (2015)" --filter-audio
"P:\tv\Adventuring Academy" --title-suffix " WebRip-1080p"
"P:\tv\Dimension 20's Adventuring Party" --title-suffix " WebRip-1080p"
"P:\tv\Dimension 20" --title-suffix " WebRip-1080p"
"P:\tv\Crowd Control" --title-suffix " WebRip-1080p"
"P:\tv\Game Changer" --title-suffix "WebRip-1080p"
"P:\tv\Make Some Noise" --title-suffix " WebRip-1080p"
"P:\tv\Parlor Room" --title-suffix " WebRip-1080p"
"P:\tv\Smartypants" --title-suffix " WebRip-1080p"
"P:\tv\Um, Actually" --title-suffix " WebRip-1080p"
"P:\tv\Very Important People" --title-suffix " WebRip-1080p"
"P:\movies\GOAT (2026)" --r 720

8
paths_batch_example.csv Normal file
View File

@ -0,0 +1,8 @@
path,resolution,cq,encoder,notes
"P:\movies\Nobody 2 (2025)","--r 1080","--cq 32","--encoder hevc","4K downscale"
"P:\movies\The French Dispatch (2021)","--r 720","--cq 28","--encoder av1","Low quality source"
"P:\movies\Let's Be Cops (2014)","--r 720","","--encoder av1","720p original"
"P:\movies\The Secret World of Arrietty (2010)","","--cq 26","","Auto resolution, best quality"
"P:\movies\Akira (1988)","--r 1080","--cq 28","--encoder hevc","Anime archive format"
"P:\movies\Space Sweepers (2021)","--r 1080","","","Use defaults for this one"
"P:\movies\John Carter (2012)","--r 720","--cq 30","--encoder av1","Reduced file size priority"
1 path resolution cq encoder notes
2 P:\movies\Nobody 2 (2025) --r 1080 --cq 32 --encoder hevc 4K downscale
3 P:\movies\The French Dispatch (2021) --r 720 --cq 28 --encoder av1 Low quality source
4 P:\movies\Let's Be Cops (2014) --r 720 --encoder av1 720p original
5 P:\movies\The Secret World of Arrietty (2010) --cq 26 Auto resolution, best quality
6 P:\movies\Akira (1988) --r 1080 --cq 28 --encoder hevc Anime archive format
7 P:\movies\Space Sweepers (2021) --r 1080 Use defaults for this one
8 P:\movies\John Carter (2012) --r 720 --cq 30 --encoder av1 Reduced file size priority

View File

@ -1,47 +0,0 @@
@echo off
REM ====================================================================
REM Batch Transcode Queue Runner
REM Reads paths.txt and processes each line as a separate encode job
REM Each line should be a Python command with arguments, e.g.:
REM --r 720 --m bitrate "C:\Videos\TV Show"
REM --r 1080 --cq 28 "C:\Videos\Movies"
REM ====================================================================
setlocal enabledelayedexpansion
echo.
echo ====================================================================
echo Starting Batch Transcode Queue
echo ====================================================================
echo.
set "JOB_COUNT=0"
set "SUCCESS_COUNT=0"
set "FAILED_COUNT=0"
for /f "usebackq delims=" %%i in ("paths.txt") do (
set /a JOB_COUNT+=1
echo.
echo [Job !JOB_COUNT!] Processing: %%i
echo ======================================
py main.py %%i
if errorlevel 1 (
set /a FAILED_COUNT+=1
echo [Job !JOB_COUNT!] FAILED - Continuing to next item...
) else (
set /a SUCCESS_COUNT+=1
echo [Job !JOB_COUNT!] SUCCESS
)
)
echo.
echo ====================================================================
echo Batch Transcode Queue Complete
echo ====================================================================
echo Total Jobs: !JOB_COUNT!
echo Successful: !SUCCESS_COUNT!
echo Failed: !FAILED_COUNT!
echo ====================================================================
pause