# OpenTranscode(v4) v4 adds: real end-to-end stability verification (caught a real bug!), CLI argument parsing, package split into `opentranscode/`, and `pyproject.toml` ready for PyPI (publishing deferred until maintainer confirms stability). ## Quick start ### Option A: Install as a package (recommended) ```bash cd /path/to/this/directory pip install -e . # editable install (dev) # OR pip install -e ".[dev]" # with pytest + build tools # Now you can run it three ways: opentranscode # console entry point python -m opentranscode # module entry point python -m opentranscode --version # → opentranscode 3.0.0 ``` ### Option B: Run the single-file v3 (backwards compat) ```bash python open-transcode.v3.py # the v3 single-file version still works ``` ### Option C: Verify your environment without encoding ```bash opentranscode --dry-run # probe env + smoke test, no GUI, no encode opentranscode --verify-only /path/to/existing_output.mkv # re-verify an output ``` ## Files | Path | Description | |------|-------------| | `opentranscode/` | **v4 package** — 16 modules, 5,744 lines. Importable as `import opentranscode`. | | `pyproject.toml` | PEP 621 build config. Entry point: `opentranscode = opentranscode.__main__:main`. Ready for `pip install -e .` and `python -m build`. **Not yet published to PyPI.** | | `tests/` | 70 tests across 10 files: 24 mocked unit tests + 10 real-ffmpeg e2e tests + 36 package-structure tests. All pass in ~9s. | | `open-transcode.v3.py` | Single-file v3 (5,370 lines). Kept for backwards compat + as the test target for the mocked tests. | | `open-transcode.v2.py` | Single-file v2 (4,874 lines). Kept for diff reference. | | `OpenTranscode_QA_Report.pdf` | The master QA report (26 pages). | | `pytest.ini` | pytest config (also in pyproject.toml). | | `README.md` | This file. | ## v4 changes (3 items) | ID | Severity | Description | |----|----------|-------------| | v4-01 | **Critical bug fix** | Real end-to-end tests caught a bug in `_probe_ffmpeg_libs`: the search strings for `libsvtav1` and `libaom` were wrong (used `_` instead of nothing/hyphen). This caused the probe to report False for both even when installed, which would have made `_handle_vs_incompat` tell users "ffmpeg also lacks libsvtav1" and abort — even though ffmpeg actually had it. **Fixed in v3 + v4.** The e2e test `test_probe_detects_ffmpeg_libs` is the regression guard. | | v4-02 | Feature | CLI argument parsing: `--version`, `--dry-run`, `--verify-only PATH`, `--help`. Lets users verify their setup without committing to a full encode. | | v4-03 | Architectural | Split single-file v3 (5,370 lines) into `opentranscode/` package (16 modules, 5,744 lines). Dependency graph is acyclic; `import opentranscode` works without PySide6 installed (lazy imports). | | v4-04 | Packaging | `pyproject.toml` — PEP 621 compliant, entry point `opentranscode = opentranscode.__main__:main`. `pip install -e .` works. `python -m build` produces sdist+wheel. **NOT published to PyPI** (per maintainer request). | | v4-05 | Test coverage | 36 new package-structure tests verifying: metadata, submodule imports, public API surface, CLI parser, `FFMPEG_LIB_KEY_MAP`, `DISTRO_REGISTRY` (6 entries), entry points. | | v4-06 | Docs | This README. | ## The critical v4-01 fix (in detail) The e2e test suite runs REAL ffmpeg encodes and verifies the output files. The first run caught this bug: ```python # v3 (BUGGY): checks = [ ("libsvtav1", ["libsvt_av1", "svt_av1"]), # WRONG — ffmpeg prints "libsvtav1" ("libaom", ["libaom_av1", "aom_av1"]), # WRONG — ffmpeg prints "libaom-av1" ... ] # v4 (FIXED): checks = [ ("libsvtav1", ["libsvtav1 ", "libsvt_av1", "svt_av1 "]), # correct + backward compat ("libaom", ["libaom-av1 ", "libaom_av1", "aom_av1 "]), ... ] ``` **Impact without the fix:** When av1an's VSScript is broken (the common case that triggers the ffmpeg fallback path), the user clicks ENCODE, the smoke test correctly fails, the code checks if ffmpeg has `libsvtav1` to offer fallback — but `_probe_ffmpeg_libs` returns False (because the search string doesn't match), so the user sees: > ABORT: ffmpeg also lacks libsvtav1. Install the encoder binary > (e.g. SvtAv1EncApp, vpxenc, x265) or use the REBUILD FROM GIT button. ...even though `ffmpeg -encoders` clearly shows `libsvtav1` is available. The user would then spend time installing SvtAv1EncApp or rebuilding from git, neither of which is necessary. With the fix, the fallback dialog correctly offers "Use ffmpeg Fallback" and the encode proceeds. ## Test suite ```bash cd /path/to/this/directory python -m pytest tests/ -v # 70 tests, ~9 seconds: # 24 mocked unit tests (test_smoke_test, test_encode_pipeline, etc.) # 10 real-ffmpeg e2e tests (test_e2e_real_encode) — requires ffmpeg + ffprobe # 36 package-structure tests (test_package_structure) ``` The e2e tests generate a real 2-second test video with ffmpeg, run the full EncoderWorker pipeline on it (AV1→MKV, x265→MKV, VP9→WebM), and verify the output file exists, is non-empty, has the correct codec, and has the expected duration. **If these tests pass, the "actually producing files" requirement is met.** ## What's deferred Per the maintainer's request, **PyPI publishing is on hold** until production stability is confirmed on a real desktop Linux system with av1an + VapourSynth installed. The `pyproject.toml` is ready; when the maintainer is ready to publish: ```bash python -m build # produces dist/opentranscode-3.0.0.tar.gz + .whl twine upload dist/* # publishes to PyPI ``` ## Verification (run these to confirm v4 works) ```bash # 1. Package imports cleanly python -c "import opentranscode; print(opentranscode.__version__)" # → 3.0.0 # 2. CLI works python -m opentranscode --version # → opentranscode 3.0.0 python -m opentranscode --help # → usage python -m opentranscode --dry-run # → env probe report (if ffmpeg installed) # 3. All tests pass python -m pytest tests/ -q # → 70 passed in ~9s # 4. Install works pip install -e . # → installs opentranscode + PySide6 opentranscode --version # → opentranscode 3.0.0 # 5. Single-file v3 still works (backwards compat) python open-transcode.v3.py # → launches GUI (if PySide6 + display) ```