Add real media-file probing (session 9, sixteenth delivery)
Wires real container-header probing into the Rename panel's Match step, the
first item on the porting roadmap: aurora-curator-core::probe reads actual
resolution, frame rate, duration, and video/audio codecs straight from a
file's own header (mp4 crate for MP4/M4V/MOV, matroska crate for MKV/WebM,
no ffmpeg/MediaInfo dependency), batched through a new probe_media_files
Tauri command. Probed values fill {resolution}/{video codec}/{audio codec}
only when a filename release tag hasn't already, and populate five bindings
with no filename-tag equivalent at all: {width}, {height}, {fps},
{duration}, {file size}. 8 new Rust unit tests against real ffmpeg-generated
fixture files (161 -> 169 total), verified end to end with a 15-check
Playwright script against npm run dev, and README updated (status
paragraph, project layout, a new "Real media-file probing" section, and
roadmap item 1 narrowed to what's still missing).
This commit is contained in:
@@ -5,6 +5,7 @@ mod history;
|
||||
mod list;
|
||||
mod metadata;
|
||||
mod presets;
|
||||
mod probe;
|
||||
mod settings;
|
||||
mod sfv;
|
||||
mod subtitles;
|
||||
@@ -47,11 +48,13 @@ fn guess_movie(filename: String) -> Option<MovieGuess> {
|
||||
|
||||
/// Guesses release-tag metadata (resolution, source, video/audio codec, release
|
||||
/// group) from a filename's own text using local regex patterns only - no network
|
||||
/// calls, no real media probing (Aurora Curator never ships an ffprobe/MediaInfo dependency,
|
||||
/// so filename tags are the only source for these fields). Independent of
|
||||
/// `guess_episode`/`guess_movie`: called alongside whichever of those two applies,
|
||||
/// since a release name carries (or doesn't carry) these tags regardless of whether
|
||||
/// it's an episode or a movie.
|
||||
/// calls, no file I/O. Complements `probe::probe_media_files` below, which reads the
|
||||
/// same kind of resolution/codec data straight from a file's real container header
|
||||
/// instead of guessing it from filename text - the Rename panel merges both,
|
||||
/// preferring an explicit filename tag over a probed value when a file has both.
|
||||
/// Independent of `guess_episode`/`guess_movie`: called alongside whichever of those
|
||||
/// two applies, since a release name carries (or doesn't carry) these tags regardless
|
||||
/// of whether it's an episode or a movie.
|
||||
#[tauri::command]
|
||||
fn guess_release_info(filename: String) -> Option<ReleaseInfo> {
|
||||
matching::guess_release_info(&filename)
|
||||
@@ -123,6 +126,7 @@ pub fn run() {
|
||||
sfv::save_checksum_file,
|
||||
sfv::verify_checksum_file,
|
||||
list::export_text_list,
|
||||
probe::probe_media_files,
|
||||
history::list_rename_history,
|
||||
history::undo_rename_batch,
|
||||
presets::list_presets,
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//! The Tauri-facing side of real media-file probing: reads real container metadata
|
||||
//! (resolution, duration, frame rate, codecs) straight from each loaded file's own
|
||||
//! header via `aurora_curator_core::probe`, batched the same way `sfv::compute_checksums`
|
||||
//! batches checksum hashing - one Tauri round trip for the whole loaded set, run off
|
||||
//! the main thread since this is real file I/O (a probe only reads a container's
|
||||
//! header/index boxes, not the whole file, but a movie file can still be tens of GB
|
||||
//! and may live on a slow network share).
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use aurora_curator_core::probe::{self, MediaProbe};
|
||||
use serde::Serialize;
|
||||
|
||||
/// One file's probe result, paired with the path it came from so the frontend can
|
||||
/// match results back to the loaded items it requested (order isn't otherwise
|
||||
/// guaranteed to be preserved end to end through `spawn_blocking`).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProbeOutcome {
|
||||
pub path: String,
|
||||
pub probe: MediaProbe,
|
||||
}
|
||||
|
||||
/// Probes a batch of loaded files. Never fails per-file - `aurora_curator_core::probe::probe_media_file`
|
||||
/// is always best-effort (see its doc comment), so every path in `paths` gets exactly
|
||||
/// one `ProbeOutcome` back, even a file that isn't a supported container or can't be
|
||||
/// read at all (its `MediaProbe` just comes back mostly empty).
|
||||
#[tauri::command]
|
||||
pub async fn probe_media_files(paths: Vec<String>) -> Vec<ProbeOutcome> {
|
||||
tauri::async_runtime::spawn_blocking(move || {
|
||||
paths
|
||||
.into_iter()
|
||||
.map(|path| {
|
||||
let probe = probe::probe_media_file(Path::new(&path));
|
||||
ProbeOutcome { path, probe }
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
}
|
||||
Reference in New Issue
Block a user