Python wrapper for DCP-o-matic CLI tools (DCP creation and KDM generation).
- Python 3.12+
- DCP-o-matic installed (provides
dcpomatic2_cli,dcpomatic2_kdm_cli, anddcpomatic2_create)
uv add pykdmOr with pip:
pip install pykdmGenerate a KDM for an encrypted DCP:
pykdm kdm generate /path/to/dcpomatic-project \
-c /path/to/certificate.pem \
-o /path/to/output.kdm.xml \
-f "2024-01-01" \
-t "2024-01-31" \
--cinema-name "My Cinema" \
--screen-name "Screen 1"Note: The path should be the DCP-o-matic project folder (containing metadata.xml),
not the DCP output subfolder.
Generate a KDM from a DKDM:
pykdm kdm generate-dkdm /path/to/dkdm.xml \
-c /path/to/certificate.pem \
-o /path/to/output.kdm.xml \
-f "2024-01-01" \
-t "2024-01-31"Create a DCP from a DCP-o-matic project:
pykdm dcp create /path/to/project.dcp -o /path/to/outputCreate an encrypted DCP:
pykdm dcp create /path/to/project.dcp -o /path/to/output -eCreate a DCP-o-matic project from video/audio files:
pykdm dcp create-from-video video.mp4 -o ./my-project -n "My Film"Create a project with multiple content files:
pykdm dcp create-from-video video.mp4 audio.wav -o ./projectCreate a project and build the DCP in one step:
pykdm dcp create-from-video video.mp4 -o ./project --buildCreate an encrypted DCP with custom output location:
pykdm dcp create-from-video video.mp4 -o ./project -e --build --dcp-output ./dcpSpecify content type and resolution:
pykdm dcp create-from-video video.mp4 -o ./project -c TLR --fourk --standard smpteGenerate a test projector certificate for KDM testing:
pykdm cert generate test_projector.pemGenerate with custom device info:
pykdm cert generate projector.pem -m Barco -M DP2K -s ABC123Generate with different DCI role:
pykdm cert generate cert.pem --role LINK_DECRYPTORGenerate a CA + leaf certificate chain:
pykdm cert generate-chain ./test-certs -m Christie -M CP4230 -s XYZ789pykdm kdm version
pykdm dcp version
pykdm dcp project-versionRun pykdm --help or pykdm <command> --help for all available options.
from datetime import datetime, timedelta
from pathlib import Path
from pykdm import KDMGenerator, KDMType
generator = KDMGenerator()
# Note: project should be the DCP-o-matic project folder (containing metadata.xml),
# not the DCP output subfolder
result = generator.generate(
project=Path("/path/to/dcpomatic-project"),
certificate=Path("/path/to/certificate.pem"),
output=Path("/path/to/output.kdm.xml"),
valid_from=datetime.now(),
valid_to=datetime.now() + timedelta(days=7),
kdm_type=KDMType.MODIFIED_TRANSITIONAL_1,
cinema_name="My Cinema",
screen_name="Screen 1",
)
print(f"KDM created at: {result.output_path}")from pathlib import Path
from pykdm import DCPCreator
creator = DCPCreator()
result = creator.create(
project=Path("/path/to/project.dcp"),
output=Path("/path/to/output"),
encrypt=True,
)
print(f"DCP created at: {result.output_path}")from pathlib import Path
from pykdm import DCPProjectCreator, DCPContentType, ContainerRatio, DCPStandard, Resolution
creator = DCPProjectCreator()
# Create a project
result = creator.create(
content=Path("/path/to/video.mp4"),
output=Path("/path/to/project"),
name="My Film",
content_type=DCPContentType.FTR,
container_ratio=ContainerRatio.RATIO_185,
standard=DCPStandard.SMPTE,
resolution=Resolution.TWO_K,
)
print(f"Project created at: {result.output_path}")Create and build DCP in one step:
from pathlib import Path
from pykdm import DCPProjectCreator
creator = DCPProjectCreator()
project_result, dcp_result = creator.create_and_build(
content=[Path("/path/to/video.mp4"), Path("/path/to/audio.wav")],
output=Path("/path/to/project"),
dcp_output=Path("/path/to/dcp"),
name="My Film",
encrypt=True,
)
print(f"Project created at: {project_result.output_path}")
print(f"DCP created at: {dcp_result.output_path}")from pathlib import Path
from pykdm import CertificateGenerator, DCIRole
generator = CertificateGenerator()
# Generate a single test certificate
result = generator.generate(
output=Path("projector.pem"),
manufacturer="Barco",
model="DP2K",
serial="ABC123",
role=DCIRole.PROJECTOR,
validity_days=3650,
)
print(f"Certificate: {result.certificate_path}")
print(f"Private key: {result.private_key_path}")
print(f"Thumbprint: {result.thumbprint}")Generate a CA + leaf certificate chain:
from pathlib import Path
from pykdm import CertificateGenerator
generator = CertificateGenerator()
ca_result, leaf_result = generator.generate_chain(
output_dir=Path("./test-certs"),
manufacturer="Christie",
model="CP4230",
serial="XYZ789",
)
print(f"CA certificate: {ca_result.certificate_path}")
print(f"Leaf certificate: {leaf_result.certificate_path}")modified-transitional-1(default) - Most compatible formatdci-any- DCI compliant, any devicedci-specific- DCI compliant, specific device
FTR- FeatureSHR- ShortTLR- TrailerTST- TestXSN- TransitionalRTG- RatingTSR- TeaserPOL- PolicyPSA- Public Service AnnouncementADV- Advertisement
119- 1.19:1133- 1.33:1 (4:3)137- 1.37:1 (Academy)138- 1.38:1166- 1.66:1 (European Widescreen)178- 1.78:1 (16:9)185- 1.85:1 (Flat)239- 2.39:1 (Scope)
smpte- SMPTE standard (recommended)interop- Interop standard (legacy)
For test certificate generation:
PROJECTOR- Media Decryptor (LE.SPB-MD) - defaultLINK_DECRYPTOR- Link Decryptor (LE.SPB-LD)SECURE_PROCESSOR- Secure Processor (LE.SPB-SP)CS- Content SignerSMPTE- SMPTE role
Note: Test certificates are self-signed and won't work with real DCI infrastructure.
MIT