mkv2cast 1.2.7.post4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mkv2cast/__init__.py +77 -0
- mkv2cast/__main__.py +14 -0
- mkv2cast/cli.py +1886 -0
- mkv2cast/config.py +638 -0
- mkv2cast/converter.py +1454 -0
- mkv2cast/history.py +389 -0
- mkv2cast/i18n.py +179 -0
- mkv2cast/integrity.py +176 -0
- mkv2cast/json_progress.py +311 -0
- mkv2cast/locales/de/LC_MESSAGES/mkv2cast.mo +0 -0
- mkv2cast/locales/de/LC_MESSAGES/mkv2cast.po +382 -0
- mkv2cast/locales/en/LC_MESSAGES/mkv2cast.mo +0 -0
- mkv2cast/locales/en/LC_MESSAGES/mkv2cast.po +382 -0
- mkv2cast/locales/es/LC_MESSAGES/mkv2cast.mo +0 -0
- mkv2cast/locales/es/LC_MESSAGES/mkv2cast.po +382 -0
- mkv2cast/locales/fr/LC_MESSAGES/mkv2cast.mo +0 -0
- mkv2cast/locales/fr/LC_MESSAGES/mkv2cast.po +430 -0
- mkv2cast/locales/it/LC_MESSAGES/mkv2cast.mo +0 -0
- mkv2cast/locales/it/LC_MESSAGES/mkv2cast.po +382 -0
- mkv2cast/notifications.py +196 -0
- mkv2cast/pipeline.py +641 -0
- mkv2cast/ui/__init__.py +26 -0
- mkv2cast/ui/legacy_ui.py +136 -0
- mkv2cast/ui/rich_ui.py +462 -0
- mkv2cast/ui/simple_rich.py +243 -0
- mkv2cast/watcher.py +293 -0
- mkv2cast-1.2.7.post4.dist-info/METADATA +1411 -0
- mkv2cast-1.2.7.post4.dist-info/RECORD +31 -0
- mkv2cast-1.2.7.post4.dist-info/WHEEL +4 -0
- mkv2cast-1.2.7.post4.dist-info/entry_points.txt +2 -0
- mkv2cast-1.2.7.post4.dist-info/licenses/LICENSE +50 -0
|
@@ -0,0 +1,1411 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mkv2cast
|
|
3
|
+
Version: 1.2.7.post4
|
|
4
|
+
Summary: Smart MKV to Chromecast-compatible converter with hardware acceleration
|
|
5
|
+
Project-URL: Homepage, https://github.com/voldardard/mkv2cast
|
|
6
|
+
Project-URL: Documentation, https://voldardard.github.io/mkv2cast
|
|
7
|
+
Project-URL: Repository, https://github.com/voldardard/mkv2cast
|
|
8
|
+
Project-URL: Issues, https://github.com/voldardard/mkv2cast/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/voldardard/mkv2cast/blob/main/CHANGELOG.md
|
|
10
|
+
Author: voldardard
|
|
11
|
+
License-Expression: GPL-3.0-or-later
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: chromecast,converter,ffmpeg,mkv,qsv,transcoding,vaapi,video
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
17
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: Multimedia :: Video :: Conversion
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: myst-parser>=2.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: sphinx-rtd-theme>=2.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: sphinx>=7.0; extra == 'dev'
|
|
35
|
+
Provides-Extra: full
|
|
36
|
+
Requires-Dist: plyer>=2.1.0; extra == 'full'
|
|
37
|
+
Requires-Dist: rich>=13.0.0; extra == 'full'
|
|
38
|
+
Requires-Dist: tomli>=2.0.0; (python_version < '3.11') and extra == 'full'
|
|
39
|
+
Requires-Dist: watchdog>=3.0.0; extra == 'full'
|
|
40
|
+
Provides-Extra: notifications
|
|
41
|
+
Requires-Dist: plyer>=2.1.0; extra == 'notifications'
|
|
42
|
+
Provides-Extra: rich
|
|
43
|
+
Requires-Dist: rich>=13.0.0; extra == 'rich'
|
|
44
|
+
Provides-Extra: watch
|
|
45
|
+
Requires-Dist: watchdog>=3.0.0; extra == 'watch'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# mkv2cast
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<img src="https://github.com/voldardard/mkv2cast/blob/main/docs/_static/mkv2cast-logo.svg" alt="mkv2cast logo" width="280">
|
|
52
|
+
</p>
|
|
53
|
+
|
|
54
|
+
<!-- Badges de statut -->
|
|
55
|
+
[](https://github.com/voldardard/mkv2cast/actions/workflows/ci.yml)
|
|
56
|
+
[](https://github.com/voldardard/mkv2cast/actions/workflows/ci.yml)
|
|
57
|
+
[](https://github.com/voldardard/mkv2cast/actions/workflows/docs.yml)
|
|
58
|
+
|
|
59
|
+
<!-- Badges de version -->
|
|
60
|
+
[](https://pypi.org/project/mkv2cast/)
|
|
61
|
+
[](https://pypi.org/project/mkv2cast/)
|
|
62
|
+
[](https://pypi.org/project/mkv2cast/)
|
|
63
|
+
|
|
64
|
+
<!-- Badges de projet -->
|
|
65
|
+
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
66
|
+
[](https://www.linux.org/)
|
|
67
|
+
[](https://github.com/astral-sh/ruff)
|
|
68
|
+
|
|
69
|
+
**Smart MKV to Chromecast-compatible converter with hardware acceleration**
|
|
70
|
+
|
|
71
|
+
Convert your MKV video files to formats compatible with Chromecast devices and Smart TVs, using intelligent codec detection and hardware-accelerated encoding.
|
|
72
|
+
|
|
73
|
+
<p align="center">
|
|
74
|
+
<img src="https://github.com/voldardard/mkv2cast/blob/main/docs/screenshot.png" alt="mkv2cast progress interface" width="700">
|
|
75
|
+
</p>
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Table of Contents
|
|
80
|
+
|
|
81
|
+
- [Features](#features)
|
|
82
|
+
- [Distribution](#distribution)
|
|
83
|
+
- [Purpose](#purpose)
|
|
84
|
+
- [Tested Devices](#tested-devices)
|
|
85
|
+
- [Prerequisites](#prerequisites)
|
|
86
|
+
- [Installation](#installation)
|
|
87
|
+
- [Configuration](#configuration)
|
|
88
|
+
- [Usage](#usage)
|
|
89
|
+
- [Using mkv2cast as a Python Package](#using-mkv2cast-as-a-python-package)
|
|
90
|
+
- [Options Reference](#options-reference)
|
|
91
|
+
- [Examples](#examples)
|
|
92
|
+
- [Maintenance](#maintenance)
|
|
93
|
+
- [Points de Vigilance](#points-de-vigilance)
|
|
94
|
+
- [Troubleshooting](#troubleshooting)
|
|
95
|
+
- [Contributing](#contributing)
|
|
96
|
+
- [Bug Reports](#bug-reports)
|
|
97
|
+
- [Roadmap](#roadmap)
|
|
98
|
+
- [Acknowledgments](#acknowledgments)
|
|
99
|
+
- [License](#license)
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Features
|
|
104
|
+
|
|
105
|
+
- **Intelligent Codec Detection**: Automatically analyzes video and audio streams to determine if transcoding is needed
|
|
106
|
+
- **Hardware Acceleration**: Supports Intel VAAPI and Quick Sync Video (QSV) for faster encoding
|
|
107
|
+
- **Parallel Processing**: Process multiple files simultaneously with configurable worker counts
|
|
108
|
+
- **Rich Progress Display**: Beautiful terminal UI with progress bars, ETA, and speed indicators
|
|
109
|
+
- **Integrity Checking**: Verifies source files before processing to avoid corrupted outputs
|
|
110
|
+
- **Conversion History**: Track all conversions with SQLite database and statistics
|
|
111
|
+
- **Flexible Filtering**: Include/exclude files using glob patterns or path filters
|
|
112
|
+
- **XDG Compliant**: Follows Linux standards for configuration, cache, and state directories
|
|
113
|
+
- **Automatic Audio Selection**: Prefers French audio tracks, falls back to first available
|
|
114
|
+
- **Configurable**: TOML/INI configuration file with sensible defaults
|
|
115
|
+
- **Desktop Notifications**: Get notified when conversions complete (via notify-send or plyer)
|
|
116
|
+
- **Multi-Language Support**: Available in English, French, Spanish, Italian, and German
|
|
117
|
+
- **PyPI Distribution**: Easy installation via `pip install mkv2cast`
|
|
118
|
+
- **GPU Acceleration**: NVIDIA NVENC, AMD AMF, Intel QSV, and VAAPI backends with auto-detection
|
|
119
|
+
- **Watch Mode**: Inotify/watchdog-based auto-conversion with optional systemd unit
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Distribution
|
|
124
|
+
|
|
125
|
+
| | |
|
|
126
|
+
|---|---|
|
|
127
|
+
| **Version** | 1.2.5 |
|
|
128
|
+
| **Author** | voldardard |
|
|
129
|
+
| **Date** | January 2026 |
|
|
130
|
+
| **License** | GPL-3.0 |
|
|
131
|
+
| **Repository** | https://github.com/voldardard/mkv2cast |
|
|
132
|
+
| **PyPI** | https://pypi.org/project/mkv2cast/ |
|
|
133
|
+
| **Documentation** | https://voldardard.github.io/mkv2cast |
|
|
134
|
+
|
|
135
|
+
### Version Format
|
|
136
|
+
|
|
137
|
+
mkv2cast uses semantic versioning with support for patch releases:
|
|
138
|
+
|
|
139
|
+
- **Standard releases**: `X.Y.Z` (e.g., `1.2.0`)
|
|
140
|
+
- **Patch releases**: `X.Y.Z-N` (e.g., `1.2.0-1`, `1.2.0-2`) - Used for bug fixes and minor updates without changing the main version
|
|
141
|
+
- **Pre-releases**: `X.Y.Z-beta.N`, `X.Y.Z-alpha.N`, `X.Y.Z-rc.N` (e.g., `1.2.0-beta.1`)
|
|
142
|
+
|
|
143
|
+
Patch releases (format `X.Y.Z-N`) are treated as stable releases and will:
|
|
144
|
+
- Be published to PyPI (automatically converted to PEP 440 format: `X.Y.Z.postN`)
|
|
145
|
+
- Trigger AUR and Debian package builds
|
|
146
|
+
- Not be treated as beta/alpha/rc releases
|
|
147
|
+
|
|
148
|
+
**Note on PyPI compatibility**: PyPI follows PEP 440 which doesn't support the `-N` format. Patch releases are automatically converted to `X.Y.Z.postN` format when publishing to PyPI (e.g., `1.2.7-1` becomes `1.2.7.post1` on PyPI). The original format `1.2.7-1` is preserved in Git tags and other package formats.
|
|
149
|
+
|
|
150
|
+
For AUR packages, patch releases are converted to `pkgver=X.Y.Z` and `pkgrel=N` format.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Purpose
|
|
155
|
+
|
|
156
|
+
**mkv2cast** was created to simplify the process of converting video files for playback on Chromecast devices and Smart TVs.
|
|
157
|
+
|
|
158
|
+
Many media files use codecs that aren't natively supported by Chromecast (like HEVC/H.265, AV1, or non-AAC audio). This tool:
|
|
159
|
+
|
|
160
|
+
1. **Analyzes** your MKV files to detect incompatible codecs
|
|
161
|
+
2. **Transcodes** only what's necessary (video, audio, or both)
|
|
162
|
+
3. **Preserves** compatible streams by copying them without re-encoding
|
|
163
|
+
4. **Outputs** Chromecast-compatible files ready for streaming
|
|
164
|
+
|
|
165
|
+
### Integration with catt
|
|
166
|
+
|
|
167
|
+
This tool is designed to work seamlessly with [catt](https://github.com/skorokithakis/catt) (Cast All The Things), a command-line tool for casting videos to Chromecast devices:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Convert your files first
|
|
171
|
+
mkv2cast movie.mkv
|
|
172
|
+
|
|
173
|
+
# Then cast to your TV
|
|
174
|
+
catt cast movie.h264.aac.cast.mkv
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Tested Devices
|
|
180
|
+
|
|
181
|
+
mkv2cast has been tested and confirmed working with:
|
|
182
|
+
|
|
183
|
+
| Device | Status | Notes |
|
|
184
|
+
|--------|--------|-------|
|
|
185
|
+
| **TCL 55C635** | ✅ Verified | Primary test device, 4K HDR |
|
|
186
|
+
| **TCL 65C735** | ✅ Verified | Similar to 55C635 |
|
|
187
|
+
| **Chromecast (Gen 3)** | ✅ Verified | 1080p |
|
|
188
|
+
| **Chromecast with Google TV** | ✅ Verified | 4K HDR |
|
|
189
|
+
| **Chromecast Ultra** | ✅ Verified | 4K HDR |
|
|
190
|
+
|
|
191
|
+
> **Note**: If you test with other devices, please submit a PR to update this list!
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Prerequisites
|
|
196
|
+
|
|
197
|
+
### Required
|
|
198
|
+
|
|
199
|
+
| Dependency | Version | Installation |
|
|
200
|
+
|------------|---------|--------------|
|
|
201
|
+
| **Python** | 3.8+ | Pre-installed on most Linux systems |
|
|
202
|
+
| **ffmpeg** | 4.0+ | `sudo pacman -S ffmpeg` (Arch) / `sudo apt install ffmpeg` (Debian) |
|
|
203
|
+
| **ffprobe** | 4.0+ | Included with ffmpeg |
|
|
204
|
+
|
|
205
|
+
### Optional (Recommended)
|
|
206
|
+
|
|
207
|
+
| Package | Purpose | Installation |
|
|
208
|
+
|---------|---------|--------------|
|
|
209
|
+
| **rich** | Beautiful progress UI | See below |
|
|
210
|
+
| **tomli** | TOML config support (Python < 3.11) | See below |
|
|
211
|
+
|
|
212
|
+
**Installing optional packages:**
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Arch Linux (recommended - system packages)
|
|
216
|
+
sudo pacman -S python-rich
|
|
217
|
+
sudo pacman -S python-tomli # Only needed for Python < 3.11
|
|
218
|
+
|
|
219
|
+
# Debian/Ubuntu
|
|
220
|
+
pip install --user rich tomli
|
|
221
|
+
|
|
222
|
+
# Other distributions
|
|
223
|
+
pip install --user rich tomli
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Hardware Acceleration
|
|
227
|
+
|
|
228
|
+
For hardware-accelerated encoding:
|
|
229
|
+
|
|
230
|
+
- **Intel VAAPI**: Install `intel-media-driver` or `libva-intel-driver`
|
|
231
|
+
- **Intel QSV**: Install `intel-media-sdk` or `oneVPL`
|
|
232
|
+
|
|
233
|
+
Check your hardware support:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# List available encoders
|
|
237
|
+
ffmpeg -encoders 2>/dev/null | grep -E 'vaapi|qsv'
|
|
238
|
+
|
|
239
|
+
# Test VAAPI
|
|
240
|
+
ls -la /dev/dri/renderD128
|
|
241
|
+
|
|
242
|
+
# Check with mkv2cast
|
|
243
|
+
mkv2cast --check-requirements
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Installation
|
|
249
|
+
|
|
250
|
+
### PyPI (Recommended) 🚀
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Basic installation
|
|
254
|
+
pip install mkv2cast
|
|
255
|
+
|
|
256
|
+
# With all optional features (rich UI, notifications)
|
|
257
|
+
pip install "mkv2cast[full]"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Arch Linux (AUR)
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
yay -S mkv2cast
|
|
264
|
+
# or
|
|
265
|
+
paru -S mkv2cast
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The AUR package ships the man page, bash/zsh completions, and both user + system cleanup timers by default.
|
|
269
|
+
|
|
270
|
+
### Debian/Ubuntu (APT Repository)
|
|
271
|
+
|
|
272
|
+
Add the official APT repository for automatic updates:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# Add the repository
|
|
276
|
+
echo "deb [trusted=yes] https://voldardard.github.io/mkv2cast/apt stable main" | sudo tee /etc/apt/sources.list.d/mkv2cast.list
|
|
277
|
+
|
|
278
|
+
# Update and install
|
|
279
|
+
sudo apt update
|
|
280
|
+
sudo apt install mkv2cast
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Or download the `.deb` package directly from [GitHub Releases](https://github.com/voldardard/mkv2cast/releases):
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Download and install specific version
|
|
287
|
+
wget https://github.com/voldardard/mkv2cast/releases/download/v1.2.5/mkv2cast_1.2.5-1_all.deb
|
|
288
|
+
sudo dpkg -i mkv2cast_1.2.5-1_all.deb
|
|
289
|
+
sudo apt-get install -f # Install dependencies
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Debian packages install the man page, bash/zsh completions, the user cleanup timer, and the optional system-wide cleanup timer. The watch mode service and timer are also available under the user systemd directory.
|
|
293
|
+
|
|
294
|
+
### Script Install (One-Liner)
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
curl -fsSL https://raw.githubusercontent.com/voldardard/mkv2cast/main/install.sh | bash
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The installer will:
|
|
301
|
+
- Download mkv2cast automatically
|
|
302
|
+
- Install to `~/.local/bin/`
|
|
303
|
+
- Set up man page and shell completions
|
|
304
|
+
- Configure your PATH automatically (if needed)
|
|
305
|
+
|
|
306
|
+
After installation, reload your shell or run:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
source ~/.bashrc # or ~/.zshrc for Zsh users
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Update
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# PyPI
|
|
316
|
+
pip install --upgrade mkv2cast
|
|
317
|
+
|
|
318
|
+
# Script
|
|
319
|
+
curl -fsSL https://raw.githubusercontent.com/voldardard/mkv2cast/main/install.sh | bash -s -- --update
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### System-Wide Installation
|
|
323
|
+
|
|
324
|
+
For servers or multi-user systems, install to `/usr/local`:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
curl -fsSL https://raw.githubusercontent.com/voldardard/mkv2cast/main/install.sh | sudo bash -s -- --system
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**System-wide cleanup**: When cleanup commands are run as root, mkv2cast automatically cleans temp files and logs for all users:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Clean temp files for all users (as root)
|
|
334
|
+
sudo mkv2cast --clean-tmp
|
|
335
|
+
|
|
336
|
+
# Clean logs for all users (as root)
|
|
337
|
+
sudo mkv2cast --clean-logs 30
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
A system-wide systemd timer is also available for automated cleanup.
|
|
341
|
+
|
|
342
|
+
### Installation Options
|
|
343
|
+
|
|
344
|
+
| Option | Description |
|
|
345
|
+
|--------|-------------|
|
|
346
|
+
| `--user` | Install for current user only (default) |
|
|
347
|
+
| `--system` | Install system-wide (requires sudo) |
|
|
348
|
+
| `--update` | Update existing installation |
|
|
349
|
+
| `--uninstall` | Remove mkv2cast |
|
|
350
|
+
| `--with-systemd` | Install cleanup timer |
|
|
351
|
+
| `--no-modify-rc` | Don't modify shell config files |
|
|
352
|
+
|
|
353
|
+
### Alternative: Manual Clone
|
|
354
|
+
|
|
355
|
+
If you prefer to clone the repository:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
git clone https://github.com/voldardard/mkv2cast.git
|
|
359
|
+
cd mkv2cast
|
|
360
|
+
./install.sh
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Verify Installation
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
mkv2cast --version
|
|
367
|
+
mkv2cast --check-requirements
|
|
368
|
+
man mkv2cast
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Uninstallation
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
# Quick uninstall
|
|
375
|
+
mkv2cast-uninstall
|
|
376
|
+
|
|
377
|
+
# Or via curl
|
|
378
|
+
curl -fsSL https://raw.githubusercontent.com/voldardard/mkv2cast/main/install.sh | bash -s -- --uninstall
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Installation Paths
|
|
382
|
+
|
|
383
|
+
| Mode | Script | Man Page | Completions | Config |
|
|
384
|
+
|------|--------|----------|-------------|--------|
|
|
385
|
+
| **User** | `~/.local/bin` | `~/.local/share/man/man1` | `~/.local/share/bash-completion` | `~/.config/mkv2cast` |
|
|
386
|
+
| **System** | `/usr/local/bin` | `/usr/local/share/man/man1` | `/etc/bash_completion.d` | `/etc/mkv2cast` |
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Configuration
|
|
391
|
+
|
|
392
|
+
### Configuration Files
|
|
393
|
+
|
|
394
|
+
mkv2cast uses a layered configuration system:
|
|
395
|
+
|
|
396
|
+
1. **System config** (optional): `/etc/mkv2cast/config.toml`
|
|
397
|
+
- Applied to all users
|
|
398
|
+
- Created only with `--system` installation
|
|
399
|
+
|
|
400
|
+
2. **User config**: `~/.config/mkv2cast/config.toml`
|
|
401
|
+
- Per-user settings
|
|
402
|
+
- Overrides system config
|
|
403
|
+
- Created automatically on first run
|
|
404
|
+
|
|
405
|
+
> **Priority**: User config values always override system config values.
|
|
406
|
+
|
|
407
|
+
### Example config.toml
|
|
408
|
+
|
|
409
|
+
```toml
|
|
410
|
+
[output]
|
|
411
|
+
suffix = ".cast"
|
|
412
|
+
container = "mkv"
|
|
413
|
+
|
|
414
|
+
[scan]
|
|
415
|
+
recursive = true
|
|
416
|
+
ignore_patterns = ["*sample*", "*.eng.*"]
|
|
417
|
+
ignore_paths = []
|
|
418
|
+
include_patterns = []
|
|
419
|
+
include_paths = []
|
|
420
|
+
|
|
421
|
+
[encoding]
|
|
422
|
+
backend = "auto" # auto, vaapi, qsv, cpu
|
|
423
|
+
crf = 20
|
|
424
|
+
preset = "slow"
|
|
425
|
+
abr = "192k"
|
|
426
|
+
|
|
427
|
+
[workers]
|
|
428
|
+
encode = 0 # 0 = auto-detect
|
|
429
|
+
integrity = 0 # 0 = auto-detect
|
|
430
|
+
|
|
431
|
+
[integrity]
|
|
432
|
+
enabled = true
|
|
433
|
+
stable_wait = 3
|
|
434
|
+
deep_check = false
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Directory Structure
|
|
438
|
+
|
|
439
|
+
mkv2cast follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html):
|
|
440
|
+
|
|
441
|
+
**User directories:**
|
|
442
|
+
|
|
443
|
+
| Directory | Purpose | Default Path |
|
|
444
|
+
|-----------|---------|--------------|
|
|
445
|
+
| Config | User configuration | `~/.config/mkv2cast/` |
|
|
446
|
+
| State | History, logs | `~/.local/state/mkv2cast/` |
|
|
447
|
+
| Cache | Temporary files | `~/.cache/mkv2cast/` |
|
|
448
|
+
|
|
449
|
+
**System directories** (only for system-wide installation):
|
|
450
|
+
|
|
451
|
+
| Directory | Purpose | Default Path |
|
|
452
|
+
|-----------|---------|--------------|
|
|
453
|
+
| Config | System-wide defaults | `/etc/mkv2cast/` |
|
|
454
|
+
|
|
455
|
+
View all directories:
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
mkv2cast --show-dirs
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Usage
|
|
464
|
+
|
|
465
|
+
### Basic Usage
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
# Process all MKV files in current directory (recursive)
|
|
469
|
+
mkv2cast
|
|
470
|
+
|
|
471
|
+
# Process a single file
|
|
472
|
+
mkv2cast movie.mkv
|
|
473
|
+
|
|
474
|
+
# Process with debug output
|
|
475
|
+
mkv2cast --debug movie.mkv
|
|
476
|
+
|
|
477
|
+
# Dry run (show what would be done)
|
|
478
|
+
mkv2cast --dryrun
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Output File Naming
|
|
482
|
+
|
|
483
|
+
Output files are named based on transformations applied:
|
|
484
|
+
|
|
485
|
+
| Input | Output | Meaning |
|
|
486
|
+
|-------|--------|---------|
|
|
487
|
+
| `movie.mkv` | `movie.h264.cast.mkv` | Video transcoded to H.264 |
|
|
488
|
+
| `movie.mkv` | `movie.aac.cast.mkv` | Audio transcoded to AAC |
|
|
489
|
+
| `movie.mkv` | `movie.h264.aac.cast.mkv` | Both transcoded |
|
|
490
|
+
| `movie.mkv` | `movie.remux.cast.mkv` | Container changed only |
|
|
491
|
+
|
|
492
|
+
### Common Workflows
|
|
493
|
+
|
|
494
|
+
#### Convert entire movie collection
|
|
495
|
+
|
|
496
|
+
```bash
|
|
497
|
+
cd /path/to/movies
|
|
498
|
+
mkv2cast
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### Convert only French movies from 2024
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
mkv2cast -i '*French*' -i '*2024*'
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
#### Fast encoding (lower quality)
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
mkv2cast --hw cpu --preset fast --crf 23
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
#### High quality with hardware acceleration
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
mkv2cast --hw vaapi --vaapi-qp 20
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
#### Process without recursive scan
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
mkv2cast --no-recursive
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## Using mkv2cast as a Python Package
|
|
528
|
+
|
|
529
|
+
mkv2cast can be imported and used as a Python library in your scripts, allowing you to programmatically convert video files with full control over the conversion process.
|
|
530
|
+
|
|
531
|
+
### Installation
|
|
532
|
+
|
|
533
|
+
First, ensure mkv2cast is installed:
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
pip install mkv2cast
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Basic Usage
|
|
540
|
+
|
|
541
|
+
The simplest way to use mkv2cast programmatically is with the `convert_file` function:
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
from mkv2cast import convert_file
|
|
545
|
+
from pathlib import Path
|
|
546
|
+
|
|
547
|
+
# Convert a single file
|
|
548
|
+
success, output_path, message = convert_file(Path("movie.mkv"))
|
|
549
|
+
|
|
550
|
+
if success:
|
|
551
|
+
if output_path:
|
|
552
|
+
print(f"Converted to: {output_path}")
|
|
553
|
+
else:
|
|
554
|
+
print(f"Skipped: {message}")
|
|
555
|
+
else:
|
|
556
|
+
print(f"Failed: {message}")
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Configuration
|
|
560
|
+
|
|
561
|
+
Create a custom configuration to control encoding settings:
|
|
562
|
+
|
|
563
|
+
```python
|
|
564
|
+
from mkv2cast import Config, convert_file
|
|
565
|
+
from pathlib import Path
|
|
566
|
+
|
|
567
|
+
# Create custom configuration
|
|
568
|
+
config = Config(
|
|
569
|
+
hw="vaapi", # Use VAAPI hardware acceleration
|
|
570
|
+
crf=20, # Quality setting (lower = better quality)
|
|
571
|
+
preset="slow", # Encoding preset
|
|
572
|
+
container="mp4", # Output container format
|
|
573
|
+
suffix=".cast", # Output file suffix
|
|
574
|
+
notify=False # Disable notifications in scripts
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
# Convert with custom config
|
|
578
|
+
success, output_path, message = convert_file(
|
|
579
|
+
Path("movie.mkv"),
|
|
580
|
+
cfg=config
|
|
581
|
+
)
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### JSON Progress Output
|
|
585
|
+
|
|
586
|
+
For integration with web UIs or monitoring tools, use `--json-progress`:
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
mkv2cast --json-progress movie.mkv
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
This outputs JSON events to stdout:
|
|
593
|
+
|
|
594
|
+
```json
|
|
595
|
+
{"version":"1.0","event":"start","overall":{"total_files":1,"backend":"vaapi"}}
|
|
596
|
+
{"version":"1.0","event":"file_start","file":"movie.mkv"}
|
|
597
|
+
{"version":"1.0","event":"progress","files":{"movie.mkv":{"progress_percent":45.2,"fps":120.5,"eta_seconds":30}}}
|
|
598
|
+
{"version":"1.0","event":"file_done","file":"movie.mkv","status":"done"}
|
|
599
|
+
{"version":"1.0","event":"complete"}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Using JSON Progress in Python
|
|
603
|
+
|
|
604
|
+
```python
|
|
605
|
+
import json
|
|
606
|
+
import subprocess
|
|
607
|
+
from typing import Generator, Dict, Any
|
|
608
|
+
|
|
609
|
+
def stream_progress(filepath: str) -> Generator[Dict[str, Any], None, None]:
|
|
610
|
+
"""Stream JSON progress events from mkv2cast."""
|
|
611
|
+
proc = subprocess.Popen(
|
|
612
|
+
["mkv2cast", "--json-progress", filepath],
|
|
613
|
+
stdout=subprocess.PIPE,
|
|
614
|
+
text=True
|
|
615
|
+
)
|
|
616
|
+
for line in proc.stdout:
|
|
617
|
+
yield json.loads(line)
|
|
618
|
+
|
|
619
|
+
# Example: Display progress
|
|
620
|
+
for event in stream_progress("movie.mkv"):
|
|
621
|
+
if event["event"] == "progress":
|
|
622
|
+
for filename, data in event.get("files", {}).items():
|
|
623
|
+
print(f"{filename}: {data['progress_percent']:.1f}%")
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### Advanced: Progress Callbacks
|
|
627
|
+
|
|
628
|
+
Instead of parsing JSON output, use progress callbacks directly in your Python code:
|
|
629
|
+
|
|
630
|
+
```python
|
|
631
|
+
from mkv2cast import convert_file, Config
|
|
632
|
+
from pathlib import Path
|
|
633
|
+
|
|
634
|
+
def on_progress(filepath: Path, progress: dict):
|
|
635
|
+
"""Called during conversion with progress updates."""
|
|
636
|
+
stage = progress.get("stage", "unknown")
|
|
637
|
+
percent = progress.get("progress_percent", 0)
|
|
638
|
+
fps = progress.get("fps", 0)
|
|
639
|
+
eta = progress.get("eta_seconds", 0)
|
|
640
|
+
|
|
641
|
+
print(f"{filepath.name}: {stage} - {percent:.1f}% @ {fps:.1f}fps, ETA: {eta:.0f}s")
|
|
642
|
+
|
|
643
|
+
config = Config.for_library(hw="auto") # Auto-disables UI for library usage
|
|
644
|
+
|
|
645
|
+
success, output, msg = convert_file(
|
|
646
|
+
Path("movie.mkv"),
|
|
647
|
+
cfg=config,
|
|
648
|
+
progress_callback=on_progress
|
|
649
|
+
)
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Progress callback receives:**
|
|
653
|
+
|
|
654
|
+
| Field | Type | Description |
|
|
655
|
+
|-------|------|-------------|
|
|
656
|
+
| `stage` | str | "checking", "encoding", "done", "skipped", "failed" |
|
|
657
|
+
| `progress_percent` | float | Progress percentage (0-100) |
|
|
658
|
+
| `fps` | float | Current encoding FPS |
|
|
659
|
+
| `eta_seconds` | float | Estimated time remaining |
|
|
660
|
+
| `bitrate` | str | Current bitrate (e.g., "2500kbits/s") |
|
|
661
|
+
| `speed` | str | Encoding speed (e.g., "2.5x") |
|
|
662
|
+
| `current_time_ms` | int | Current position in milliseconds |
|
|
663
|
+
| `duration_ms` | int | Total duration in milliseconds |
|
|
664
|
+
| `error` | str/None | Error message if stage is "failed" |
|
|
665
|
+
|
|
666
|
+
### Batch Processing with Multi-threading
|
|
667
|
+
|
|
668
|
+
Process multiple files in parallel using `convert_batch()`:
|
|
669
|
+
|
|
670
|
+
```python
|
|
671
|
+
from mkv2cast import convert_batch, Config
|
|
672
|
+
from pathlib import Path
|
|
673
|
+
|
|
674
|
+
config = Config.for_library(
|
|
675
|
+
hw="vaapi",
|
|
676
|
+
encode_workers=2, # 2 parallel encoders
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
def on_progress(filepath: Path, progress: dict):
|
|
680
|
+
"""Thread-safe callback for progress updates."""
|
|
681
|
+
percent = progress.get("progress_percent", 0)
|
|
682
|
+
stage = progress.get("stage", "")
|
|
683
|
+
print(f"{filepath.name}: {stage} {percent:.1f}%")
|
|
684
|
+
|
|
685
|
+
files = [Path("movie1.mkv"), Path("movie2.mkv"), Path("movie3.mkv")]
|
|
686
|
+
|
|
687
|
+
results = convert_batch(
|
|
688
|
+
files,
|
|
689
|
+
cfg=config,
|
|
690
|
+
progress_callback=on_progress
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
# Check results
|
|
694
|
+
for filepath, (success, output, msg) in results.items():
|
|
695
|
+
if success:
|
|
696
|
+
print(f"OK {filepath.name}: {msg}")
|
|
697
|
+
else:
|
|
698
|
+
print(f"FAIL {filepath.name}: {msg}")
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Script Mode (No Colors/Output)
|
|
702
|
+
|
|
703
|
+
When used as a library, mkv2cast can automatically disable:
|
|
704
|
+
|
|
705
|
+
- Progress bars
|
|
706
|
+
- Colored output
|
|
707
|
+
- Desktop notifications
|
|
708
|
+
- Rich UI
|
|
709
|
+
|
|
710
|
+
**Automatic detection** happens when:
|
|
711
|
+
|
|
712
|
+
- `sys.stdout` is not a TTY (piped or redirected)
|
|
713
|
+
- `NO_COLOR` environment variable is set
|
|
714
|
+
- `MKV2CAST_SCRIPT_MODE=1` is set
|
|
715
|
+
|
|
716
|
+
**Recommended for library usage:**
|
|
717
|
+
|
|
718
|
+
```python
|
|
719
|
+
# Use Config.for_library() which auto-disables UI features
|
|
720
|
+
config = Config.for_library(hw="vaapi", crf=20)
|
|
721
|
+
|
|
722
|
+
# Or manually disable
|
|
723
|
+
config = Config(
|
|
724
|
+
progress=False, # No progress bars
|
|
725
|
+
notify=False, # No notifications
|
|
726
|
+
pipeline=False, # No Rich UI
|
|
727
|
+
)
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### Analyzing Files
|
|
731
|
+
|
|
732
|
+
Before converting, you can analyze a file to see what transcoding is needed:
|
|
733
|
+
|
|
734
|
+
```python
|
|
735
|
+
from mkv2cast import decide_for, pick_backend
|
|
736
|
+
from pathlib import Path
|
|
737
|
+
|
|
738
|
+
# Analyze a file
|
|
739
|
+
decision = decide_for(Path("movie.mkv"))
|
|
740
|
+
|
|
741
|
+
print(f"Video codec: {decision.vcodec}")
|
|
742
|
+
print(f"Audio codec: {decision.acodec}")
|
|
743
|
+
print(f"Needs video transcode: {decision.need_v}")
|
|
744
|
+
print(f"Needs audio transcode: {decision.need_a}")
|
|
745
|
+
print(f"Reason: {decision.reason_v}")
|
|
746
|
+
|
|
747
|
+
# Check available backend
|
|
748
|
+
backend = pick_backend()
|
|
749
|
+
print(f"Best backend: {backend}")
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### Batch Processing (Sequential)
|
|
753
|
+
|
|
754
|
+
Process multiple files sequentially with custom logic:
|
|
755
|
+
|
|
756
|
+
```python
|
|
757
|
+
from pathlib import Path
|
|
758
|
+
from mkv2cast import convert_file, Config
|
|
759
|
+
|
|
760
|
+
config = Config.for_library(hw="auto", container="mkv")
|
|
761
|
+
|
|
762
|
+
input_dir = Path("/media/videos")
|
|
763
|
+
output_dir = Path("/media/converted")
|
|
764
|
+
|
|
765
|
+
for mkv_file in input_dir.glob("**/*.mkv"):
|
|
766
|
+
success, output, msg = convert_file(
|
|
767
|
+
mkv_file,
|
|
768
|
+
cfg=config,
|
|
769
|
+
output_dir=output_dir
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
if success and output:
|
|
773
|
+
print(f"OK {mkv_file.name} -> {output.name}")
|
|
774
|
+
elif not success:
|
|
775
|
+
print(f"FAIL {mkv_file.name}: {msg}")
|
|
776
|
+
else:
|
|
777
|
+
print(f"SKIP {mkv_file.name}: {msg}")
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
For parallel batch processing, see [Batch Processing with Multi-threading](#batch-processing-with-multi-threading) above.
|
|
781
|
+
|
|
782
|
+
### Advanced: Building Custom Commands
|
|
783
|
+
|
|
784
|
+
For more control, you can build FFmpeg commands manually:
|
|
785
|
+
|
|
786
|
+
```python
|
|
787
|
+
from mkv2cast import decide_for, pick_backend, build_transcode_cmd, Config
|
|
788
|
+
from pathlib import Path
|
|
789
|
+
import subprocess
|
|
790
|
+
|
|
791
|
+
input_file = Path("movie.mkv")
|
|
792
|
+
output_file = Path("movie.h264.cast.mkv")
|
|
793
|
+
config = Config()
|
|
794
|
+
|
|
795
|
+
# Analyze file
|
|
796
|
+
decision = decide_for(input_file, config)
|
|
797
|
+
|
|
798
|
+
# Select backend
|
|
799
|
+
backend = pick_backend(config)
|
|
800
|
+
|
|
801
|
+
# Build command
|
|
802
|
+
cmd, stage = build_transcode_cmd(
|
|
803
|
+
input_file,
|
|
804
|
+
decision,
|
|
805
|
+
backend,
|
|
806
|
+
output_file,
|
|
807
|
+
log_path=None, # Optional: Path to log file
|
|
808
|
+
cfg=config
|
|
809
|
+
)
|
|
810
|
+
|
|
811
|
+
# Run manually
|
|
812
|
+
result = subprocess.run(cmd)
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### Working with History
|
|
816
|
+
|
|
817
|
+
Access conversion history programmatically:
|
|
818
|
+
|
|
819
|
+
```python
|
|
820
|
+
from mkv2cast import HistoryDB, get_app_dirs
|
|
821
|
+
|
|
822
|
+
# Get history database
|
|
823
|
+
dirs = get_app_dirs()
|
|
824
|
+
history = HistoryDB(dirs["state"])
|
|
825
|
+
|
|
826
|
+
# Get recent conversions
|
|
827
|
+
recent = history.get_recent(20)
|
|
828
|
+
for entry in recent:
|
|
829
|
+
print(f"{entry['status']}: {entry['input_path']}")
|
|
830
|
+
|
|
831
|
+
# Get statistics
|
|
832
|
+
stats = history.get_stats()
|
|
833
|
+
print(f"Total conversions: {sum(stats['by_status'].values())}")
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
### Loading Configuration Files
|
|
837
|
+
|
|
838
|
+
Load settings from configuration files:
|
|
839
|
+
|
|
840
|
+
```python
|
|
841
|
+
from mkv2cast import load_config_file, get_app_dirs, Config
|
|
842
|
+
|
|
843
|
+
# Get config directory
|
|
844
|
+
dirs = get_app_dirs()
|
|
845
|
+
|
|
846
|
+
# Load config file (TOML or INI)
|
|
847
|
+
file_config = load_config_file(dirs["config"])
|
|
848
|
+
|
|
849
|
+
# Create config and manually apply settings from file
|
|
850
|
+
config = Config()
|
|
851
|
+
if "encoding" in file_config:
|
|
852
|
+
if "backend" in file_config["encoding"]:
|
|
853
|
+
config.hw = file_config["encoding"]["backend"]
|
|
854
|
+
if "crf" in file_config["encoding"]:
|
|
855
|
+
config.crf = file_config["encoding"]["crf"]
|
|
856
|
+
# ... apply other settings as needed
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### Available Functions and Classes
|
|
860
|
+
|
|
861
|
+
Main exports from `mkv2cast`:
|
|
862
|
+
|
|
863
|
+
| Function/Class | Description |
|
|
864
|
+
|----------------|-------------|
|
|
865
|
+
| **`convert_file()`** | Convert a single file with optional progress callback |
|
|
866
|
+
| **`convert_batch()`** | Convert multiple files in parallel with multi-threading |
|
|
867
|
+
| **`decide_for()`** | Analyze what transcoding is needed for a file |
|
|
868
|
+
| **`pick_backend()`** | Auto-detect best encoding backend |
|
|
869
|
+
| **`build_transcode_cmd()`** | Build FFmpeg command manually |
|
|
870
|
+
| **`Config`** | Configuration dataclass with `for_library()` factory |
|
|
871
|
+
| **`Config.for_library()`** | Create config optimized for library usage |
|
|
872
|
+
| **`Decision`** | Analysis result dataclass |
|
|
873
|
+
| **`HistoryDB`** | Conversion history database |
|
|
874
|
+
| **`get_app_dirs()`** | Get XDG directories |
|
|
875
|
+
| **`load_config_file()`** | Load config from file |
|
|
876
|
+
| **`is_script_mode()`** | Check if running in script/library mode |
|
|
877
|
+
| **`send_notification()`** | Send desktop notification |
|
|
878
|
+
| **`setup_i18n()`** | Setup internationalization |
|
|
879
|
+
|
|
880
|
+
For detailed API documentation, see the [API Reference](https://voldardard.github.io/mkv2cast/api/index.html).
|
|
881
|
+
|
|
882
|
+
---
|
|
883
|
+
|
|
884
|
+
## Options Reference
|
|
885
|
+
|
|
886
|
+
### General Options
|
|
887
|
+
|
|
888
|
+
| Option | Description |
|
|
889
|
+
|--------|-------------|
|
|
890
|
+
| `-h, --help` | Show help message |
|
|
891
|
+
| `-V, --version` | Show version information |
|
|
892
|
+
| `--check-requirements` | Check system requirements |
|
|
893
|
+
|
|
894
|
+
### Output Settings
|
|
895
|
+
|
|
896
|
+
| Option | Default | Description |
|
|
897
|
+
|--------|---------|-------------|
|
|
898
|
+
| `--suffix SUFFIX` | `.cast` | Output file suffix |
|
|
899
|
+
| `--container FORMAT` | `mkv` | Output format: `mkv` or `mp4` |
|
|
900
|
+
|
|
901
|
+
### Scan Settings
|
|
902
|
+
|
|
903
|
+
| Option | Default | Description |
|
|
904
|
+
|--------|---------|-------------|
|
|
905
|
+
| `-r, --recursive` | enabled | Scan directories recursively |
|
|
906
|
+
| `--no-recursive` | - | Disable recursive scanning |
|
|
907
|
+
| `-I, --ignore-pattern PATTERN` | - | Ignore files matching glob pattern |
|
|
908
|
+
| `--ignore-path PATH` | - | Ignore specific paths/folders |
|
|
909
|
+
| `-i, --include-pattern PATTERN` | - | Only process matching files |
|
|
910
|
+
| `--include-path PATH` | - | Only process files in path |
|
|
911
|
+
|
|
912
|
+
### Codec Decisions
|
|
913
|
+
|
|
914
|
+
| Option | Default | Description |
|
|
915
|
+
|--------|---------|-------------|
|
|
916
|
+
| `--skip-when-ok` | enabled | Skip compatible files |
|
|
917
|
+
| `--no-skip-when-ok` | - | Process all files |
|
|
918
|
+
| `--force-h264` | disabled | Force H.264 transcoding |
|
|
919
|
+
| `--allow-hevc` | disabled | Allow HEVC passthrough |
|
|
920
|
+
| `--force-aac` | disabled | Force AAC transcoding |
|
|
921
|
+
| `--keep-surround` | disabled | Keep surround audio |
|
|
922
|
+
| `--no-silence` | - | Don't add silence track |
|
|
923
|
+
|
|
924
|
+
### Encoding Quality
|
|
925
|
+
|
|
926
|
+
| Option | Default | Description |
|
|
927
|
+
|--------|---------|-------------|
|
|
928
|
+
| `--abr BITRATE` | `192k` | Audio bitrate |
|
|
929
|
+
| `--crf VALUE` | `20` | CRF for CPU encoding (18-28) |
|
|
930
|
+
| `--preset PRESET` | `slow` | x264 preset |
|
|
931
|
+
|
|
932
|
+
### Profiles
|
|
933
|
+
|
|
934
|
+
| Option | Default | Description |
|
|
935
|
+
|--------|---------|-------------|
|
|
936
|
+
| `--profile {fast,balanced,quality}` | - | Apply encoding profile (sets CRF, preset, and hardware quality defaults) |
|
|
937
|
+
|
|
938
|
+
### Hardware Acceleration
|
|
939
|
+
|
|
940
|
+
| Option | Default | Description |
|
|
941
|
+
|--------|---------|-------------|
|
|
942
|
+
| `--hw BACKEND` | `auto` | Backend: `auto`, `nvenc`, `amf`, `qsv`, `vaapi`, `cpu` |
|
|
943
|
+
| `--vaapi-device PATH` | `/dev/dri/renderD128` | VAAPI device |
|
|
944
|
+
| `--vaapi-qp VALUE` | `23` | VAAPI quality |
|
|
945
|
+
| `--qsv-quality VALUE` | `23` | QSV quality |
|
|
946
|
+
| `--nvenc-cq VALUE` | `23` | NVENC constant quality (0-51) |
|
|
947
|
+
| `--amf-quality VALUE` | `23` | AMD AMF quality (0-51) |
|
|
948
|
+
|
|
949
|
+
### Preservation
|
|
950
|
+
|
|
951
|
+
| Option | Default | Description |
|
|
952
|
+
|--------|---------|-------------|
|
|
953
|
+
| `--no-metadata` | enabled | Disable metadata preservation |
|
|
954
|
+
| `--no-chapters` | enabled | Disable chapter preservation |
|
|
955
|
+
| `--no-attachments` | enabled | Disable MKV attachments preservation |
|
|
956
|
+
|
|
957
|
+
### Integrity Checks
|
|
958
|
+
|
|
959
|
+
| Option | Default | Description |
|
|
960
|
+
|--------|---------|-------------|
|
|
961
|
+
| `--integrity-check` | enabled | Enable integrity check |
|
|
962
|
+
| `--no-integrity-check` | - | Disable integrity check |
|
|
963
|
+
| `--stable-wait SECONDS` | `3` | Wait for file stability |
|
|
964
|
+
| `--deep-check` | disabled | Deep decode verification |
|
|
965
|
+
|
|
966
|
+
### Disk Guards & Quotas
|
|
967
|
+
|
|
968
|
+
| Option | Default | Description |
|
|
969
|
+
|--------|---------|-------------|
|
|
970
|
+
| `--min-free-mb MB` | `1024` | Minimum free space to keep in output filesystem |
|
|
971
|
+
| `--min-free-tmp-mb MB` | `512` | Minimum free space to keep in temp filesystem |
|
|
972
|
+
| `--max-output-mb MB` | `0` | Max output size per file (0 = disabled) |
|
|
973
|
+
| `--max-output-ratio RATIO` | `0.0` | Max output size ratio vs input (0 = disabled) |
|
|
974
|
+
|
|
975
|
+
### Parallelism
|
|
976
|
+
|
|
977
|
+
| Option | Default | Description |
|
|
978
|
+
|--------|---------|-------------|
|
|
979
|
+
| `--pipeline` | enabled | Parallel processing |
|
|
980
|
+
| `--no-pipeline` | - | Sequential mode |
|
|
981
|
+
| `--encode-workers N` | `0` (auto) | Parallel encoding workers |
|
|
982
|
+
| `--integrity-workers N` | `0` (auto) | Parallel integrity workers |
|
|
983
|
+
|
|
984
|
+
### Reliability
|
|
985
|
+
|
|
986
|
+
| Option | Default | Description |
|
|
987
|
+
|--------|---------|-------------|
|
|
988
|
+
| `--retry-attempts N` | `1` | Number of retries after failure (0 = disabled) |
|
|
989
|
+
| `--retry-delay SECONDS` | `2.0` | Delay between retries |
|
|
990
|
+
| `--no-retry-fallback-cpu` | enabled | Disable CPU fallback on last retry |
|
|
991
|
+
|
|
992
|
+
### JSON Progress Output
|
|
993
|
+
|
|
994
|
+
| Option | Default | Description |
|
|
995
|
+
|--------|---------|-------------|
|
|
996
|
+
| `--json-progress` | disabled | Output structured JSON progress |
|
|
997
|
+
|
|
998
|
+
### Utility Commands
|
|
999
|
+
|
|
1000
|
+
| Option | Description |
|
|
1001
|
+
|--------|-------------|
|
|
1002
|
+
| `--show-dirs` | Show XDG directory paths |
|
|
1003
|
+
| `--history [N]` | Show recent conversions (default: 20, max: 1000) |
|
|
1004
|
+
| `--history-stats` | Show conversion statistics |
|
|
1005
|
+
| `--clean-tmp` | Remove orphaned temp files (all users if root) |
|
|
1006
|
+
| `--clean-logs DAYS` | Remove old log files (all users if root) |
|
|
1007
|
+
| `--clean-history DAYS` | Remove old history entries |
|
|
1008
|
+
|
|
1009
|
+
---
|
|
1010
|
+
|
|
1011
|
+
## Examples
|
|
1012
|
+
|
|
1013
|
+
### Filtering Examples
|
|
1014
|
+
|
|
1015
|
+
```bash
|
|
1016
|
+
# Ignore sample files and English tracks
|
|
1017
|
+
mkv2cast -I '*sample*' -I '*.eng.*'
|
|
1018
|
+
|
|
1019
|
+
# Process only French content
|
|
1020
|
+
mkv2cast -i '*French*' -i '*VFF*' -i '*FRENCH*'
|
|
1021
|
+
|
|
1022
|
+
# Ignore specific folders
|
|
1023
|
+
mkv2cast --ignore-path Downloads/temp --ignore-path "To Sort"
|
|
1024
|
+
|
|
1025
|
+
# Process only specific folder
|
|
1026
|
+
mkv2cast --include-path Movies/2024
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
### Encoding Examples
|
|
1030
|
+
|
|
1031
|
+
```bash
|
|
1032
|
+
# Use CPU with fast preset (quick, lower quality)
|
|
1033
|
+
mkv2cast --hw cpu --preset fast --crf 23
|
|
1034
|
+
|
|
1035
|
+
# Use VAAPI with high quality
|
|
1036
|
+
mkv2cast --hw vaapi --vaapi-qp 18
|
|
1037
|
+
|
|
1038
|
+
# Keep surround sound
|
|
1039
|
+
mkv2cast --keep-surround --abr 256k
|
|
1040
|
+
|
|
1041
|
+
# Output to MP4 instead of MKV
|
|
1042
|
+
mkv2cast --container mp4
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
### Parallel Processing Examples
|
|
1046
|
+
|
|
1047
|
+
```bash
|
|
1048
|
+
# Use 3 parallel encoders
|
|
1049
|
+
mkv2cast --encode-workers 3
|
|
1050
|
+
|
|
1051
|
+
# Disable parallel processing
|
|
1052
|
+
mkv2cast --no-pipeline
|
|
1053
|
+
|
|
1054
|
+
# Custom worker configuration
|
|
1055
|
+
mkv2cast --encode-workers 2 --integrity-workers 4
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
### Maintenance Examples
|
|
1059
|
+
|
|
1060
|
+
```bash
|
|
1061
|
+
# View conversion history (default: 20 lines)
|
|
1062
|
+
mkv2cast --history
|
|
1063
|
+
|
|
1064
|
+
# View more history (50 or 100 lines)
|
|
1065
|
+
mkv2cast --history 50
|
|
1066
|
+
mkv2cast --history 100
|
|
1067
|
+
|
|
1068
|
+
# View statistics
|
|
1069
|
+
mkv2cast --history-stats
|
|
1070
|
+
|
|
1071
|
+
# Clean temporary files
|
|
1072
|
+
mkv2cast --clean-tmp
|
|
1073
|
+
|
|
1074
|
+
# Clean logs older than 30 days
|
|
1075
|
+
mkv2cast --clean-logs 30
|
|
1076
|
+
|
|
1077
|
+
# Clean history older than 90 days
|
|
1078
|
+
mkv2cast --clean-history 90
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
---
|
|
1082
|
+
|
|
1083
|
+
## Maintenance
|
|
1084
|
+
|
|
1085
|
+
### Automatic Cleanup with systemd
|
|
1086
|
+
|
|
1087
|
+
Install the systemd timer for weekly automatic cleanup:
|
|
1088
|
+
|
|
1089
|
+
```bash
|
|
1090
|
+
./install.sh --with-systemd
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
Or manually:
|
|
1094
|
+
|
|
1095
|
+
```bash
|
|
1096
|
+
# Copy service files
|
|
1097
|
+
cp systemd/mkv2cast-cleanup.* ~/.config/systemd/user/
|
|
1098
|
+
|
|
1099
|
+
# Enable timer
|
|
1100
|
+
systemctl --user enable --now mkv2cast-cleanup.timer
|
|
1101
|
+
|
|
1102
|
+
# Check status
|
|
1103
|
+
systemctl --user status mkv2cast-cleanup.timer
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
### Automatic Cleanup with cron
|
|
1107
|
+
|
|
1108
|
+
Add to your crontab (`crontab -e`):
|
|
1109
|
+
|
|
1110
|
+
```cron
|
|
1111
|
+
# Weekly cleanup on Sunday at 3 AM
|
|
1112
|
+
0 3 * * 0 mkv2cast --clean-tmp && mkv2cast --clean-logs 30
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
### Manual Cleanup
|
|
1116
|
+
|
|
1117
|
+
```bash
|
|
1118
|
+
# Clean orphaned temp files
|
|
1119
|
+
mkv2cast --clean-tmp
|
|
1120
|
+
|
|
1121
|
+
# Clean logs older than 30 days
|
|
1122
|
+
mkv2cast --clean-logs 30
|
|
1123
|
+
|
|
1124
|
+
# Clean history older than 90 days
|
|
1125
|
+
mkv2cast --clean-history 90
|
|
1126
|
+
```
|
|
1127
|
+
|
|
1128
|
+
---
|
|
1129
|
+
|
|
1130
|
+
## Points de Vigilance
|
|
1131
|
+
|
|
1132
|
+
### Important Notes
|
|
1133
|
+
|
|
1134
|
+
1. **Recursive Scanning is Default**
|
|
1135
|
+
- mkv2cast scans subdirectories by default
|
|
1136
|
+
- Use `--no-recursive` to process only the current directory
|
|
1137
|
+
- Be careful when running in large directory trees!
|
|
1138
|
+
|
|
1139
|
+
2. **Original Files are Preserved**
|
|
1140
|
+
- mkv2cast creates new output files, it does NOT modify originals
|
|
1141
|
+
- Output files have a distinct suffix (`.cast.mkv` by default)
|
|
1142
|
+
|
|
1143
|
+
3. **Temporary Files**
|
|
1144
|
+
- During encoding, temp files are created in `~/.cache/mkv2cast/tmp/`
|
|
1145
|
+
- They are automatically cleaned on successful completion
|
|
1146
|
+
- Use `--clean-tmp` to remove orphaned temp files after interruption
|
|
1147
|
+
|
|
1148
|
+
4. **French Audio Preference**
|
|
1149
|
+
- By default, mkv2cast selects French audio tracks when available
|
|
1150
|
+
- Falls back to the first audio track if no French track found
|
|
1151
|
+
|
|
1152
|
+
5. **HEVC/H.265 Transcoding**
|
|
1153
|
+
- By default, HEVC content is transcoded to H.264
|
|
1154
|
+
- Use `--allow-hevc` if your device supports HEVC
|
|
1155
|
+
|
|
1156
|
+
6. **Disk Space**
|
|
1157
|
+
- Ensure sufficient disk space for output files
|
|
1158
|
+
- Temporary files can also consume significant space during encoding
|
|
1159
|
+
|
|
1160
|
+
---
|
|
1161
|
+
|
|
1162
|
+
## Troubleshooting
|
|
1163
|
+
|
|
1164
|
+
### Common Issues
|
|
1165
|
+
|
|
1166
|
+
#### "ffmpeg not found"
|
|
1167
|
+
|
|
1168
|
+
```bash
|
|
1169
|
+
# Arch Linux
|
|
1170
|
+
sudo pacman -S ffmpeg
|
|
1171
|
+
|
|
1172
|
+
# Debian/Ubuntu
|
|
1173
|
+
sudo apt install ffmpeg
|
|
1174
|
+
|
|
1175
|
+
# Fedora
|
|
1176
|
+
sudo dnf install ffmpeg
|
|
1177
|
+
```
|
|
1178
|
+
|
|
1179
|
+
#### "VAAPI encoding failed"
|
|
1180
|
+
|
|
1181
|
+
```bash
|
|
1182
|
+
# Check VAAPI device exists
|
|
1183
|
+
ls -la /dev/dri/
|
|
1184
|
+
|
|
1185
|
+
# Install Intel drivers (for Intel GPUs)
|
|
1186
|
+
sudo pacman -S intel-media-driver # Arch
|
|
1187
|
+
sudo apt install intel-media-va-driver # Debian
|
|
1188
|
+
|
|
1189
|
+
# Test with mkv2cast
|
|
1190
|
+
mkv2cast --check-requirements
|
|
1191
|
+
```
|
|
1192
|
+
|
|
1193
|
+
#### "No progress display"
|
|
1194
|
+
|
|
1195
|
+
Install the `rich` Python package:
|
|
1196
|
+
|
|
1197
|
+
```bash
|
|
1198
|
+
# Arch Linux
|
|
1199
|
+
sudo pacman -S python-rich
|
|
1200
|
+
|
|
1201
|
+
# Other distributions
|
|
1202
|
+
pip install --user rich
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
#### "Permission denied" errors
|
|
1206
|
+
|
|
1207
|
+
Ensure the script is executable and in your PATH:
|
|
1208
|
+
|
|
1209
|
+
```bash
|
|
1210
|
+
chmod +x ~/.local/bin/mkv2cast
|
|
1211
|
+
echo $PATH | grep -q ".local/bin" || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
#### "TOML config not loading"
|
|
1215
|
+
|
|
1216
|
+
For Python < 3.11, install tomli:
|
|
1217
|
+
|
|
1218
|
+
```bash
|
|
1219
|
+
# Arch Linux
|
|
1220
|
+
sudo pacman -S python-tomli
|
|
1221
|
+
|
|
1222
|
+
# Other distributions
|
|
1223
|
+
pip install --user tomli
|
|
1224
|
+
```
|
|
1225
|
+
|
|
1226
|
+
### Getting Help
|
|
1227
|
+
|
|
1228
|
+
```bash
|
|
1229
|
+
# Check requirements
|
|
1230
|
+
mkv2cast --check-requirements
|
|
1231
|
+
|
|
1232
|
+
# View debug output
|
|
1233
|
+
mkv2cast --debug movie.mkv
|
|
1234
|
+
|
|
1235
|
+
# Dry run to see commands
|
|
1236
|
+
mkv2cast --dryrun movie.mkv
|
|
1237
|
+
|
|
1238
|
+
# Check logs
|
|
1239
|
+
ls ~/.local/state/mkv2cast/logs/
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
---
|
|
1243
|
+
|
|
1244
|
+
## Contributing
|
|
1245
|
+
|
|
1246
|
+
Contributions are welcome! Here's how to get started:
|
|
1247
|
+
|
|
1248
|
+
### Development Setup
|
|
1249
|
+
|
|
1250
|
+
```bash
|
|
1251
|
+
# Clone the repository
|
|
1252
|
+
git clone https://github.com/voldardard/mkv2cast.git
|
|
1253
|
+
cd mkv2cast
|
|
1254
|
+
|
|
1255
|
+
# Install development dependencies
|
|
1256
|
+
# Arch Linux:
|
|
1257
|
+
sudo pacman -S python-rich python-tomli
|
|
1258
|
+
# Other distributions:
|
|
1259
|
+
pip install --user rich tomli
|
|
1260
|
+
|
|
1261
|
+
# Run tests
|
|
1262
|
+
python mkv2cast.py --check-requirements
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
### Submitting Changes
|
|
1266
|
+
|
|
1267
|
+
1. Fork the repository
|
|
1268
|
+
2. Create a feature branch: `git checkout -b feature/my-feature`
|
|
1269
|
+
3. Make your changes
|
|
1270
|
+
4. Test thoroughly
|
|
1271
|
+
5. Commit with descriptive message: `git commit -m "Add feature X"`
|
|
1272
|
+
6. Push to your fork: `git push origin feature/my-feature`
|
|
1273
|
+
7. Open a Pull Request
|
|
1274
|
+
|
|
1275
|
+
### Code Style
|
|
1276
|
+
|
|
1277
|
+
- Follow PEP 8 for Python code
|
|
1278
|
+
- Add docstrings to new functions
|
|
1279
|
+
- Update documentation for new features
|
|
1280
|
+
- Test on both CPU and hardware-accelerated backends if possible
|
|
1281
|
+
|
|
1282
|
+
---
|
|
1283
|
+
|
|
1284
|
+
## Bug Reports
|
|
1285
|
+
|
|
1286
|
+
Found a bug? Please report it!
|
|
1287
|
+
|
|
1288
|
+
### How to Report
|
|
1289
|
+
|
|
1290
|
+
1. Go to [GitHub Issues](https://github.com/voldardard/mkv2cast/issues)
|
|
1291
|
+
2. Click "New Issue"
|
|
1292
|
+
3. Include:
|
|
1293
|
+
- Your operating system and version
|
|
1294
|
+
- Python version (`python3 --version`)
|
|
1295
|
+
- FFmpeg version (`ffmpeg -version`)
|
|
1296
|
+
- mkv2cast version (`mkv2cast --version`)
|
|
1297
|
+
- Output of `mkv2cast --check-requirements`
|
|
1298
|
+
- Steps to reproduce the bug
|
|
1299
|
+
- Error messages or log files (from `~/.local/state/mkv2cast/logs/`)
|
|
1300
|
+
|
|
1301
|
+
### Example Bug Report
|
|
1302
|
+
|
|
1303
|
+
```
|
|
1304
|
+
### Environment
|
|
1305
|
+
- OS: Arch Linux 2026.01
|
|
1306
|
+
- Python: 3.12.1
|
|
1307
|
+
- FFmpeg: 7.0
|
|
1308
|
+
- mkv2cast: 1.0.0
|
|
1309
|
+
|
|
1310
|
+
### Description
|
|
1311
|
+
Encoding fails with VAAPI on AMD GPU...
|
|
1312
|
+
|
|
1313
|
+
### Steps to Reproduce
|
|
1314
|
+
1. Run `mkv2cast --hw vaapi movie.mkv`
|
|
1315
|
+
2. Error occurs at 15%
|
|
1316
|
+
|
|
1317
|
+
### Error Output
|
|
1318
|
+
[paste error here]
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
---
|
|
1322
|
+
|
|
1323
|
+
## Web Interface
|
|
1324
|
+
|
|
1325
|
+
Looking for a web-based interface? Check out **[mkv2castUI](https://github.com/voldardard/mkv2castUI)** - a full-featured web application for mkv2cast with:
|
|
1326
|
+
|
|
1327
|
+
- 🌐 **Web Upload**: Drag and drop MKV files for conversion
|
|
1328
|
+
- 📊 **Real-time Progress**: WebSocket-based progress tracking
|
|
1329
|
+
- 🔐 **OAuth Authentication**: Sign in with Google or GitHub
|
|
1330
|
+
- 💳 **Subscription Tiers**: Free, Pro, and Enterprise plans
|
|
1331
|
+
- 🐳 **Docker Ready**: Easy deployment with Docker Compose
|
|
1332
|
+
|
|
1333
|
+
```bash
|
|
1334
|
+
git clone https://github.com/voldardard/mkv2castUI.git
|
|
1335
|
+
cd mkv2castUI
|
|
1336
|
+
docker-compose up -d
|
|
1337
|
+
```
|
|
1338
|
+
|
|
1339
|
+
---
|
|
1340
|
+
|
|
1341
|
+
## Roadmap
|
|
1342
|
+
|
|
1343
|
+
| Feature | Priority | Complexity | Status |
|
|
1344
|
+
|---------|----------|------------|--------|
|
|
1345
|
+
| Profiles (fast/balanced/quality) | Medium | Low | ✅ Done |
|
|
1346
|
+
| Disk guards & quotas | High | Low | ✅ Done |
|
|
1347
|
+
| Metadata/chapters/attachments preservation | Medium | Medium | ✅ Done |
|
|
1348
|
+
| Pipeline auto-retry + CPU fallback | Medium | Medium | ✅ Done |
|
|
1349
|
+
| HDR to SDR tone mapping | Low | High | Planned |
|
|
1350
|
+
| Webhooks notifications | Low | Low | Planned |
|
|
1351
|
+
| Audio loudness normalization (EBU R128) | Medium | Medium | Planned |
|
|
1352
|
+
| Subtitle extraction + forced-burn options | Medium | Medium | Planned |
|
|
1353
|
+
| Integration Plex/Jellyfin | Low | High | Planned |
|
|
1354
|
+
| Automatic device capability detection (Chromecast/TV) | Medium | Medium | Idea |
|
|
1355
|
+
| Metrics export (Prometheus/StatsD) from history and live runs | Low | Medium | Idea |
|
|
1356
|
+
| Remote/agent workers for headless servers | Low | High | Idea |
|
|
1357
|
+
| Package signing (APT GPG + checksums) | Medium | Low | Idea |
|
|
1358
|
+
|
|
1359
|
+
### Recent Additions (v1.2.x)
|
|
1360
|
+
|
|
1361
|
+
- ✅ NVIDIA NVENC & AMD AMF hardware acceleration (auto-priority)
|
|
1362
|
+
- ✅ Audio & subtitle selection by language or track index
|
|
1363
|
+
- ✅ Watch mode (watchdog/inotify) with systemd unit and timer
|
|
1364
|
+
- ✅ JSON progress output + Python callbacks for integrations
|
|
1365
|
+
- ✅ Library-friendly config factory (`Config.for_library`) and batch API
|
|
1366
|
+
- ✅ Multi-language CLI (EN, FR, ES, IT, DE) and desktop notifications
|
|
1367
|
+
|
|
1368
|
+
Have a feature request? [Open an issue](https://github.com/voldardard/mkv2cast/issues)!
|
|
1369
|
+
|
|
1370
|
+
---
|
|
1371
|
+
|
|
1372
|
+
## Acknowledgments
|
|
1373
|
+
|
|
1374
|
+
*This section will be updated as the project grows.*
|
|
1375
|
+
|
|
1376
|
+
Thanks to:
|
|
1377
|
+
- The FFmpeg team for their incredible media processing tools
|
|
1378
|
+
- The `rich` library for beautiful terminal interfaces
|
|
1379
|
+
- All contributors and users who report bugs and suggest improvements
|
|
1380
|
+
|
|
1381
|
+
---
|
|
1382
|
+
|
|
1383
|
+
## License
|
|
1384
|
+
|
|
1385
|
+
This project is licensed under the **GNU General Public License v3.0**.
|
|
1386
|
+
|
|
1387
|
+
```
|
|
1388
|
+
mkv2cast - Smart MKV to Chromecast-compatible converter
|
|
1389
|
+
Copyright (C) 2024-2026 voldardard
|
|
1390
|
+
|
|
1391
|
+
This program is free software: you can redistribute it and/or modify
|
|
1392
|
+
it under the terms of the GNU General Public License as published by
|
|
1393
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
1394
|
+
(at your option) any later version.
|
|
1395
|
+
|
|
1396
|
+
This program is distributed in the hope that it will be useful,
|
|
1397
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
1398
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
1399
|
+
GNU General Public License for more details.
|
|
1400
|
+
|
|
1401
|
+
You should have received a copy of the GNU General Public License
|
|
1402
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
See the [LICENSE](LICENSE) file for the full license text.
|
|
1406
|
+
|
|
1407
|
+
---
|
|
1408
|
+
|
|
1409
|
+
<p align="center">
|
|
1410
|
+
Made with ❤️ for the media enthusiast community
|
|
1411
|
+
</p>
|