CLI-Tool zur Konvertierung von DTS/DTS-HD Audiospuren in MKV-Dateien zu AC3
Project description
kinofilm-manager
Python-CLI-Tool zur Konvertierung von DTS/DTS-HD Audiospuren in MKV-Dateien zu Dolby Digital AC3. Das Ergebnis ist eine neue MKV-Datei, die direkt in Subler importiert und zu M4V/MP4 für Apple TV und Infuse weiterverarbeitet werden kann.
Für Artwork und Fanart wird die TMDB-API (The Movie Database) verwendet.
Hintergrund und Motivation
Das Container-Problem
Der MP4/M4V-Container – der native Container für Apple TV, iTunes und Infuse – unterstützt DTS und DTS-HD nicht. Dies ist eine Einschränkung des Container-Standards: DTS ist im MP4-Standard nicht als zulässiger Audio-Codec spezifiziert.
Wer eine Archivierungs-Pipeline aufbaut, die auf folgenden Komponenten basiert:
MKV (Quellformat) → Subler (Muxing/Metadaten) → M4V (Apple TV / Infuse)
steht vor dem Problem, dass Subler DTS-Spuren aus einem MKV nicht direkt in einen M4V-Container übernehmen kann. Der Workaround wäre ein manuelles Transcodieren in Subler – was aber keine Batch-Fähigkeit bietet und keinen kontrollierten Workflow erlaubt.
Die Lösung: Zweistufiger Workflow
Der Workflow wird sauber in zwei unabhängige Schritte getrennt:
Schritt 1: kinofilm-manager convert
MKV (mit DTS) → MKV (mit AC3)
Schritt 2: Subler (manuell oder via SublerCLI)
MKV (mit AC3) → M4V (für Apple TV / Infuse)
Dadurch bleibt Subler ein reines Muxing- und Metadaten-Tool und kinofilm-manager übernimmt die Audiokonvertierung deterministisch und reproduzierbar.
Unterstützte Audio-Codecs im M4V-Container
Zur Übersicht welche Audioformate im MP4/M4V-Container zulässig sind:
| Codec | M4V-kompatibel | Bemerkung |
|---|---|---|
| AAC | ✅ | Nativ |
| AC3 (Dolby Digital) | ✅ | Von Apple für M4V zugelassen |
| E-AC3 (Dolby Digital Plus) | ✅ | Inkl. Atmos-Metadata |
| DTS | ❌ | Nicht im MP4-Standard |
| DTS-HD HRA / MA | ❌ | Nicht im MP4-Standard |
| TrueHD | ❌ | Nicht im MP4-Standard |
Voraussetzungen
- Python 3.11 oder neuer
ffmpegundffprobeim PATH
Installation ffmpeg auf macOS:
brew install ffmpeg
Hinweis: HandBrake nicht via Homebrew installieren – es überschreibt shared Libraries (z.B.
libvpx) und kann zudyld: Library not loaded-Fehlern bei ffmpeg führen. HandBrake stattdessen als.appvia DMG installieren.
Installation
# Via pip
pip install kurmann-kinofilm-manager
# Via uv
uv pip install kurmann-kinofilm-manager
# Für Entwicklung (lokal)
git clone https://github.com/kurmann/kinofilm-manager.git
cd kinofilm-manager
pip install -e ".[dev]"
Verwendung
kinofilm-manager convert <input.mkv> [Optionen]
kinofilm-manager artwork fetch <video-file> [Optionen]
kinofilm-manager movie identify <video-file> [Optionen]
Parameter
| Argument | Kurz | Standard | Beschreibung |
|---|---|---|---|
INPUT_FILE |
– | – | Pfad zur Eingabe-MKV (Pflichtfeld) |
--output |
-o |
<input>_ac3.mkv |
Pfad zur Ausgabe-MKV |
--bitrate |
-b |
automatisch oder config-Wert |
AC3-Bitrate für alle konvertierten Spuren |
--dry-run / --no-dry-run |
– | false oder config-Wert |
Zeigt Analyse und FFmpeg-Befehl, erstellt keine Datei |
--verbose / --no-verbose |
-v |
false oder config-Wert |
Zusätzliche Diagnoseinformationen auf stderr |
Beispiele
# Einfachster Aufruf – Ausgabe landet neben der Quelldatei
kinofilm-manager convert "Film (2024).mkv"
# Ausgabepfad selbst bestimmen
kinofilm-manager convert "Film (2024).mkv" -o "Film (2024)_subler.mkv"
# Erst prüfen was passieren würde (empfohlen beim ersten Test)
kinofilm-manager convert "Film (2024).mkv" --dry-run
# Eigene Bitrate (kleinere Datei, geringfügig weniger Qualität)
kinofilm-manager convert "Film (2024).mkv" --bitrate 448k
# Persistente Defaults für künftige Aufrufe setzen
kinofilm-manager config set bitrate 448k
kinofilm-manager config set verbose true
# Pipeline: Ergebnis-Pfad auf stdout, Diagnose auf stderr
output=$(kinofilm-manager convert "Film (2024).mkv")
echo "Konvertierte Datei: $output"
Artwork / Fanart für Infuse
Für Infuse-kompatibles Fanart kann pro Videodatei ein Backdrop im Format
<Titel (Jahr)-fanart.jpg> geladen werden. Die Datei wird immer im gleichen
Verzeichnis wie die Videodatei gespeichert.
kinofilm-manager artwork fetch <video-file> [Optionen]
Unterstützte Eingaben
- Primär: Dateiname im Schema
<Titel (Jahr)>[ - Zusatz].m4v,.mkvoder.mp4; Zusätze nach-werden ignoriert - Alternativ:
--titleund--year, falls der Dateiname nicht parsebar ist - Direkter Lookup:
--tmdb-id, falls ein Film über Titel und Jahr nicht zuverlässig gefunden werden kann
Optionen
| Option | Standard | Beschreibung |
|---|---|---|
--title TEXT |
aus Dateiname | Alternativer Filmtitel |
--year INTEGER |
aus Dateiname | Erscheinungsjahr; nur zusammen mit --title |
--tmdb-id INTEGER |
– | Direkter TMDB-ID-Lookup; umgeht die Titelsuche. Kann nicht zusammen mit --title/--year verwendet werden |
--dry-run / --no-dry-run |
false oder config-Wert |
Prüft den Workflow ohne Dateiablage |
--language TEXT |
– | Suchsprache für TMDB, z.B. de-DE oder en-US |
--provider TEXT |
tmdb oder config-Wert |
Artwork-Provider; aktuell wird nur tmdb unterstützt |
--tmdb-api-key TEXT |
config-Wert |
TMDB API Key |
--interactive / --no-interactive |
false |
Erlaubt eine manuelle Auswahl bei mehrdeutigen Treffern |
Beispiele
# Fanart direkt neben der Videodatei speichern
kinofilm-manager artwork fetch "Frozen (2013).m4v" --tmdb-api-key "$TMDB_API_KEY"
# Parsebaren Dateinamen überschreiben
kinofilm-manager artwork fetch "film-final.mp4" --title "Frozen" --year 2013 --tmdb-api-key "$TMDB_API_KEY"
# Direkter TMDB-ID-Lookup für hartnäckige Suchfälle
kinofilm-manager artwork fetch "Neues von uns Kindern aus Bullerbü (1987).m4v" --tmdb-id 26111 --tmdb-api-key "$TMDB_API_KEY"
# Mehrdeutige Treffer bewusst interaktiv auswählen
kinofilm-manager artwork fetch "Frozen (2013).m4v" --interactive --tmdb-api-key "$TMDB_API_KEY"
# Workflow testen ohne Dateiablage
kinofilm-manager artwork fetch "Frozen (2013).m4v" --dry-run --tmdb-api-key "$TMDB_API_KEY"
Ausgabe-Konvention für artwork fetch
- stdout: Zielpfad der Fanart-Datei
- stderr: Parsing-/Such-Events, Auswahlhinweise, Fehlerdiagnosen
- Ohne
--interactivewird bei mehrdeutigen Treffern mit Exit-Code1abgebrochen - Mit
--dry-runwird der Zielpfad ausgegeben, aber keine Datei geschrieben
Verwendete Dienste
| Dienst | Verwendung | Nutzungsform |
|---|---|---|
| TMDB | Filmsuche und Backdrop-Download | Kostenlos, API-Key erforderlich |
Film-Identifikation: movie identify
Mit movie identify wird eine Videodatei so umbenannt, dass die TMDB-ID direkt im Dateinamen eingebettet ist. Das Format [tmdb-<id>] wird von Infuse direkt gelesen und ermöglicht eine zuverlässige Metadaten- und Artwork-Erkennung, ohne dass eine manuelle Zuordnung in Infuse erforderlich ist.
kinofilm-manager movie identify <video-file> [Optionen]
Beispiele
# Datei automatisch identifizieren und TMDB-ID anhängen
kinofilm-manager movie identify 'Wir Kinder aus Bullerbü (1986).m4v' --tmdb-api-key "$TMDB_API_KEY"
# → Wir Kinder aus Bullerbü (1986) [tmdb-21394].m4v
# Direkter Lookup per TMDB-ID (umgeht die Titelsuche)
kinofilm-manager movie identify 'Film (1987).m4v' --tmdb-id 26111 --tmdb-api-key "$TMDB_API_KEY"
# Mehrdeutige Treffer interaktiv auswählen
kinofilm-manager movie identify 'Pippi Langstrumpf (1969).m4v' --interactive --tmdb-api-key "$TMDB_API_KEY"
# Nur Zielpfad anzeigen, nicht umbenennen
kinofilm-manager movie identify 'Film (2000).m4v' --dry-run --tmdb-api-key "$TMDB_API_KEY"
Wenn bereits ein [tmdb-xxxx]-Suffix im Dateinamen vorhanden ist, wird er ersetzt, nicht doppelt angehängt.
Optionen
| Option | Standard | Beschreibung |
|---|---|---|
--title TEXT |
aus Dateiname | Alternativer Filmtitel |
--year INTEGER |
aus Dateiname | Erscheinungsjahr; nur zusammen mit --title |
--tmdb-id INTEGER |
– | Direkter TMDB-ID-Lookup; umgeht die Titelsuche. Kann nicht zusammen mit --title/--year verwendet werden |
--dry-run / --no-dry-run |
false oder config-Wert |
Zeigt Zielpfad, benennt aber nicht um |
--language TEXT |
– | Suchsprache für TMDB, z.B. de-DE oder en-US |
--provider TEXT |
tmdb oder config-Wert |
Provider; aktuell wird nur tmdb unterstützt |
--tmdb-api-key TEXT |
config-Wert |
TMDB API Key |
--interactive / --no-interactive |
false |
Erlaubt eine manuelle Auswahl bei mehrdeutigen Treffern |
Ausgabe-Konvention für movie identify
- stdout: Neuer Dateipfad nach der Umbenennung
- stderr: Such-Events, Auswahlhinweise, Fehlerdiagnosen
- Ohne
--interactivewird bei mehrdeutigen Treffern mit Exit-Code1abgebrochen - Mit
--dry-runwird der Zielpfad ausgegeben, aber die Datei nicht umbenannt
Persistente Konfiguration
Persistente CLI-Defaults werden XDG-konform in ~/.config/kinofilm-manager/config.toml
gespeichert. Falls XDG_CONFIG_HOME gesetzt ist, wird stattdessen
$XDG_CONFIG_HOME/kinofilm-manager/config.toml verwendet.
Unterstützte Konfigurationsschlüssel
| Schlüssel | Typ | Beschreibung |
|---|---|---|
bitrate |
String | Default für --bitrate, z.B. 448k oder 640k |
dry_run |
Boolean | Default für --dry-run / --no-dry-run |
verbose |
Boolean | Default für --verbose / --no-verbose |
artwork_provider |
String | Default für artwork fetch --provider (tmdb) |
tmdb_api_key |
String | Default für artwork fetch --tmdb-api-key |
CLI-Befehle
# Alle unterstützten Schlüssel und aktuelle Werte anzeigen
kinofilm-manager config list
# Einzelnen Wert setzen
kinofilm-manager config set bitrate 448k
kinofilm-manager config set dry_run false
kinofilm-manager config set artwork_provider tmdb
kinofilm-manager config set tmdb_api_key "<API_KEY>"
# Einzelnen Wert lesen
kinofilm-manager config get bitrate
Beispiel-Konfiguration
bitrate = "448k"
dry_run = false
verbose = true
artwork_provider = "tmdb"
tmdb_api_key = "your-key"
CLI-Optionen überschreiben persistierte Defaults immer explizit pro Aufruf. Die
Bibliotheks-API liest keine globale Konfiguration; technische Laufzeitoptionen werden
explizit als RuntimeOptions übergeben.
Ausgabekonvention
Gemäss den Architekturprinzipien gilt:
- stdout: Ergebnis-Pfad der konvertierten Datei (pipeline-freundlich)
- stderr: Stream-Analyse, Fortschritt, Warnungen (Rich-formatiert)
--verbose: Zusätzliche Diagnoseinformationen (FFmpeg-Befehl) auf stderr
API-Nutzung
kinofilm-manager kann auch als Python-Bibliothek verwendet werden:
from pathlib import Path
from kinofilm_manager.api import ConvertRequest, RuntimeOptions, convert
request = ConvertRequest(
input_path=Path("Film.mkv"),
)
runtime_options = RuntimeOptions(
dry_run=True,
bitrate="448k",
)
result = convert(request, runtime_options=runtime_options)
if result.success:
print(f"Konvertiert: {result.converted_count} Spuren")
for stream in result.streams:
print(f" #{stream.index}: {stream.codec_name} → {stream.action}")
Laufzeitoptionen und Konfiguration
ConvertRequest beschreibt nur den fachlichen Auftrag (input_path, optional output_path).
Technische Laufzeitoptionen wie Bitrate oder Dry-Run werden getrennt über
RuntimeOptions übergeben. Die CLI liest dafür auf Wunsch persistente Defaults aus
der XDG-Konfiguration und reicht sie explizit an die API weiter.
Fachlogik
1. DTS-Erkennung
DTS-Spuren werden über codec_name und profile aus den ffprobe-Metadaten erkannt:
dts(DTS Core)dts-hd/dtshd- Profile wie
DTS-HD HRA,DTS-HD MA
2. Duplikat-Erkennung: DTS überspringen wenn AC3 mit gleicher Kanalanzahl vorhanden
Viele MKV-Dateien enthalten bereits mehrere Audiospuren pro Sprache. Eine DTS-Spur wird nur dann übersprungen, wenn bereits eine AC3-Spur gleicher Sprache und mindestens gleicher Kanalanzahl vorhanden ist.
Eine vorhandene AC3 Stereo (2.0) Spur ist kein Ersatz für eine DTS 5.1 Spur – der Mehrkanal-Surround-Ton würde verloren gehen.
3. Kanalanzahl und Bitrate
AC3 (Dolby Digital) unterstützt maximal 5.1 (6 Kanäle). Die Bitrate wird automatisch je nach Kanalanzahl gewählt:
| Kanäle | Automatische Bitrate |
|---|---|
| Mono / Stereo | 192k |
| 5.1 | 640k |
| 7.1 (vor Downmix) | 640k |
4. 7.1 → 5.1 Downmix via pan-Filter
DTS-HD 7.1 wird via FFmpeg pan-Filter auf 5.1 downgemischt. Seitenkanäle (SL/SR) werden auf die Rear-Kanäle (BL/BR) überlagert mit Faktor 0.7 zur Clipping-Vermeidung. Frontkanäle bleiben unverändert.
5. Tonversatz (Audio Delay)
MKV-Dateien können pro Spur einen start_time-Wert enthalten. FFmpeg erhält -avoid_negative_ts make_zero für korrekte Übertragung.
6. Stream-Metadaten
Alle Stream-Metadaten (Sprache, Titel) werden explizit pro Stream übertragen. Für konvertierte DTS-Spuren wird der Titel automatisch neu generiert.
7. Untertitel-Kompatibilität
Inkompatible Untertitel-Streams (z.B. dvd_subtitle) werden erkannt und weggelassen. MKV-kompatible Formate (SRT, ASS, PGS, etc.) werden unverändert kopiert.
PGS-Untertitel und OCR: Blu-ray PGS-Untertitel werden als Bitmap ins MKV kopiert. Eine integrierte OCR-Lösung wurde evaluiert, wird aber bewusst nicht umgesetzt. Das Tool bleibt im Scope der Audio-Konvertierung. Subler übernimmt im nachgelagerten Schritt die OCR-Konvertierung der PGS-Untertitel beim Muxing zu M4V – mit guter Qualität.
Bekannte Einschränkungen
- DVD-Untertitel werden weggelassen. Workaround: In Subler als Bitmap importieren.
- AC3-Maximum ist 5.1 – 7.1-Material wird immer auf 5.1 downgemischt.
- Qualitätsverlust – DTS→AC3 ist verlustbehaftet. Für audiophile Ansprüche bleibt MKV mit DTS-HD das bessere Archivformat.
Weiterführender Workflow
Nach der Konvertierung empfiehlt sich folgender Workflow in Subler:
- Konvertierte MKV in Subler öffnen
- Gewünschte Spuren auswählen (typisch: eine Audiospur pro Sprache)
- PGS-Untertitel via Sublers integrierte OCR zu Text konvertieren (falls vorhanden)
- Metadaten ergänzen (Titel, Jahr, Beschreibung, Artwork)
- Als M4V exportieren
Änderungsverlauf
[2.2.0] – 2026-03-19
- Neuer Befehl
movie identify: identifiziert einen Film via TMDB und ergänzt[tmdb-<id>]im Dateinamen - Neues Modul
movie_searchmit wiederverwendbarer Film-Such- und Auswahllogik artwork fetch --tmdb-id: direkter TMDB-ID-Lookup ohne Titelsuche
[2.1.0] – 2026-03-18
- Neues Subcommand
kinofilm-manager configmitset,getundlist - Persistente XDG-Konfiguration unter
~/.config/kinofilm-manager/config.toml RuntimeOptionstrennt CLI-Laufzeitoptionen vonConvertRequest
[2.0.0] – 2026-03-12
- ⚠️ Breaking Change: Neuer CLI-Aufruf
kinofilm-manager convertstattpython3 mkv_dts_to_ac3.py - Restrukturierung als PyPI-Paket
kurmann-kinofilm-manager - CLI mit typer und rich, Ergebnisse auf stdout, Diagnose auf stderr
- Request/Result-API für programmatische Nutzung
[1.0.0] – 2026-03-12
- Erstveröffentlichung als einzelnes Script
Vollständiger Änderungsverlauf: CHANGELOG.md
Lizenz
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kurmann_kinofilm_manager-2.2.0.tar.gz.
File metadata
- Download URL: kurmann_kinofilm_manager-2.2.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cb2edf0eba9966ff2aae5d84c5b7e5ab0045a05e78477fc1fe51049515e5cac
|
|
| MD5 |
c707bd5c4e6d394d282caeb30c3ae62e
|
|
| BLAKE2b-256 |
7c3a232203836062c5c665871a901ce08b3d647fdc5057a48ad1264a96d972a5
|
Provenance
The following attestation bundles were made for kurmann_kinofilm_manager-2.2.0.tar.gz:
Publisher:
publish.yml on kurmann/kinofilm-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kurmann_kinofilm_manager-2.2.0.tar.gz -
Subject digest:
8cb2edf0eba9966ff2aae5d84c5b7e5ab0045a05e78477fc1fe51049515e5cac - Sigstore transparency entry: 1131917097
- Sigstore integration time:
-
Permalink:
kurmann/kinofilm-manager@2f286d4003a4f37630d69a5ad48e3d0a1135c713 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/kurmann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2f286d4003a4f37630d69a5ad48e3d0a1135c713 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kurmann_kinofilm_manager-2.2.0-py3-none-any.whl.
File metadata
- Download URL: kurmann_kinofilm_manager-2.2.0-py3-none-any.whl
- Upload date:
- Size: 30.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31f1de39b8285e52586f197e54314ac007801fb933a0d1a1c6622ac8c376e919
|
|
| MD5 |
05d88416534c2e4252401d9e1b636903
|
|
| BLAKE2b-256 |
224c7ab780567f781f80ac8f0323d23a27b004eaf68ea2e14985acdb7c0b5397
|
Provenance
The following attestation bundles were made for kurmann_kinofilm_manager-2.2.0-py3-none-any.whl:
Publisher:
publish.yml on kurmann/kinofilm-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kurmann_kinofilm_manager-2.2.0-py3-none-any.whl -
Subject digest:
31f1de39b8285e52586f197e54314ac007801fb933a0d1a1c6622ac8c376e919 - Sigstore transparency entry: 1131917228
- Sigstore integration time:
-
Permalink:
kurmann/kinofilm-manager@2f286d4003a4f37630d69a5ad48e3d0a1135c713 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/kurmann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2f286d4003a4f37630d69a5ad48e3d0a1135c713 -
Trigger Event:
release
-
Statement type: