Merge pull request #27 from Polochon-street/example-playlist-3

Polish the playlist example a bit more
This commit is contained in:
Polochon-street 2021-11-27 16:48:48 +01:00
commit a27b91c6fd
5 changed files with 107 additions and 25 deletions

View file

@ -1,5 +1,8 @@
# Changelog
## bliss 0.4.2
* Add a binary example to easily make playlists.
## bliss 0.4.1
* Add a function to make album playlists.

54
Cargo.lock generated
View file

@ -26,6 +26,15 @@ dependencies = [
"memchr 2.4.1",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "anyhow"
version = "1.0.45"
@ -77,10 +86,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bliss-audio"
version = "0.4.1"
version = "0.4.2"
dependencies = [
"anyhow",
"bliss-audio-aubio-rs",
"clap",
"crossbeam",
"env_logger",
"ffmpeg-next",
@ -236,6 +246,21 @@ dependencies = [
"libloading",
]
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -1111,6 +1136,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strum"
version = "0.21.0"
@ -1149,6 +1180,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.29"
@ -1235,6 +1275,12 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
@ -1253,6 +1299,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.3"

View file

@ -1,6 +1,6 @@
[package]
name = "bliss-audio"
version = "0.4.1"
version = "0.4.2"
authors = ["Polochon-street <polochonstreet@gmx.fr>"]
edition = "2018"
license = "GPL-3.0-only"
@ -50,3 +50,4 @@ mime_guess = "2.0.3"
glob = "0.3.0"
anyhow = "1.0.45"
serde_json = "1.0.59"
clap = "2.33.3"

View file

@ -23,10 +23,25 @@ different, more accurate values, based on
[actual literature](https://lelele.io/thesis.pdf). It is also faster.
## Examples
For simple analysis / distance computing, a look at `examples/distance.rs` and
For simple analysis / distance computing, take a look at `examples/distance.rs` and
`examples/analyse.rs`.
Ready to use examples:
If you simply want to try out making playlists from a folder containing songs,
[this example](https://github.com/Polochon-street/bliss-rs/blob/master/examples/playlist.rs)
contains all you need. Usage:
cargo run --features=serde --release --example=playlist /path/to/folder /path/to/first/song
Don't forget the `--release` flag!
By default, it outputs the playlist to stdout, but you can use `-o <path>`
to output it to a specific path.
To avoid having to analyze the entire folder
several times, it also stores the analysis in `/tmp/analysis.json`. You can customize
this behavior by using `-a <path>` to store this file in a specific place.
Ready to use code examples:
### Compute the distance between two songs
```
@ -72,7 +87,7 @@ fn main() -> Result<(), BlissError> {
Instead of reinventing ways to fetch a user library, play songs, etc,
and embed that into bliss, it is easier to look at the
[Library](https://github.com/Polochon-street/bliss-rs/blob/master/src/library.rs#L12)
[Library](https://docs.rs/bliss-audio/0.4.1/bliss_audio/library/trait.Library.html)
trait.
By implementing a few functions to get songs from a media library, and store

View file

@ -1,6 +1,7 @@
use anyhow::Result;
use bliss_audio::distance::{closest_to_first_song, dedup_playlist, euclidean_distance};
use bliss_audio::{library::analyze_paths_streaming, Song};
use clap::{App, Arg};
use glob::glob;
use mime_guess;
use serde_json;
@ -11,28 +12,34 @@ use std::path::{Path, PathBuf};
/* Analyzes a folder recursively, and make a playlist out of the file
* provided by the user. */
// TODO still:
// * Mention it in the README
// * Make the output file configurable
// * Allow to choose between outputing to stdout and a file
// How to use: ./playlist [-o file.m3u] [-a analysis.json] <folder> <file to start the playlist from>
#[cfg(feature = "serde")]
fn main() -> Result<()> {
let args: Vec<String> = env::args().skip(1).collect();
if args.len() > 3 || args.len() < 2 {
println!("Usage: ./playlist <folder> <file>");
println!(
"Creates a playlist of all audio files in a folder (recursively), \
starting with <file>, 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 matches = App::new("playlist")
.version(env!("CARGO_PKG_VERSION"))
.author("Polochon_street")
.about("Analyze a folder and make a playlist from a target song")
.arg(Arg::with_name("output-playlist").short("o").long("output-playlist")
.value_name("PLAYLIST.M3U")
.help("Outputs the playlist to a file.")
.takes_value(true))
.arg(Arg::with_name("analysis-file").short("a").long("analysis-file")
.value_name("ANALYSIS.JSON")
.help("Use the songs that have been analyzed in <analysis-file>, and appends newly analyzed songs to it. Defaults to /tmp/analysis.json.")
.takes_value(true))
.arg(Arg::with_name("FOLDER").help("Folders containing some songs.").required(true))
.arg(Arg::with_name("FIRST-SONG").help("Song to start from (can be outside of FOLDER).").required(true))
.get_matches();
let folder = matches.value_of("FOLDER").unwrap();
let file = fs::canonicalize(matches.value_of("FIRST-SONG").unwrap())?;
let pattern = Path::new(folder).join("**").join("*");
let mut songs: Vec<Song> = Vec::new();
let analysis_file = fs::File::open("./songs.json");
let analysis_path = matches
.value_of("analysis-file")
.unwrap_or("/tmp/analysis.json");
let analysis_file = fs::File::open(analysis_path);
if let Ok(f) = analysis_file {
let reader = BufReader::new(f);
songs = serde_json::from_reader(reader)?;
@ -75,14 +82,18 @@ fn main() -> Result<()> {
.collect();
closest_to_first_song(&first_song, &mut songs_to_chose_from, euclidean_distance);
dedup_playlist(&mut songs_to_chose_from, None);
fs::write("./songs.json", serialized)?;
fs::write(analysis_path, serialized)?;
let playlist = songs_to_chose_from
.iter()
.map(|s| s.path.to_string_lossy().to_string())
.collect::<Vec<String>>()
.join("\n");
println!("{}", playlist);
fs::write("./playlist.m3u", playlist)?;
if let Some(m) = matches.value_of("output-playlist") {
fs::write(m, playlist)?;
} else {
println!("{}", playlist);
}
Ok(())
}