Compare commits

..

1 Commits

Author SHA1 Message Date
Connor Johnstone 8ddd3bd64b speedup on tagging 2026-03-24 21:32:25 -04:00
2 changed files with 20 additions and 26 deletions
+3 -1
View File
@@ -31,7 +31,9 @@ pub fn write_tags(
) -> TagResult<()> {
let path = Path::new(file_path);
let tagged_file = Probe::open(path)?.options(ParseOptions::default()).read()?;
let tagged_file = Probe::open(path)?
.options(ParseOptions::new().read_properties(false))
.read()?;
// Determine the tag type to use
let tag_type = tagged_file
+17 -25
View File
@@ -1,27 +1,18 @@
use std::fmt;
use sea_orm::{ActiveValue::Set, DatabaseConnection, NotSet};
use sea_orm::{ActiveValue::NotSet, ActiveValue::Set, DatabaseConnection};
use shanty_data::MetadataFetcher as MetadataProvider;
use shanty_db::entities::track;
use shanty_db::queries;
use crate::error::TagResult;
use crate::file_tags;
use crate::matcher::{self, ScoredMatch};
use shanty_data::MetadataFetcher as MetadataProvider;
/// Configuration for a tagging operation.
pub struct TagConfig {
/// If true, show what would change without writing to DB or files.
pub dry_run: bool,
/// If true, write updated tags back to the music files.
pub write_tags: bool,
/// Minimum match confidence (0.0 - 1.0).
pub confidence: f64,
}
/// Statistics from a completed tagging run.
#[derive(Debug, Default, Clone)]
pub struct TagStats {
pub tracks_processed: u64,
pub tracks_matched: u64,
@@ -30,8 +21,8 @@ pub struct TagStats {
pub tracks_errored: u64,
}
impl fmt::Display for TagStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl std::fmt::Display for TagStats {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"processed: {}, matched: {}, updated: {}, skipped: {}, errors: {}",
@@ -198,30 +189,33 @@ fn log_match(track: &track::Model, best: &ScoredMatch) {
confidence = format!("{:.2}", best.confidence),
matched_title = %best.recording.title,
matched_artist = %best.recording.artist,
release = best.best_release.as_ref().map(|r| r.title.as_str()).unwrap_or("(none)"),
"match found"
"matched"
);
}
/// Run tagging on all untagged tracks or a specific track.
/// Run tagging on a single track (by ID) or all tracks needing metadata.
pub async fn run_tagging(
conn: &DatabaseConnection,
provider: &impl MetadataProvider,
config: &TagConfig,
track_id: Option<i32>,
) -> TagResult<TagStats> {
let tracks: Vec<track::Model> = if let Some(id) = track_id {
let mut stats = TagStats {
tracks_processed: 0,
tracks_matched: 0,
tracks_updated: 0,
tracks_skipped: 0,
tracks_errored: 0,
};
let tracks = if let Some(id) = track_id {
vec![queries::tracks::get_by_id(conn, id).await?]
} else {
queries::tracks::get_needing_metadata(conn).await?
};
tracing::info!(count = tracks.len(), "tracks to process");
let mut stats = TagStats::default();
for track in &tracks {
stats.tracks_processed += 1;
match tag_track(conn, provider, track, config).await {
Ok(true) => {
stats.tracks_matched += 1;
@@ -229,11 +223,9 @@ pub async fn run_tagging(
stats.tracks_updated += 1;
}
}
Ok(false) => {
stats.tracks_skipped += 1;
}
Ok(false) => stats.tracks_skipped += 1,
Err(e) => {
tracing::error!(id = track.id, path = %track.file_path, "tagging error: {e}");
tracing::error!(id = track.id, error = %e, "tagging failed");
stats.tracks_errored += 1;
}
}