Use bit rate instead of resolution in making dedup decision.
Keep lower resolution movie if it is higher bit rate.
This commit is contained in:
parent
974d9386fb
commit
150bdfddef
14
src/lib.rs
14
src/lib.rs
@ -324,6 +324,16 @@ pub struct Movie {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Movie {
|
impl Movie {
|
||||||
|
fn min_bit_rate(&self) -> Option<usize> {
|
||||||
|
if self.files.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.files.iter().fold(usize::max_value(), |acc, (_, cmd)| {
|
||||||
|
std::cmp::min(acc, cmd.bit_rate)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn min_resolution(&self) -> Option<Resolution> {
|
fn min_resolution(&self) -> Option<Resolution> {
|
||||||
if self.files.is_empty() {
|
if self.files.is_empty() {
|
||||||
None
|
None
|
||||||
@ -371,8 +381,8 @@ impl Movies {
|
|||||||
let mut dupes = Vec::new();
|
let mut dupes = Vec::new();
|
||||||
for (_parent, mut movies) in movie_counter.into_iter() {
|
for (_parent, mut movies) in movie_counter.into_iter() {
|
||||||
if movies.len() > 1 {
|
if movies.len() > 1 {
|
||||||
// Sort, smallest movie first.
|
// Sort, lowest bit_rate movie first
|
||||||
movies.sort_by(|a, b| a.min_resolution().cmp(&b.min_resolution()));
|
movies.sort_by(|a, b| a.min_bit_rate().cmp(&b.min_bit_rate()));
|
||||||
// Flip order, we care about the largest.
|
// Flip order, we care about the largest.
|
||||||
movies.reverse();
|
movies.reverse();
|
||||||
// Take the largest image, return the rest for removal.
|
// Take the largest image, return the rest for removal.
|
||||||
|
|||||||
@ -49,7 +49,7 @@ fn test_simple_library() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_tuple<R>(path: &str, res: R) -> (String, CompactMetadata)
|
fn build_tuple<R>(path: &str, res: R, bit_rate: usize) -> (String, CompactMetadata)
|
||||||
where
|
where
|
||||||
R: Into<Resolution>,
|
R: Into<Resolution>,
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ where
|
|||||||
path.to_string(),
|
path.to_string(),
|
||||||
CompactMetadata {
|
CompactMetadata {
|
||||||
filename: format!("./{}", path),
|
filename: format!("./{}", path),
|
||||||
bit_rate: 1,
|
bit_rate,
|
||||||
duration: 1.0,
|
duration: 1.0,
|
||||||
format_name: "test_format".to_string(),
|
format_name: "test_format".to_string(),
|
||||||
size: 1,
|
size: 1,
|
||||||
@ -72,14 +72,14 @@ where
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_movie<R>(paths: Vec<(&str, R)>) -> Movie
|
fn build_movie<R>(paths: Vec<(&str, R, usize)>) -> Movie
|
||||||
where
|
where
|
||||||
R: Into<Resolution>,
|
R: Into<Resolution>,
|
||||||
{
|
{
|
||||||
Movie {
|
Movie {
|
||||||
files: paths
|
files: paths
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(path, res)| build_tuple(path, res))
|
.map(|(path, res, bit_rate)| build_tuple(path, res, bit_rate))
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,26 +89,32 @@ fn build_complex_metadata() -> HashMap<String, CompactMetadata> {
|
|||||||
build_tuple(
|
build_tuple(
|
||||||
"One Movie With Year (2019)/abcdef123456789.mkv",
|
"One Movie With Year (2019)/abcdef123456789.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
1,
|
||||||
),
|
),
|
||||||
build_tuple(
|
build_tuple(
|
||||||
"One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv",
|
"One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1,
|
||||||
),
|
),
|
||||||
build_tuple(
|
build_tuple(
|
||||||
"One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv",
|
"One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1,
|
||||||
),
|
),
|
||||||
build_tuple(
|
build_tuple(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
build_tuple(
|
build_tuple(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
build_tuple(
|
build_tuple(
|
||||||
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
5000,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -121,30 +127,36 @@ fn build_complex_movies() -> Movies {
|
|||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"One Movie With Year (2019)/abcdef123456789.mkv",
|
"One Movie With Year (2019)/abcdef123456789.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
1,
|
||||||
)]),
|
)]),
|
||||||
build_movie(vec![
|
build_movie(vec![
|
||||||
(
|
(
|
||||||
"One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv",
|
"One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv",
|
"One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1,
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
build_movie(vec![
|
build_movie(vec![
|
||||||
(
|
(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
5000,
|
||||||
)]),
|
)]),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -192,15 +204,18 @@ fn test_duplicate_candidates() -> Result<(), Box<dyn Error>> {
|
|||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
"Two Movies With Multi Parts (2019)/somethingelse.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
5000,
|
||||||
)]),
|
)]),
|
||||||
vec![build_movie(vec![
|
vec![build_movie(vec![
|
||||||
(
|
(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
"Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
1000,
|
||||||
),
|
),
|
||||||
])],
|
])],
|
||||||
)];
|
)];
|
||||||
@ -215,10 +230,12 @@ fn test_fullmetal() -> Result<(), Box<dyn Error>> {
|
|||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"Full Metal Jacket (1987)/Full Metal Jacket.mp4",
|
"Full Metal Jacket (1987)/Full Metal Jacket.mp4",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
2581935,
|
||||||
)]),
|
)]),
|
||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv",
|
"Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
5719802,
|
||||||
)]),
|
)]),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -235,10 +252,53 @@ fn test_fullmetal() -> Result<(), Box<dyn Error>> {
|
|||||||
build_movie(vec![(
|
build_movie(vec![(
|
||||||
"Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv",
|
"Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv",
|
||||||
(1920, 1080),
|
(1920, 1080),
|
||||||
|
5719802,
|
||||||
)]),
|
)]),
|
||||||
vec![build_movie(vec![(
|
vec![build_movie(vec![(
|
||||||
"Full Metal Jacket (1987)/Full Metal Jacket.mp4",
|
"Full Metal Jacket (1987)/Full Metal Jacket.mp4",
|
||||||
(1280, 720),
|
(1280, 720),
|
||||||
|
2581935,
|
||||||
|
)])],
|
||||||
|
)];
|
||||||
|
validate_duplicates(got, want);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_keep_lower_res_higher_bit_rate() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut movies = Movies {
|
||||||
|
movies: vec![
|
||||||
|
build_movie(vec![(
|
||||||
|
"X Men The Last Stand (2006)/X.Men.The.Last.Stand.2006.1080p.BluRay.x264.DTS-ES.PRoDJi.mkv",
|
||||||
|
(1920, 800),
|
||||||
|
11349705,
|
||||||
|
)]),
|
||||||
|
build_movie(vec![(
|
||||||
|
"X Men The Last Stand (2006)/948f08a4ba784626ac13de77b77559dd.mkv",
|
||||||
|
(1920, 1080),
|
||||||
|
6574160,
|
||||||
|
)]),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
movies.movies.sort_by(|a, b| {
|
||||||
|
a.files
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.partial_cmp(&b.files.first().unwrap().0)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
let got = movies.duplicate_candidates();
|
||||||
|
let want = vec![(
|
||||||
|
build_movie(vec![(
|
||||||
|
"X Men The Last Stand (2006)/X.Men.The.Last.Stand.2006.1080p.BluRay.x264.DTS-ES.PRoDJi.mkv",
|
||||||
|
(1920, 800),
|
||||||
|
11349705,
|
||||||
|
)]),
|
||||||
|
vec![build_movie(vec![(
|
||||||
|
"X Men The Last Stand (2006)/948f08a4ba784626ac13de77b77559dd.mkv",
|
||||||
|
(1920, 1080),
|
||||||
|
6574160,
|
||||||
)])],
|
)])],
|
||||||
)];
|
)];
|
||||||
validate_duplicates(got, want);
|
validate_duplicates(got, want);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user