You've already forked flix
Improve title handling and rework catalog builder
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-mux"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "CLI for bulk media muxing"
|
||||
|
||||
@@ -5,6 +5,13 @@ use anyhow::{Context as _, Result};
|
||||
use crate::model::MediaFile;
|
||||
use crate::parser::{Matcher, Selector, StreamFlag, StreamType};
|
||||
|
||||
#[derive(Default)]
|
||||
struct OutputIndex {
|
||||
video: usize,
|
||||
audio: usize,
|
||||
subtitle: usize,
|
||||
}
|
||||
|
||||
pub fn mux_files<T>(
|
||||
dry_run: bool,
|
||||
files: &[MediaFile],
|
||||
@@ -40,14 +47,16 @@ fn mux(dry_run: bool, file: &MediaFile, selectors: &[Selector]) -> Result<()> {
|
||||
}
|
||||
|
||||
command = command.args(["-c:v", "copy", "-c:a", "copy", "-c:s", "mov_text"]);
|
||||
command = command.args(["-strict", "-2"]);
|
||||
command = command.args(["-movflags", "faststart+disable_chpl+write_colr"]);
|
||||
command = command.args(["-map_chapters", "-1"]);
|
||||
command = command.args(["-map_metadata", "-1"]);
|
||||
command = command.args(["-metadata:g", "encoding_tool=Skrundzflix"]);
|
||||
|
||||
let mut ouput_index = OutputIndex::default();
|
||||
for selector in selectors {
|
||||
command = command.args(
|
||||
make_metadata_args(file, selector)
|
||||
make_metadata_args(file, selector, &mut ouput_index)
|
||||
.with_context(|| format!("Failed to mux {:?}", file.path))?,
|
||||
);
|
||||
}
|
||||
@@ -91,9 +100,16 @@ fn make_map_args(file: &MediaFile, selector: &Selector) -> Result<Vec<String>> {
|
||||
])
|
||||
}
|
||||
|
||||
fn make_metadata_args(file: &MediaFile, selector: &Selector) -> Result<Vec<String>> {
|
||||
fn make_metadata_args(
|
||||
file: &MediaFile,
|
||||
selector: &Selector,
|
||||
index: &mut OutputIndex,
|
||||
) -> Result<Vec<String>> {
|
||||
let stream_type = selector.stream_type.as_ref();
|
||||
let Some(stream_index) = find_stream_index(file, selector) else {
|
||||
let stream_language = selector.language();
|
||||
|
||||
// Bail early if the stream is not selected
|
||||
let Some(_) = find_stream_index(file, selector) else {
|
||||
if selector.optional {
|
||||
return Ok(vec![]);
|
||||
} else {
|
||||
@@ -101,7 +117,13 @@ fn make_metadata_args(file: &MediaFile, selector: &Selector) -> Result<Vec<Strin
|
||||
}
|
||||
};
|
||||
|
||||
let stream_language = selector.language();
|
||||
let counter = match selector.stream_type {
|
||||
StreamType::Video => &mut index.video,
|
||||
StreamType::Audio => &mut index.audio,
|
||||
StreamType::Subtitle => &mut index.subtitle,
|
||||
};
|
||||
let stream_index = *counter;
|
||||
*counter = counter.saturating_add(1);
|
||||
|
||||
let mut args = vec![
|
||||
format!("-metadata:s:{}:{}", stream_type, stream_index),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-cli"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "CLI for interacting with a flix database"
|
||||
|
||||
@@ -50,10 +50,19 @@ pub async fn add(
|
||||
let fs_slug = overrides
|
||||
.fs_slug
|
||||
.unwrap_or_else(|| text::make_fs_slug(&title));
|
||||
let web_slug = overrides
|
||||
let mut web_slug = overrides
|
||||
.web_slug
|
||||
.unwrap_or_else(|| text::make_web_slug(&title));
|
||||
|
||||
const COLLECTION_SUFFIX_TO_REMOVE: &str = "-collection";
|
||||
if web_slug.ends_with(COLLECTION_SUFFIX_TO_REMOVE) {
|
||||
web_slug.truncate(
|
||||
web_slug
|
||||
.len()
|
||||
.saturating_sub(COLLECTION_SUFFIX_TO_REMOVE.len()),
|
||||
);
|
||||
}
|
||||
|
||||
let result: Result<CollectionId, TransactionError<DbErr>> = db
|
||||
.transaction(|txn| {
|
||||
let title = title.clone();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-db"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "Types for storing persistent data about media"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "Mechanisms for interacting with flix media"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-fs"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "Filesystem scanner for flix media"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-model"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "Core types for flix data"
|
||||
|
||||
@@ -15,6 +15,10 @@ fn split_normalized_words(input: &str) -> impl Iterator<Item = String> {
|
||||
input
|
||||
.split_ascii_whitespace()
|
||||
.map(|s| {
|
||||
if s == "&" {
|
||||
return "and".to_string();
|
||||
}
|
||||
|
||||
let chars = s
|
||||
.chars()
|
||||
.filter(|c| c.is_ascii_alphanumeric() || *c == '-')
|
||||
@@ -30,7 +34,7 @@ fn split_normalized_words(input: &str) -> impl Iterator<Item = String> {
|
||||
chars.collect()
|
||||
}
|
||||
})
|
||||
.filter(|part: &String| !part.is_empty())
|
||||
.filter(|part: &String| !part.is_empty() && part != "-")
|
||||
}
|
||||
|
||||
fn split_leading_article<I: Iterator<Item = String>>(iter: I) -> (Option<String>, Peekable<I>) {
|
||||
@@ -48,6 +52,7 @@ fn split_leading_article<I: Iterator<Item = String>>(iter: I) -> (Option<String>
|
||||
/// assert_eq!(make_sortable_title("The Matrix"), "matrix, the");
|
||||
/// assert_eq!(make_sortable_title("Marvel's Agents of S.H.I.E.L.D."), "marvels agents of shield");
|
||||
/// assert_eq!(make_sortable_title("Avatar: The Last Airbender"), "avatar the last airbender");
|
||||
/// assert_eq!(make_sortable_title("Cloak & Dagger"), "cloak and dagger");
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -71,6 +76,7 @@ pub fn make_sortable_title(title: &str) -> String {
|
||||
/// assert_eq!(make_fs_slug("The Matrix"), "matrix");
|
||||
/// assert_eq!(make_fs_slug("Marvel's Agents of S.H.I.E.L.D."), "marvels agents of shield");
|
||||
/// assert_eq!(make_fs_slug("Avatar: The Last Airbender"), "avatar the last airbender");
|
||||
/// assert_eq!(make_fs_slug("Cloak & Dagger"), "cloak and dagger");
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -89,6 +95,7 @@ pub fn make_fs_slug(title: &str) -> String {
|
||||
/// assert_eq!(make_fs_slug_year("The Matrix", 1999), "matrix (1999)");
|
||||
/// assert_eq!(make_fs_slug_year("Marvel's Agents of S.H.I.E.L.D.", 2013), "marvels agents of shield (2013)");
|
||||
/// assert_eq!(make_fs_slug_year("Avatar: The Last Airbender", 2005), "avatar the last airbender (2005)");
|
||||
/// assert_eq!(make_fs_slug_year("Cloak & Dagger", 2018), "cloak and dagger (2018)");
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -109,8 +116,13 @@ pub fn make_fs_slug_year(title: &str, year: i32) -> String {
|
||||
/// assert_eq!(normalize_fs_name("Matrix (1999)"), "matrix (1999)");
|
||||
/// assert_eq!(normalize_fs_name("Marvel's Agents of SHIELD (2013)"), "marvels agents of shield (2013)");
|
||||
/// assert_eq!(normalize_fs_name("Avatar The Last Airbender (2005)"), "avatar the last airbender (2005)");
|
||||
/// assert_eq!(normalize_fs_name("Cloak & Dagger (2018)"), "cloak and dagger (2018)");
|
||||
pub fn normalize_fs_name(input: &str) -> String {
|
||||
let chars = input.split_ascii_whitespace().map(|s| {
|
||||
if s == "&" {
|
||||
return "and".to_string();
|
||||
}
|
||||
|
||||
let chars = s
|
||||
.chars()
|
||||
.filter(|c| c.is_ascii_alphanumeric() || *c == '-' || *c == '(' || *c == ')')
|
||||
@@ -136,6 +148,7 @@ pub fn normalize_fs_name(input: &str) -> String {
|
||||
/// assert_eq!(make_web_slug("The Matrix"), "matrix");
|
||||
/// assert_eq!(make_web_slug("Marvel's Agents of S.H.I.E.L.D."), "marvels-agents-of-shield");
|
||||
/// assert_eq!(make_web_slug("Avatar: The Last Airbender"), "avatar-the-last-airbender");
|
||||
/// assert_eq!(make_web_slug("Cloak & Dagger"), "cloak-and-dagger");
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@@ -154,6 +167,7 @@ pub fn make_web_slug(title: &str) -> String {
|
||||
/// assert_eq!(make_web_slug_year("The Matrix", 1999), "matrix-1999");
|
||||
/// assert_eq!(make_web_slug_year("Marvel's Agents of S.H.I.E.L.D.", 2013), "marvels-agents-of-shield-2013");
|
||||
/// assert_eq!(make_web_slug_year("Avatar: The Last Airbender", 2005), "avatar-the-last-airbender-2005");
|
||||
/// assert_eq!(make_web_slug_year("Cloak & Dagger", 2018), "cloak-and-dagger-2018");
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flix-tmdb"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
license-file.workspace = true
|
||||
|
||||
description = "Clients and models for fetching data from TMDB"
|
||||
|
||||
Reference in New Issue
Block a user