#![allow(clippy::unwrap_used)]
mod fixtures;
use ff_encode::{AudioCodec, VideoCodec, VideoEncoder};
use ff_format::{AudioFrame, SampleFormat};
use fixtures::{FileGuard, assert_valid_output_file, create_black_frame, test_output_path};
#[test]
fn test_video_audio_mpeg4_aac() {
let output_path = test_output_path("video_audio_mpeg4_aac.mp4");
let _guard = FileGuard::new(output_path.clone());
let result = VideoEncoder::create(&output_path)
.video(640, 480, 30.0)
.video_codec(VideoCodec::Mpeg4) .audio(48000, 2) .audio_codec(AudioCodec::Aac)
.audio_bitrate(192_000)
.build();
let mut encoder = match result {
Ok(enc) => enc,
Err(e) => {
println!("Encoder creation failed (no suitable codec): {}", e);
return; }
};
assert!(
!encoder.actual_video_codec().is_empty(),
"Video codec should be set"
);
assert!(
!encoder.actual_audio_codec().is_empty(),
"Audio codec should be set"
);
println!("Using video codec: {}", encoder.actual_video_codec());
println!("Using audio codec: {}", encoder.actual_audio_codec());
let video_frames = 30;
let audio_samples_per_frame = 1024; let audio_frames_needed =
(48000.0 * video_frames as f64 / 30.0 / audio_samples_per_frame as f64).ceil() as usize;
let mut audio_sample_offset = 0;
for _ in 0..video_frames {
let video_frame = create_black_frame(640, 480);
encoder
.push_video(&video_frame)
.expect("Failed to push video frame");
}
for _ in 0..audio_frames_needed {
let mut audio_frame =
AudioFrame::empty(audio_samples_per_frame, 2, 48000, SampleFormat::F32)
.expect("Failed to create audio frame");
if let Some(samples) = audio_frame.as_f32_mut() {
for (j, sample) in samples.iter_mut().enumerate() {
let t = (audio_sample_offset + j / 2) as f32 / 48000.0;
*sample = (t * 440.0 * 2.0 * std::f32::consts::PI).sin() * 0.3;
}
}
encoder
.push_audio(&audio_frame)
.expect("Failed to push audio frame");
audio_sample_offset += audio_samples_per_frame;
}
encoder.finish().expect("Failed to finish encoding");
assert_valid_output_file(&output_path);
let file_size = std::fs::metadata(&output_path).unwrap().len();
assert!(
file_size > 10_000,
"Output file size ({} bytes) is too small",
file_size
);
println!(
"Output file size: {} bytes (video+audio encoded successfully)",
file_size
);
}
#[test]
fn test_video_audio_vp9_opus() {
let output_path = test_output_path("video_audio_vp9_opus.webm");
let _guard = FileGuard::new(output_path.clone());
let result = VideoEncoder::create(&output_path)
.video(640, 480, 30.0)
.video_codec(VideoCodec::Vp9)
.audio(48000, 2)
.audio_codec(AudioCodec::Opus)
.audio_bitrate(128_000)
.build();
let mut encoder = match result {
Ok(enc) => enc,
Err(e) => {
println!("Encoder creation failed (no suitable codec): {}", e);
return; }
};
assert!(!encoder.actual_video_codec().is_empty());
assert!(!encoder.actual_audio_codec().is_empty());
println!("Using video codec: {}", encoder.actual_video_codec());
println!("Using audio codec: {}", encoder.actual_audio_codec());
let video_frames = 15;
let audio_samples_per_frame = 960; let audio_frames_needed =
(48000.0 * video_frames as f64 / 30.0 / audio_samples_per_frame as f64).ceil() as usize;
let mut audio_sample_offset = 0;
for _ in 0..video_frames {
let video_frame = create_black_frame(640, 480);
encoder.push_video(&video_frame).unwrap();
}
for _ in 0..audio_frames_needed {
let mut audio_frame =
AudioFrame::empty(audio_samples_per_frame, 2, 48000, SampleFormat::F32)
.expect("Failed to create audio frame");
if let Some(samples) = audio_frame.as_f32_mut() {
for (j, sample) in samples.iter_mut().enumerate() {
let t = (audio_sample_offset + j / 2) as f32 / 48000.0;
*sample = (t * 880.0 * 2.0 * std::f32::consts::PI).sin() * 0.3;
}
}
encoder.push_audio(&audio_frame).unwrap();
audio_sample_offset += audio_samples_per_frame;
}
encoder.finish().unwrap();
assert_valid_output_file(&output_path);
let file_size = std::fs::metadata(&output_path).unwrap().len();
assert!(
file_size > 5_000,
"Output file size ({file_size} bytes) is too small"
);
println!("Output file size: {file_size} bytes (VP9+Opus encoded successfully)");
}
#[test]
fn test_video_only_no_regression() {
let output_path = test_output_path("video_only_no_regression.mp4");
let _guard = FileGuard::new(output_path.clone());
let mut encoder = VideoEncoder::create(&output_path)
.video(640, 480, 30.0)
.video_codec(VideoCodec::Mpeg4)
.build()
.expect("Failed to build encoder");
assert!(!encoder.actual_video_codec().is_empty());
assert_eq!(encoder.actual_audio_codec(), "");
for _ in 0..15 {
let frame = create_black_frame(640, 480);
encoder.push_video(&frame).unwrap();
}
encoder.finish().unwrap();
assert_valid_output_file(&output_path);
}