Skip to main content

Crate mp4decrypt

Crate mp4decrypt 

Source
Expand description

This crate provides a safe high-level API to decrypt CENC/CENS/CBC1/CBCS protected MP4 content using Bento4.

§Environment Variables

The following environment variables can be used to configure the Bento4 library location:

VariableDescription
BENTO4_DIRDirectory of a Bento4 installation. Should contain lib and include subdirectories.
BENTO4_VENDORIf set, always build and link against the vendored Bento4 version.

These variables can also be prefixed with the upper-cased target architecture (e.g. X86_64_UNKNOWN_LINUX_GNU_BENTO4_DIR), which is useful for cross-compilation.

§Quick Start

use mp4decrypt::Ap4CencDecryptingProcessor;
use std::{error::Error, fs, io::Write};

fn main() -> Result<(), Box<dyn Error>> {
    // Create a processor with decryption keys
    let processor = Ap4CencDecryptingProcessor::new()
        .key("eb676abbcb345e96bbcf616630f1a3da", "100b6c20940f779a4589152b57d2dacb")?
        .build()?;

    // Decrypt in memory
    let init_data = fs::read("init.mp4")?;
    let segment_data = fs::read("segment.m4s")?;
    let decrypted = processor.decrypt(&segment_data, Some(&init_data))?;

    // Write playable MP4 (init + decrypted segment)
    let mut f = fs::File::create("output.mp4")?;
    f.write_all(&init_data)?;
    f.write_all(&decrypted)?;

    Ok(())
}

§Multithreaded Decryption

The processor is thread-safe and can be shared across multiple threads using Arc. This is useful for decrypting multiple segments in parallel:

use mp4decrypt::Ap4CencDecryptingProcessor;
use std::{fs, sync::Arc, thread};

fn main() -> Result<(), mp4decrypt::Error> {
    // Create a shared processor
    let processor = Arc::new(
        Ap4CencDecryptingProcessor::new()
            .key("eb676abbcb345e96bbcf616630f1a3da", "100b6c20940f779a4589152b57d2dacb")?
            .build()?
    );

    let init_data = Arc::new(fs::read("init.mp4").unwrap());

    // Spawn multiple threads to decrypt segments in parallel
    let handles: Vec<_> = (1..=10)
        .map(|i| {
            let processor = Arc::clone(&processor);
            let init = Arc::clone(&init_data);

            thread::spawn(move || {
                let segment = fs::read(format!("segment_{}.m4s", i)).unwrap();
                let decrypted = processor.decrypt(&segment, Some(&*init)).unwrap();

                // Write playable MP4 (init + decrypted segment)
                let mut f = fs::File::create(format!("decrypted_{}.mp4", i)).unwrap();
                use std::io::Write;
                f.write_all(&*init).unwrap();
                f.write_all(&decrypted).unwrap();
            })
        })
        .collect();

    // Wait for all threads to complete
    for handle in handles {
        handle.join().expect("Thread panicked");
    }

    Ok(())
}

§File-Based Decryption

For large files or when you want to avoid loading everything into memory:

use mp4decrypt::Ap4CencDecryptingProcessor;

fn main() -> Result<(), mp4decrypt::Error> {
    let processor = Ap4CencDecryptingProcessor::new()
        .key("eb676abbcb345e96bbcf616630f1a3da", "100b6c20940f779a4589152b57d2dacb")?
        .build()?;

    // Decrypt directly from file to file
    processor.decrypt_file(
        "encrypted_segment.m4s",
        "decrypted_segment.m4s",
        Some("init.mp4"),
    )?;

    Ok(())
}

Structs§

Ap4CencDecryptingProcessor
A CENC (Common Encryption) decrypting processor for MP4 files.
Ap4CencDecryptingProcessorBuilder
Builder for creating Ap4CencDecryptingProcessor instances.

Enums§

Error
Error types returned by the mp4decrypt operations.