#![cfg(feature = "encode")]
use std::path::Path;
use unbundle::{FrameRange, MediaFile, VideoCodec, VideoEncoder, VideoEncoderOptions};
fn sample_video_path() -> &'static str {
"tests/fixtures/sample_video.mp4"
}
#[test]
fn write_frames_to_mp4() {
let path = sample_video_path();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("open");
let frames = unbundler
.video()
.frames(FrameRange::Range(0, 5))
.expect("extract frames");
let output = "tests/fixtures/test_writer_output.mp4";
let config = VideoEncoderOptions::default().frames_per_second(10);
let result = VideoEncoder::new(config).write(output, &frames);
if let Err(ref e) = result {
let msg = format!("{e}");
if msg.contains("cannot open encoder") || msg.contains("codec") {
eprintln!("Skipping: H264 encoder not available ({msg})");
return;
}
}
result.expect("write video");
assert!(Path::new(output).exists());
let file_size = std::fs::metadata(output).unwrap().len();
assert!(file_size > 0, "output file should be non-empty");
std::fs::remove_file(output).ok();
}
#[test]
fn write_frames_with_resolution() {
let path = sample_video_path();
if !Path::new(path).exists() {
return;
}
let mut unbundler = MediaFile::open(path).expect("open");
let frames = unbundler
.video()
.frames(FrameRange::Range(0, 3))
.expect("extract frames");
let output = "tests/fixtures/test_writer_resized.mp4";
let config = VideoEncoderOptions::default()
.frames_per_second(5)
.resolution(160, 120)
.codec(VideoCodec::H264);
let result = VideoEncoder::new(config).write(output, &frames);
if let Err(ref e) = result {
let msg = format!("{e}");
if msg.contains("cannot open encoder") || msg.contains("codec") {
eprintln!("Skipping: H264 encoder not available ({msg})");
return;
}
}
result.expect("write resized video");
assert!(Path::new(output).exists());
std::fs::remove_file(output).ok();
}
#[test]
fn write_empty_frames_returns_error() {
let output = "tests/fixtures/test_writer_empty.mp4";
let config = VideoEncoderOptions::default();
let result = VideoEncoder::new(config).write(output, &[]);
assert!(result.is_err(), "should error on empty frames");
}
#[test]
fn video_encoder_options_builder() {
let config = VideoEncoderOptions::default()
.frames_per_second(24)
.resolution(1920, 1080)
.codec(VideoCodec::H265)
.crf(18)
.bitrate(5_000_000);
assert_eq!(config.frames_per_second, 24);
assert_eq!(config.width, Some(1920));
assert_eq!(config.height, Some(1080));
assert_eq!(config.codec, VideoCodec::H265);
assert_eq!(config.crf, Some(18));
assert_eq!(config.bitrate, Some(5_000_000));
}
#[test]
fn video_encoder_options_with_aliases_builder() {
let config = VideoEncoderOptions::default()
.with_frames_per_second(24)
.with_resolution(1920, 1080)
.with_codec(VideoCodec::H265)
.with_crf(18)
.with_bitrate(5_000_000);
assert_eq!(config.frames_per_second, 24);
assert_eq!(config.width, Some(1920));
assert_eq!(config.height, Some(1080));
assert_eq!(config.codec, VideoCodec::H265);
assert_eq!(config.crf, Some(18));
assert_eq!(config.bitrate, Some(5_000_000));
}