From fac5579a667cde1b9d5339ea705315dd960149b9 Mon Sep 17 00:00:00 2001 From: Polochon-street Date: Wed, 3 Nov 2021 19:57:16 +0100 Subject: [PATCH] Add binary example to make playlist from a folder --- Cargo.lock | 32 +++++++++++++++++++++++-- Cargo.toml | 5 ++++ examples/playlist.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 examples/playlist.rs diff --git a/Cargo.lock b/Cargo.lock index e924850..a44442a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7" [[package]] name = "atty" @@ -79,12 +79,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" name = "bliss-audio" version = "0.4.1" dependencies = [ + "anyhow", "bliss-audio-aubio-rs", "crossbeam", "env_logger", "ffmpeg-next", + "glob", "lazy_static 1.4.0", "log", + "mime_guess", "ndarray", "ndarray-npy", "ndarray-stats", @@ -616,6 +619,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1177,6 +1196,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-segmentation" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index d453f1c..2756b43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,3 +44,8 @@ bliss-audio-aubio-rs = "0.2.0" strum = "0.21" strum_macros = "0.21" serde = { version = "1.0", optional = true, features = ["derive"] } + +[dev-dependencies] +mime_guess = "2.0.3" +glob = "0.3.0" +anyhow = "1.0.45" diff --git a/examples/playlist.rs b/examples/playlist.rs new file mode 100644 index 0000000..cc279f1 --- /dev/null +++ b/examples/playlist.rs @@ -0,0 +1,57 @@ +use anyhow::Result; +use bliss_audio::distance::{closest_to_first_song, dedup_playlist, euclidean_distance}; +use bliss_audio::{library::analyze_paths_streaming, Song}; +use glob::glob; +use mime_guess; +use std::env; +use std::fs; +use std::path::Path; + +/* Analyzes a folder recursively, and make a playlist out of the file + * provided by the user. */ +// TODO still: +// * Save the results somewhere to avoid analyzing stuff over and over +// * Make the output file configurable +// * Allow to choose between outputing to stdout and a file +fn main() -> Result<()> { + let args: Vec = env::args().skip(1).collect(); + if args.len() > 3 || args.len() < 2 { + println!("Usage: ./playlist "); + println!( + "Creates a playlist of all audio files in a folder (recursively), \ + starting with , and outputs the result both to stdout and \ + a `playlist.m3u` file in the current folder." + ); + return Ok(()); + } + let folder = &args[0]; + let file = fs::canonicalize(&args[1])?; + let pattern = Path::new(folder).join("**").join("*"); + let songs = glob(&pattern.to_string_lossy())? + .map(|e| fs::canonicalize(e.unwrap()).unwrap()) + .filter(|e| match mime_guess::from_path(e).first() { + Some(m) => m.type_() == "audio", + None => false, + }) + .map(|x| x.to_string_lossy().to_string()) + .collect::>(); + let rx = analyze_paths_streaming(songs)?; + let first_song = Song::new(file)?; + let mut analyzed_songs = vec![first_song.to_owned()]; + for (path, result) in rx.iter() { + match result { + Ok(song) => analyzed_songs.push(song), + Err(e) => println!("error analyzing {}: {}", path, e), + }; + } + closest_to_first_song(&first_song, &mut analyzed_songs, euclidean_distance); + dedup_playlist(&mut analyzed_songs, None); + let playlist = analyzed_songs + .iter() + .map(|s| s.path.to_string_lossy().to_string()) + .collect::>() + .join("\n"); + println!("{}", playlist); + fs::write("./playlist.m3u", playlist)?; + Ok(()) +}