diff --git a/README.md b/README.md index ade6340..b43baf2 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ sudo apt-get install \ cargo install --path . ``` -This will **dynamically** link against FFmpeg and statically link `chromaprint`. +This will **dynamically** link against FFmpeg. #### Dynamic @@ -223,7 +223,7 @@ brew install cmake pkg-config ffmpeg cargo install --path . ``` -This will **dynamically** link against FFmpeg. `chromaprint` will be statically linked. +This will **dynamically** link against FFmpeg. ### Windows @@ -242,7 +242,7 @@ cargo vcpkg build 3. Build: ```bash -# Statically link against both FFmpeg and chromaprint +# Statically link against FFmpeg. cargo build --release --features static ``` @@ -250,7 +250,7 @@ cargo build --release --features static 1. Set the following environment variables: - a. To dynamically link **both** FFmpeg and `chromaprint`: + a. To dynamically link FFmpeg: ```powershell # Powershell @@ -264,18 +264,6 @@ cargo build --release --features static export VCPKGRS_TRIPLET='x64-windows' ``` - b. Just `chromaprint`: - - ```powershell - # Powershell - $env:CHROMAPRINT_SYS_DYNAMIC='1' - ``` - - ```bash - # Git bash - export CHROMAPRINT_SYS_DYNAMIC=1 - ``` - 2. Build deps: ``` diff --git a/flake.nix b/flake.nix index 30d7872..8df4b78 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,7 @@ inherit pname; inherit version; src = ./needle; - cargoSha256 = "sha256-aUKzSbyniuk2+UZmrUZjMv+yhcjn+eilnZtCMxzJLZo="; + cargoSha256 = "sha256-CUcjt7BLvTSaiiYCuzVilEf0y1zN08Bo8YtvKFVTSiM="; # nativeBuildInputs: used only in build phase nativeBuildInputs = [ pkgs.cmake @@ -30,7 +30,6 @@ # buildInputs: used only at runtime (i.e., linked against) # https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-dependencies-overview buildInputs = [ - pkgs.chromaprint pkgs.ffmpeg-full ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.fftw @@ -58,7 +57,6 @@ in { default = pkgs.mkShell { buildInputs = [ - pkgs.chromaprint pkgs.ffmpeg-full pkgs.libiconv # required by rust-ffmpeg build script pkgs.pkg-config diff --git a/needle/Cargo.lock b/needle/Cargo.lock index 273a298..36ace98 100644 --- a/needle/Cargo.lock +++ b/needle/Cargo.lock @@ -61,29 +61,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.60.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "clap", - "env_logger", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "which", -] - [[package]] name = "bindgen" version = "0.69.4" @@ -143,31 +120,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chromaprint-rust" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1d9bca6efb59acb6a08aa386e252dda3c6541ef18d277841b48d9133cbc934" -dependencies = [ - "chromaprint-sys-next", - "num-traits", - "thiserror", -] - -[[package]] -name = "chromaprint-sys-next" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74158b525ca4b9517023d890458b18f3ad9924c341190aba0c07d9a8f819ce2a" -dependencies = [ - "bindgen 0.60.1", - "cfg-if", - "cmake", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "chrono" version = "0.4.38" @@ -230,15 +182,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "console" version = "0.15.8" @@ -294,29 +237,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - [[package]] name = "ffmpeg-next" version = "7.0.2" @@ -334,7 +254,7 @@ version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "972a460dd8e901b737ce0482bf71a837e1751e3dd7c8f8b0a4ead808e7f174a5" dependencies = [ - "bindgen 0.69.4", + "bindgen", "cc", "libc", "num_cpus", @@ -375,21 +295,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "iana-time-zone" version = "0.1.60" @@ -499,12 +404,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "log" version = "0.4.22" @@ -543,13 +442,14 @@ name = "needle-rs" version = "0.1.5" dependencies = [ "bincode", - "chromaprint-rust", "clap", "ffmpeg-next", "infer", "insta", "md5", + "num-traits", "rayon", + "rusty-chromaprint", "serde", "serde_json", "thiserror", @@ -568,6 +468,24 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -599,12 +517,6 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -617,6 +529,15 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "primal-check" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" +dependencies = [ + "num-integer", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -679,6 +600,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "realfft" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953d9f7e5cdd80963547b456251296efc2626ed4e3cbf36c869d9564e0220571" +dependencies = [ + "rustfft", +] + [[package]] name = "regex" version = "1.10.5" @@ -723,6 +653,18 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "rubato" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "realfft", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -730,16 +672,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustix" -version = "0.38.34" +name = "rustfft" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", + "version_check", +] + +[[package]] +name = "rusty-chromaprint" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1755646867c36ecb391776deaa0b557a76d3badf20c142de7282630c34b20440" +dependencies = [ + "rubato", + "rustfft", ] [[package]] @@ -806,6 +760,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + [[package]] name = "strsim" version = "0.10.0" @@ -954,6 +914,16 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -1032,18 +1002,6 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/needle/Cargo.toml b/needle/Cargo.toml index acf8a33..a850ee0 100644 --- a/needle/Cargo.toml +++ b/needle/Cargo.toml @@ -33,7 +33,6 @@ thiserror = "1" tracing = "0.1.34" tracing-subscriber = "0.2" ffmpeg-next = { version = "7.0.2", default-features = false, features = ["codec", "format", "software-resampling"] } -chromaprint-rust = "0.1" clap = { version = "3", features = ["derive"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } @@ -41,16 +40,17 @@ serde_json = "1" rayon = { version = "1", optional = true } infer = { version = "0.8", default-features = false } md5 = "0.7" +rusty-chromaprint = "0.2.0" +num-traits = "0.2.19" [dev-dependencies] insta = "1" [features] -default = ["rayon", "static-chromaprint"] -static-chromaprint = ["chromaprint-rust/static"] +default = ["rayon"] static-ffmpeg = ["ffmpeg-next/static"] static-ffmpeg-build = ["ffmpeg-next/build"] -static = ["static-chromaprint", "static-ffmpeg"] +static = ["static-ffmpeg"] [target.'cfg(windows)'.build-dependencies] vcpkg = "0.2" diff --git a/needle/src/audio/analyzer.rs b/needle/src/audio/analyzer.rs index 4ffce02..863282d 100644 --- a/needle/src/audio/analyzer.rs +++ b/needle/src/audio/analyzer.rs @@ -1,9 +1,7 @@ -extern crate chromaprint_rust; extern crate ffmpeg_next; #[cfg(feature = "rayon")] extern crate rayon; - -use chromaprint_rust as chromaprint; +extern crate rusty_chromaprint; use std::path::Path; use std::time::Duration; @@ -11,6 +9,8 @@ use std::time::Duration; #[cfg(feature = "rayon")] use rayon::prelude::*; +use rusty_chromaprint::{Configuration, Fingerprinter}; + use super::FrameHashes; use crate::{Error, Result}; @@ -173,10 +173,11 @@ impl> Analyzer

{ let mut frame_resampled = ffmpeg_next::frame::Audio::empty(); // Setup the audio fingerprinter - let mut chromaprint_ctx = chromaprint::Context::default(); + let config = &Configuration::preset_test2(); + let target_sample_rate = config.sample_rate(); + let mut chromaprint_ctx = Fingerprinter::new(config); // Setup the audio resampler - let target_sample_rate = chromaprint_ctx.sample_rate(); let mut resampler = decoder .decoder .resampler( @@ -215,7 +216,8 @@ impl> Analyzer

{ } }); - chromaprint_ctx.start(target_sample_rate, 2)?; + // TODO(aksiksi): Export ResetError from rusty-chromaprint. + chromaprint_ctx.start(target_sample_rate, 2).expect("failed to start fingerprinter"); for p in audio_packets { if p.pts().unwrap() <= 0 { @@ -272,7 +274,7 @@ impl> Analyzer

{ // Feed the i16 samples to Chromaprint. Since we are using the default sampling rate, // Chromaprint will _not_ do any resampling internally. - chromaprint_ctx.feed(samples)?; + chromaprint_ctx.consume(samples); if delay.is_none() { break; @@ -283,10 +285,10 @@ impl> Analyzer

{ } } - chromaprint_ctx.finish()?; + chromaprint_ctx.finish(); - let chromaprint_hash_delay = chromaprint_ctx.get_delay()?; - let item_duration = chromaprint_ctx.get_item_duration()?; + let chromaprint_hash_delay = Duration::ZERO; + let item_duration = Duration::from_secs_f32(config.item_duration_in_seconds()); // We can use the given hash duration and Chromaprint's item duration to // figure out how many hashes we can skip. @@ -297,8 +299,7 @@ impl> Analyzer

{ }; for (i, hash) in chromaprint_ctx - .get_fingerprint_raw()? - .get() + .fingerprint() .iter() .enumerate() .step_by(step_by) diff --git a/needle/src/audio/comparator.rs b/needle/src/audio/comparator.rs index e89889a..f7446fa 100644 --- a/needle/src/audio/comparator.rs +++ b/needle/src/audio/comparator.rs @@ -1,4 +1,3 @@ -extern crate chromaprint_rust; #[cfg(feature = "rayon")] extern crate rayon; @@ -7,7 +6,6 @@ use std::fmt::Display; use std::path::Path; use std::time::Duration; -use chromaprint_rust as chromaprint; #[cfg(feature = "rayon")] use rayon::prelude::*; @@ -149,7 +147,7 @@ impl> Comparator

{ #[inline] fn compute_hash_for_match(hashes: &[(u32, Duration)], (start, end): (usize, usize)) -> u32 { let hashes: Vec = hashes.iter().map(|t| t.0).collect(); - chromaprint::simhash::simhash32(&hashes[start..end + 1]) + crate::simhash::simhash32(&hashes[start..end + 1]) } /// Runs a LCS (longest common substring) search between the two sets of hashes. This runs in diff --git a/needle/src/lib.rs b/needle/src/lib.rs index a89c1af..dbb623a 100644 --- a/needle/src/lib.rs +++ b/needle/src/lib.rs @@ -143,9 +143,6 @@ pub enum Error { /// Wraps [std::io::Error]. #[error("IO error: {0}")] IOError(#[from] std::io::Error), - /// Wraps [chromaprint_rust::Error]. - #[error("Chromaprint error: {0}")] - ChromaprintError(#[from] chromaprint_rust::Error), } /// Common result type.