# FFmpeg Wrapper A desktop GUI for common ffmpeg jobs: remuxing MKV files to Jellyfin-friendly MP4s, choosing which audio tracks to keep, stripping audio, re-encoding, and scaling. Works on single files or whole batches. It's a single executable for Windows and Linux, built with Python, Qt (PySide6) and PyInstaller. ![icon](assets/icon.png) ## Features - **Single file or batch.** Use *Add Files*, *Add Folder* (recursive), or drag and drop. Files are probed in the background and shown with duration, video info, and audio and subtitle counts. - **Target container.** MP4, MKV, MOV, M4V, WebM, AVI or MPEG-TS. The encoder lists only show codecs the chosen container can hold. - **Audio track picker.** Every audio track in the selected file is listed with its language, codec, channels and title. Tick the tracks you want and drag them into order. The first ticked track becomes the default. **Apply to All Files** copies your choice to the rest of the queue, matching tracks by language, codec and layout, so a season of episodes takes one click. - **Strip audio.** Set Audio mode to *Strip audio*. - **Keep streams unaltered.** *Copy* mode remuxes video and/or audio without re-encoding. *Auto* copies whatever the container supports and re-encodes only what it can't hold (for example DTS/TrueHD to AAC for MP4). - **Up/downscale video.** Pick 360p up to 8K, or a custom WxH, with aspect ratio kept and Lanczos scaling. Portrait and rotated phone videos are handled. You can also change the frame rate. Encoders: H.264, HEVC, AV1, VP9, MPEG-4, plus NVENC, QuickSync and AMF if your ffmpeg has them. There are CRF quality and speed preset controls. - **Up/downmix audio.** Change channels (mono, stereo, 5.1, 7.1), sample rate, bitrate, and codec (AAC, AC-3, E-AC-3, Opus, MP3, Vorbis, FLAC, ALAC, PCM). - **Output folder.** Save next to the source or in a chosen folder. You can add a filename suffix and choose what happens when the output file already exists (keep both, overwrite, or skip). The source file is never overwritten. - **Subtitles** are kept where possible. MP4 and MOV turn text subs into `mov_text`, and image subs (PGS) are dropped with a note in the log. MKV keeps everything, including font attachments. - MP4/MOV outputs get `+faststart`, and HEVC is tagged `hvc1` for Apple and TV compatibility. - The window shows per-file and overall progress, has a **Stop** button, and keeps a full log. **Show Command** prints the exact ffmpeg command so you can copy it. - ffmpeg writes to `name.part.ext` and the file is renamed only on success, so a failed or cancelled job never leaves a half-written file. ## Getting ffmpeg The app looks for `ffmpeg` and `ffprobe` in this order: 1. The folder set in **Settings > Set FFmpeg Location...** 2. Next to the executable (or in `ffmpeg/`, `ffmpeg/bin/` or `bin/` beside it) 3. Your `PATH` The release archives (`FFmpegWrapper--windows-x64.zip` / `-linux-x64.tar.gz`) already include ffmpeg and ffprobe next to the executable, with ffmpeg's license as `ffmpeg-LICENSE.txt`. If you use the bare executable, install ffmpeg (`sudo apt install ffmpeg`, `winget install ffmpeg`, ...) or point the app at it. ## Running from source ```bash python -m venv .venv .venv/bin/pip install -r requirements-dev.txt # Windows: .venv\Scripts\pip ... python scripts/fetch_ffmpeg.py # optional: downloads ffmpeg into ./ffmpeg/bin python run.py ``` Tests: `python -m pytest`. The integration tests run real conversions when ffmpeg is found, either on `PATH` or through `FFWRAP_FFMPEG_DIR=ffmpeg/bin`. ## Building the executables PyInstaller does not cross-compile. Build the Windows `.exe` on Windows and the Linux binary on Linux. ```bash pip install -r requirements-dev.txt python build.py # -> dist/FFmpegWrapper or dist/FFmpegWrapper.exe python build.py --ffmpeg-dir ffmpeg/bin # also bundles ffmpeg + ffprobe + their license into a .zip / .tar.gz python scripts/smoke_test.py dist/FFmpegWrapper # optional: headless start-up check ``` `--onedir` builds a folder instead of a single file. It starts faster because nothing has to be unpacked on launch. **CI:** [.github/workflows/build.yml](.github/workflows/build.yml) builds, tests and smoke-tests both platforms on every `v*` tag (or a manual run) and attaches the archives to the release. Gitea and Forgejo Actions can run it too, but they need a Windows runner registered. ### Notes - **Linux:** the binary needs glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+, Mint 21+). It bundles the Qt XCB libraries, but uses the system's OpenGL/EGL driver libraries. To get a menu entry, copy `assets/icon.png` and write a `.desktop` file that points at the binary. - **PySide6 is pinned below 6.12.** PySide6 6.12.0 mis-counts references to Python's `None` (in `QComboBox.clear()`/`currentData()`), which crashes the app on Python 3.11. Python 3.12+ is not affected, but keep the pin until a fixed PySide6 ships. - **ffmpeg licensing:** the bundled ffmpeg builds come from [BtbN/FFmpeg-Builds](https://github.com/BtbN/FFmpeg-Builds) and are GPLv3, so their license has to ship with them. `scripts/fetch_ffmpeg.py` saves it as `ffmpeg/LICENSE.txt`, and `build.py --ffmpeg-dir` copies it into the archive as `ffmpeg-LICENSE.txt`. It looks in the ffmpeg folder and the folder above it, and stops with an error if the license isn't in either. - Settings (last options, window size, ffmpeg location) are saved per user through Qt's QSettings: the registry on Windows, `~/.config/ffwrap/FFmpegWrapper.conf` on Linux. ## Project layout ``` ffwrap/ formats.py container/encoder tables and compatibility rules (no Qt) probe.py ffprobe -> MediaInfo/Stream dataclasses command.py Options -> ffmpeg arguments, output naming, audio-track matching (no Qt) tools.py locating ffmpeg/ffprobe, encoder detection gui/ main window, queue model, QProcess batch runner build.py PyInstaller build + packaging scripts/ fetch_ffmpeg.py, smoke_test.py, make_icon.py tests/ unit tests + real-ffmpeg integration tests ``` ## License FFmpeg Wrapper is public domain, released under [the Unlicense](LICENSE). Kopimi: copy it, change it, share it, sell it. No permission needed. That covers this project's own code. The ffmpeg and ffprobe binaries in the release archives are GPLv3 (license in `ffmpeg-LICENSE.txt`, source at ), and the Qt libraries built into the executable are LGPLv3.