pub mod common;
use std::fs;
use std::env;
use ffprobe::ffprobe;
use file_format::FileFormat;
use pretty_assertions::assert_eq;
use dash_mpd::fetch::DashDownloader;
use common::{check_file_size_approx, check_media_duration, setup_logging};
#[tokio::test]
async fn test_lang_prefer_spa() {
setup_logging();
if env::var("CI").is_ok() {
return;
}
let mpd_url = "https://refapp.hbbtv.org/videos/02_gran_dillama_1080p_ma_25f75g6sv5/manifest.mpd";
let out = env::temp_dir().join("dillama-spa.mp4");
if out.exists() {
let _ = fs::remove_file(&out);
}
DashDownloader::new(mpd_url)
.worst_quality()
.sandbox(true)
.max_error_count(5)
.record_metainformation(true)
.prefer_language(String::from("spa"))
.download_to(&out).await
.unwrap();
check_file_size_approx(&out, 11_809_117);
let format = FileFormat::from_file(&out).unwrap();
assert_eq!(format, FileFormat::Mpeg4Part14Video);
let meta = ffprobe(&out).unwrap();
assert_eq!(meta.streams.len(), 2);
let stream = &meta.streams[1];
assert_eq!(stream.codec_type, Some(String::from("audio")));
assert_eq!(stream.codec_name, Some(String::from("aac")));
let tags = stream.tags.as_ref().unwrap();
assert_eq!(tags.language, Some(String::from("spa")));
let _ = fs::remove_file(out);
}
#[tokio::test]
async fn test_lang_prefer_chi() {
setup_logging();
if env::var("CI").is_ok() {
return;
}
let mpd_url = "https://refapp.hbbtv.org/videos/02_gran_dillama_1080p_ma_25f75g6sv5/manifest.mpd";
let out = env::temp_dir().join("dillama-chi.mp4");
if out.exists() {
let _ = fs::remove_file(&out);
}
DashDownloader::new(mpd_url)
.worst_quality()
.sandbox(true)
.max_error_count(5)
.record_metainformation(true)
.prefer_audio_language(String::from("chi"))
.download_to(&out).await
.unwrap();
check_file_size_approx(&out, 11_809_117);
let format = FileFormat::from_file(&out).unwrap();
assert_eq!(format, FileFormat::Mpeg4Part14Video);
let meta = ffprobe(&out).unwrap();
assert_eq!(meta.streams.len(), 2);
let stream = &meta.streams[1];
assert_eq!(stream.codec_type, Some(String::from("audio")));
assert_eq!(stream.codec_name, Some(String::from("aac")));
let tags = stream.tags.as_ref().unwrap();
assert_eq!(tags.language, Some(String::from("chi")));
let _ = fs::remove_file(out);
}
#[tokio::test]
async fn test_subtitle_lang_stpp_im1t() {
setup_logging();
if env::var("CI").is_ok() {
return;
}
let mpd = "http://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-mobile.mpd";
let outpath = env::temp_dir().join("im1t-subs.mp4");
if outpath.exists() {
let _ = fs::remove_file(&outpath);
}
DashDownloader::new(mpd)
.fetch_audio(true)
.fetch_video(true)
.fetch_subtitles(true)
.prefer_language(String::from("fra"))
.verbosity(2)
.sandbox(true)
.download_to(&outpath).await
.unwrap();
let meta = ffprobe(&outpath).unwrap();
assert_eq!(meta.streams.len(), 3);
let audio = &meta.streams[1];
assert_eq!(audio.codec_type, Some(String::from("audio")));
assert_eq!(audio.codec_name, Some(String::from("aac")));
let tags = audio.tags.as_ref().unwrap();
assert_eq!(tags.language, Some(String::from("fra")));
let stpp = &meta.streams[2];
assert_eq!(stpp.codec_tag_string, "stpp");
let subtags = stpp.tags.as_ref().unwrap();
assert_eq!(subtags.language, Some(String::from("fra")));
check_media_duration(&outpath, 3600.0);
let _ = fs::remove_file(outpath);
}
#[tokio::test]
async fn test_subtitle_lang_different() {
setup_logging();
if env::var("CI").is_ok() {
return;
}
let mpd = "http://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-mobile.mpd";
let outpath = env::temp_dir().join("subs-prefer-lang.mp4");
if outpath.exists() {
let _ = fs::remove_file(&outpath);
}
DashDownloader::new(mpd)
.fetch_audio(true)
.fetch_video(true)
.fetch_subtitles(true)
.prefer_audio_language(String::from("fra"))
.prefer_subtitle_language(String::from("deu"))
.verbosity(1)
.sandbox(true)
.download_to(&outpath).await
.unwrap();
let meta = ffprobe(&outpath).unwrap();
assert_eq!(meta.streams.len(), 3);
let audio = meta.streams.iter()
.find(|s| s.codec_type.eq(&Some(String::from("audio"))))
.expect("finding audio stream");
assert_eq!(audio.codec_type, Some(String::from("audio")));
assert_eq!(audio.codec_name, Some(String::from("aac")));
let tags = audio.tags.as_ref().unwrap();
assert_eq!(tags.language, Some(String::from("fra")));
let subs = meta.streams.iter()
.find(|s| s.codec_type.eq(&Some(String::from("subtitle"))))
.expect("finding embedded subtitle track");
assert_eq!(subs.codec_tag_string, "stpp");
let subtags = subs.tags.as_ref().unwrap();
assert_eq!(subtags.language, Some(String::from("deu")));
check_media_duration(&outpath, 3600.0);
let _ = fs::remove_file(outpath);
}
#[tokio::test]
async fn test_lang_en_multilang() {
setup_logging();
if env::var("CI").is_ok() {
return;
}
let mpd_url = "https://media.axprod.net/TestVectors/Cmaf/clear_1080p_h264/manifest.mpd";
let tmpd = tempfile::tempdir().unwrap();
let out = tmpd.path().join("axprod-multilang.mp4");
DashDownloader::new(mpd_url)
.worst_quality()
.sandbox(true)
.without_content_type_checks()
.prefer_language(String::from("en-low"))
.audio_only()
.download_to(&out).await
.unwrap();
check_file_size_approx(&out, 12_036_135);
let format = FileFormat::from_file(&out).unwrap();
assert_eq!(format, FileFormat::Mpeg4Part14Audio);
let meta = ffprobe(&out).unwrap();
assert_eq!(meta.streams.len(), 1);
let audio = meta.streams.iter()
.find(|s| s.codec_type.eq(&Some(String::from("audio"))))
.expect("finding audio stream");
assert_eq!(audio.codec_name, Some(String::from("aac")));
let entries = fs::read_dir(tmpd.path()).unwrap();
let count = entries.count();
assert_eq!(count, 1, "Expecting a single output file, got {count}");
let _ = fs::remove_dir_all(tmpd);
}