unbundle 5.2.0

Unbundle media files - extract still frames, audio tracks, and subtitles from video files
Documentation
//! Subtitle stream-copy integration tests.
//!
//! These tests require fixture files generated by
//! `tests/fixtures/generate_fixtures.sh` (or `.bat` on Windows).

use std::{path::Path, time::Duration};

use unbundle::{MediaFile, UnbundleError};

fn sample_with_subtitles() -> &'static str {
    "tests/fixtures/sample_with_subtitles.mkv"
}

#[test]
fn stream_copy_subtitle_to_file() {
    let path = sample_with_subtitles();
    if !Path::new(path).exists() {
        return;
    }

    let output = tempfile::NamedTempFile::new().expect("Failed to create temp file");
    let output_path = output.path().with_extension("mkv");

    let mut unbundler = MediaFile::open(path).expect("Failed to open subtitle fixture");
    unbundler
        .subtitle()
        .stream_copy(&output_path)
        .expect("Failed to stream-copy subtitle to file");

    let written_bytes = std::fs::read(&output_path).expect("Failed to read output file");
    assert!(
        !written_bytes.is_empty(),
        "Expected non-empty output after subtitle stream copy"
    );

    let _ = std::fs::remove_file(&output_path);
}

#[test]
fn stream_copy_subtitle_range_to_file() {
    let path = sample_with_subtitles();
    if !Path::new(path).exists() {
        return;
    }

    let output = tempfile::NamedTempFile::new().expect("Failed to create temp file");
    let output_path = output.path().with_extension("mkv");

    let mut unbundler = MediaFile::open(path).expect("Failed to open subtitle fixture");
    unbundler
        .subtitle()
        .stream_copy_range(
            &output_path,
            Duration::from_millis(500),
            Duration::from_secs(3),
        )
        .expect("Failed to stream-copy subtitle range to file");

    let written_bytes = std::fs::read(&output_path).expect("Failed to read output file");
    assert!(
        !written_bytes.is_empty(),
        "Expected non-empty range output after subtitle stream copy"
    );

    let _ = std::fs::remove_file(&output_path);
}

#[test]
fn stream_copy_subtitle_to_memory() {
    let path = sample_with_subtitles();
    if !Path::new(path).exists() {
        return;
    }

    let mut unbundler = MediaFile::open(path).expect("Failed to open subtitle fixture");
    let bytes = unbundler
        .subtitle()
        .stream_copy_to_memory("matroska")
        .expect("Failed to stream-copy subtitle to memory");

    assert!(
        !bytes.is_empty(),
        "Expected non-empty in-memory payload after subtitle stream copy"
    );
}

#[test]
fn stream_copy_subtitle_invalid_range_returns_error() {
    let path = sample_with_subtitles();
    if !Path::new(path).exists() {
        return;
    }

    let mut unbundler = MediaFile::open(path).expect("Failed to open subtitle fixture");
    let result = unbundler.subtitle().stream_copy_range(
        "unused.mkv",
        Duration::from_secs(2),
        Duration::from_secs(1),
    );

    assert!(result.is_err(), "Expected invalid range error");
    assert!(
        matches!(result.unwrap_err(), UnbundleError::InvalidRange { .. }),
        "Expected InvalidRange variant"
    );
}