A single-file, batch transcoding GUI for Linux built with PySide6. Wraps av1an for chunk-parallel AV1/VP9/x265 encoding with a retro-futuristic MMD3 media console aesthetic.

This commit is contained in:
Jeremy Anderson 2026-07-05 11:27:03 -04:00
commit 510c3855ac
5 changed files with 4347 additions and 0 deletions

54
.gitignore vendored Normal file
View File

@ -0,0 +1,54 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
*.egg-info/
*.egg
dist/
build/
eggs/
sdist/
# Virtual environments
.venv/
venv/
ENV/
# PySide6 / Qt generated files
*.pro
*.pri
moc_*.cpp
ui_*.h
qrc_*.py
*.qmlc
*.jsc
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
*.kate-swp
# OS files
.DS_Store
Thumbs.db
*.tmp
# av1an build artifacts (generated at runtime)
/tmp/av1an-build/
# Encoded output (user data, not project files)
*.scaled_tmp.mkv
*.submux_tmp
# Logs
*.log
# my-project workspace (development environment, not part of the repo)

21
LICENSE Executable file
View File

@ -0,0 +1,21 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
See https://www.gnu.org/licenses/agpl-3.0.txt for the full license text.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

179
README.md Executable file
View File

@ -0,0 +1,179 @@
# OpenTranscode
A single-file, batch transcoding GUI for Linux built with PySide6. Wraps **av1an** for chunk-parallel AV1/VP9/x265 encoding with a retro-futuristic MMD3 media console aesthetic.
![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-blue)
![PySide6](https://img.shields.io/badge/PySide6-6.6%2B-green)
![Linux](https://img.shields.io/badge/Platform-Linux-orange)
![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-yellow)
## Features
- **Batch encoding** — Drop a source folder, pick settings, hit encode. Processes every matching file recursively.
- **Three open codecs** — AV1 (SVT-AV1), VP9 (libvpx), x265 (HEVC) with per-codec preset selection.
- **Config-driven profiles** — Codecs, audio, containers, and resolutions defined as dataclass tables — no nested if/else chains.
- **av1an chunk-parallel encoding** — Scene-based chunking with multi-worker parallelism. Automatically detects `--chunk-method` support and scales workers to physical CPU cores minus one.
- **Lossless intermediate pipeline** — Resolution changes use a lossless libx264 ultrafast CRF 0 pre-scale pass (yuv420p10le) with duration integrity verification before the final encode.
- **Forced subtitle muxing** — Optional soft-subtitle remux post-encode. Prefers forced-disposition tracks. Container-aware: WebVTT for WebM, stream copy for MKV.
- **Audio normalization** — Rotary volume knob (-20 dB to +6 dB gain).
- **Real-time FFmpeg library probing** — Greys out audio codecs whose underlying FFmpeg libraries are missing.
- **Distro-aware dependency management** — Auto-detects Arch, Debian/Ubuntu, Fedora/RHEL/Rocky/Alma, openSUSE, and NixOS. Installs packages, handles av1an version conflicts, and builds from source when repos are stale.
- **Post-encode integrity checks** — Verifies output file size (≥ 5% of source) and duration (≥ 95% of source) before accepting. Failed outputs are deleted automatically.
- **Batch delete with confirmation** — Single pre-flight prompt showing file count and total size. Sources deleted only after individual verification passes.
- **Custom radio-knob widgets** — Retro rotary controls for CRF and audio normalization with snap-to-tick, glow indicators, and mouse/scroll interaction.
- **MMD3 theme** — Brushed aluminum, amber/green LED displays, beveled metallic panels via QSS.
## Requirements
| Dependency | Minimum Version | Purpose |
|---|---|---|
| Python | 3.12+ | Runtime |
| PySide6 | 6.6+ | Qt6 GUI framework |
| av1an | 0.4.0+ | Chunk-parallel encoder frontend |
| FFmpeg | 5.0+ (with libsvtav1, libvpx, libx265, libopus, libvorbis, flac) | Encoding, probing, remuxing |
| ffprobe | (bundled with FFmpeg) | Stream analysis and validation |
| mkvtoolnix | any | MKV container support |
| Rust/Cargo | latest stable | Building av1an from source (if repo version is stale) |
### Per-Distro Package Lists
**Arch / Manjaro / Endeavouros / Garuda / CachyOS:**
`ffmpeg mkvtoolnix-cli nasm cython gcc cmake git ninja python-pip svt-av1 rav1e aom libvpx x265 libopus libvorbis flac`
**Debian / Ubuntu / Linux Mint / Pop!_OS:**
`ffmpeg av1an mkvtoolnix svt-av1 rav1e aom-tools libvpx-tools x265 nasm gcc cmake git cargo rustc`
**Fedora:**
`ffmpeg mkvtoolnix svt-av1 rav1e aom libvpx x265 nasm gcc cmake git ninja-build cargo rustc` (requires RPM Fusion)
**RHEL / CentOS / Rocky / Alma:**
Same as Fedora, plus `epel-release` and RPM Fusion.
**openSUSE (Tumbleweed/Leap):**
`ffmpeg av1an mkvtoolnix svt-av1 rav1e aom-tools libvpx-tools x265 nasm gcc cmake git ninja cargo rustc` (requires Packman repo)
**NixOS:**
Manual configuration required — see quickstart.
> All distros: if the packaged av1an is below 0.4.0, the app automatically builds from git.
## Install & Run
```bash
# Clone the repo
git clone https://github.com/YOUR_USER/open-transcode.git
cd open-transcode
# Install Python dependency
pip install PySide6
# Run — dependency auto-install triggers on first launch
python open-transcode-master.py
```
On first launch, if av1an or FFmpeg is missing, the app detects your distro and offers to install everything automatically (Arch, Debian, Fedora, openSUSE). NixOS users will see a config snippet to paste into their configuration.
## Project Structure
```
open-transcode/
├── open-transcode-master.py # Single-file application (~2800 lines)
├── README.md # This file
├── quickstart.md # Setup & first-encode walkthrough
├── LICENSE # AGPL-3.0
└── .gitignore # Python/Qt/OS artifacts
```
## How It Works
### Encoding Pipeline
```
Source file
├─ ffprobe pre-validation (skip if no video stream or < 0.5s)
├─ [If resolution != Original]
│ └─ Lossless pre-scale → {file}.scaled_tmp.mkv
│ (libx264 ultrafast CRF 0, yuv420p10le, scale+pad filter)
│ └─ Duration integrity check (≥ 95% of source)
├─ av1an encode (chunk-parallel, scene-based splitting)
│ └─ Workers: physical_cores - 1
├─ Post-encode verification
│ ├─ Size check: output ≥ 5% of source
│ └─ Duration check: output ≥ 95% of source
├─ [If subtitle language selected]
│ └─ Soft subtitle remux (forced track preferred)
│ ├─ MKV: -c:s copy (any codec)
│ └─ WebM: -c:s webvtt (container requirement)
└─ [If delete-source enabled]
└─ Delete source (only after verification passes)
```
### Distro Auto-Detection
On startup, reads `/etc/os-release` and matches against known distro families. Each family has:
- Package manager and install command template
- Extra binary search paths (e.g. `~/.cargo/bin` for Rust-built tools)
- Distro-specific av1an encoder name quirks
- A dedicated `*_prep_deps()` function with fine-grained package installation
### Config-Driven Profiles
All codec/container/audio/resolution options are defined as `@dataclass` tables:
- `VIDEO_CODECS` — Label, av1an encoder name, CRF range, default CRF, params function, preset map
- `AUDIO_PROFILES` — Label + FFmpeg parameter tokens
- `CONTAINER_PROFILES` — Label + file extension
- `RESOLUTION_PRESETS` — Label, category (standard/wide/ultrawide/original), dimensions
- `SUBTITLE_OPTIONS` — Label + ISO 639-2 language code (or None)
The UI indexes into these tables — zero conditional logic for profile selection.
## Supported Input Formats
Default: `.mp4 .mkv .avi .mov .ts .m4v .flv .wmv .webm .mpg .mpeg`
Configurable at runtime via the FILTER field in the UI (comma-separated extensions).
## Supported Output Formats
| Container | Video Codecs | Audio Codecs | Subtitles |
|---|---|---|---|
| MKV (.mkv) | AV1, VP9, x265 | Opus, Vorbis, FLAC | Any (stream copy) |
| WebM (.webm) | AV1, VP9 | Opus, Vorbis, FLAC | WebVTT only |
## UI Controls
| Control | Type | Range / Options |
|---|---|---|
| SOURCE / SINK | Path fields + browse | Any directory |
| VIDEO | Combo | AV1 (SVT-AV1), VP9, x265 (HEVC) |
| PRESET | Combo | 4 per codec (e.g. Slow/Medium/Fast/Faster) |
| AUDIO | Combo | Opus 96k/128k/64k, Vorbis 128k/192k, FLAC |
| CONTAINER | Combo | MKV, WebM |
| RESOLUTION | Combo | Original, 720p4K (16:9 / 21:9 / 32:9) |
| SUBS | Combo | None, English (forced track preferred) |
| CRF | Rotary knob | 1852 (codec-dependent range) |
| AUDIO NORM | Rotary knob | -20 dB to +6 dB (0 = off) |
| DELETE SOURCE | Checkbox | Per-batch confirmation prompt |
## Troubleshooting
**av1an build fails:** Ensure Rust is installed (`rustup`) and you have ~2 GB of free disk space in `/tmp`. The build takes 515 minutes depending on hardware.
**Codec greyed out:** The corresponding FFmpeg library is missing. Install it via your package manager or re-run the auto-prep.
**"chunk-method not recognized":** Your av1an is below 0.4.0. The auto-prep should handle this by building from git. If it doesn't, manually remove the packaged av1an and rebuild.
**WebM + non-WebVTT subtitles fail:** WebM only supports WebVTT subtitles. The app auto-converts during remux. If the source subtitle codec can't be converted, the mux is silently skipped.
**Permission denied on av1an install:** The git build attempts `sudo cp` to `/usr/local/bin`. Ensure your user has sudo access, or manually copy the binary from `/tmp/av1an-build/target/release/av1an`.
## License
AGPL-3.0 — see [LICENSE](LICENSE).

3940
open-transcode.py Normal file

File diff suppressed because it is too large Load Diff

153
quickstart.md Normal file
View File

@ -0,0 +1,153 @@
# Quickstart — OpenTranscode
Get from zero to your first batch encode in under 10 minutes.
## Prerequisites
- **Linux** (x86_64, any major distro)
- **Python 3.12+** with pip
- **~2 GB free disk** in `/tmp` (for av1an source build, if needed)
- **sudo access** (for system package installation)
## Step 1 — Get the Code
```bash
git clone https://git.dcos.net/dcosnet/open-transcode.git
cd open-transcode
```
## Step 2 — Install PySide6
```bash
pip install PySide6
```
If you hit permission errors, use a venv:
```bash
python -m venv .venv
source .venv/bin/activate
pip install PySide6
```
## Step 3 — Launch
```bash
python open-transcode.py
```
The window opens with the MMD3 console theme. The ENCODE button is disabled — the app needs to probe your system first.
## Step 4 — First-Run Auto-Setup
### What happens automatically
~500ms after launch, the app:
1. **Detects your distro** by reading `/etc/os-release` (Arch, Debian, Fedora, openSUSE, NixOS, or generic).
2. **Probes for binaries** — searches distro-specific paths for `av1an`, `ffmpeg`, and `ffprobe`.
3. **Checks av1an version** — needs ≥ 0.4.0 (for `--chunk-method` support).
4. **Probes FFmpeg libraries** — verifies libsvtav1, libvpx, libx265, libopus, libvorbis, and flac availability.
5. **If anything is missing**, spawns a background thread that:
- Installs all required packages via your distro's package manager.
- If av1an is too old, removes it and builds from source (git clone + cargo build).
- Re-probes the environment after installation completes.
You'll see the log box filling with status messages. Wait for the ENCODE button to light up.
### NixOS (manual setup)
NixOS can't auto-install packages at runtime. Add this to your configuration:
```nix
environment.systemPackages = with pkgs; [
ffmpeg-full av1an svt-av1 rav1e aom libvpx x265
mkvtoolnix nasm gcc cmake git ninja cargo rustc
opus libvorbis flac
];
```
Then rebuild: `sudo nixos-rebuild switch`
### Fedora / RHEL — RPM Fusion
If you're on Fedora or RHEL-like systems, the auto-prep installs RPM Fusion repos before attempting FFmpeg. This is handled automatically — just wait for it.
## Step 5 — Your First Encode
### 5a. Set up folders
The defaults are `~/Videos/INCOMING` (source) and `~/Videos/ARCHIVE` (output). Create them or click the browse buttons to pick your own.
```bash
mkdir -p ~/Videos/INCOMING ~/Videos/ARCHIVE
```
Drop some video files into `~/Videos/INCOMING`.
### 5b. Pick your settings
| Setting | Recommended first run | Why |
|---|---|---|
| VIDEO | AV1 (SVT-AV1) | Best compression, modern standard |
| PRESET | Medium | Good balance of speed and quality |
| AUDIO | Opus 128k | Excellent quality at low bitrate |
| CONTAINER | MKV | Universal, supports all codecs and subtitle formats |
| RESOLUTION | Original | Skip pre-scaling for fastest first run |
| SUBS | None | Skip subtitle muxing for first test |
| CRF knob | 30 | Reasonable file size reduction on most sources |
| AUDIO NORM knob | 0 (off) | No gain adjustment |
### 5c. Hit ENCODE
Click the amber `> ENCODE` button. The log box shows per-file progress:
```
> [1/5] Encoding: video1.mkv → /home/you/Videos/ARCHIVE/video1_archived.mkv
> av1an: workers=7 encoder=svt_av1 chunk-method=select
> ✓ video1.mkv — 1.2 GB → 340 MB (28.3%) duration match: 99.8%
> [2/5] Encoding: video2.mp4 → ...
```
### 5d. Verify output
Check `~/Videos/ARCHIVE/`. Each file should play correctly in mpv, VLC, or any modern player.
## Common First-Run Issues
### "ENCODE button stays disabled"
The environment probe found a critical issue. Check the log box for red/warning messages. Common causes:
- **No internet** — auto-prep can't fetch packages or clone av1an from git.
- **av1an build failed** — scroll up in the log for the cargo error. Usually a missing Rust toolchain.
- **FFmpeg missing libraries** — the auto-prep should install them. If not, manually install the FFmpeg "full" variant for your distro.
### "Codec greyed out in AUDIO dropdown"
The corresponding FFmpeg library isn't installed. For example, if FLAC is greyed out, install `flac` (Arch) or `flac libflac-dev` (Debian). The auto-prep handles this, but if you skipped it, re-launch and let it run.
### Encoding is slow
- **Try a faster preset** (Faster instead of Slow/Medium).
- **Raise the CRF** — higher = smaller file = faster encode (but lower quality).
- **Check your worker count** — logged at the start of each encode. It's `physical_cores - 1`. If it says 1, your CPU topology detection may have fallen back to a conservative estimate.
### Output file is much larger than expected
- **Lower the CRF** — you may have it set too low (high quality, large file).
- **x265/VP9 at low CRF** produces significantly larger files than AV1 at the same CRF.
- **FLAC audio** is lossless and can be 500 MB+ for a 2-hour movie. Use Opus instead.
## Next Steps
- **Try resolution scaling** — pick 1080p or 720p to normalize mixed-resolution batches.
- **Enable subtitles** — switch SUBS to "English" for forced-track soft subs.
- **Batch delete** — check "DELETE SOURCE AFTER VERIFY" to auto-remove originals after verified encoding. You'll get a confirmation dialog showing total file count and size before anything is deleted.
- **Audio normalization** — twist the AUDIO NORM knob if your sources have inconsistent volume. +3 dB is a good starting point for quiet sources.
## Keyboard & Mouse
- **CRF / Volume knobs** — click and drag, or scroll the mouse wheel.
- **Knobs snap to ticks** by default for precise values.
- **Log box** — scrollable, read-only. Copy text with mouse selection.