A song analysis library for making playlists
Go to file
2024-02-16 17:57:14 +02:00
data Cleanup repo from audio data 2023-12-28 13:58:26 +01:00
examples Merge branch 'master' into github-mirror-master 2024-02-16 17:57:14 +02:00
src Merge branch 'master' into github-mirror-master 2024-02-16 17:57:14 +02:00
.gitignore Merge branch 'master' into github-mirror-master 2024-02-16 17:57:14 +02:00
.gitmodules Vendor aubio-rs pt.2 2021-05-16 14:47:42 +02:00
build.rs Bump ffmpeg to 6.0 2023-03-16 20:50:39 +01:00
Cargo.lock Merge branch 'master' into github-mirror-master 2024-02-16 17:57:14 +02:00
Cargo.toml Merge branch 'master' into github-mirror-master 2024-02-16 17:57:14 +02:00
CHANGELOG.md Bump rust-ffmpeg to hopefully support rpis. 2024-01-03 21:40:33 +01:00
ci_check.sh Add a local CI check script 2023-12-27 23:30:40 +01:00
Dockerfile Update Dockerfile 2023-12-29 11:15:31 +02:00
index.d.ts Revert "Fix type definitions, bump version" 2023-12-28 12:23:55 +02:00
index.js Fix: remove the export statement 2023-12-28 01:03:16 +02:00
LICENSE Add license 2023-03-23 22:06:17 +01:00
package-lock.json Abandon the automation idea, prepare the package for publishing with prebuilt binaries 2023-12-28 00:46:05 +02:00
package.json Recompile the package for lower GLIBC version 2023-12-29 11:46:14 +02:00
README.md Return the version in little endian 2023-12-28 17:47:35 +02:00

crate build doc

Fork notice

This repo is a fork of bliss-rs with bindings for Node.js (using N-API and Neon).

Example usage:

The package is published to the Gitea registry: https://gitea.antonlyap.pp.ua/antonlyap/-/packages/npm/@bliss-rs%2Fbliss-rs/1.0.0

import { analyze, analyzeSync } from '@bliss-rs/bliss-rs';

await analyze("/path/to/track.mp3") // returns Uint8Array

Return value

The output of bliss-rs consists of single-precision floats, currently 20 of them. This fork contains code to convert it into an array of 80 bytes in little endian order. An additional version (also comes from bliss-rs, currently equal to 1) is prepended at the start (16-bit unsigned little-endian integer). Therefore, the total output size is 82 bytes.

Usage

The output (without the version) is meant to be converted back into floats and used to calculate the Euclidean distance between two songs. Other distance algorithms are being worked on by the Bliss team.


(Original README) bliss music analyzer - Rust version

bliss-rs is the Rust improvement of bliss, a library used to make playlists by analyzing songs, and computing distance between them.

Like bliss, it eases the creation of « intelligent » playlists and/or continuous play, à la Spotify/Grooveshark Radio, as well as easing creating plug-ins for existing audio players. For instance, you can use it to make calm playlists to help you sleeping, fast playlists to get you started during the day, etc.

For now (and if you're looking for an easy-to use smooth play experience), blissify implements bliss for MPD.

There are also python bindings. The wheels are compiled used maturin; the sources are available here for inspiration.

Note 1: the features bliss-rs outputs is not compatible with the ones used by C-bliss, since it uses different, more accurate values, based on actual literature. It is also faster.

Examples

For simple analysis / distance computing, take a look at examples/distance.rs and examples/analyze.rs.

If you simply want to try out making playlists from a folder containing songs, this example 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

use bliss_audio::{BlissError, Song};

fn main() -> Result<(), BlissError> {
    let song1 = Song::from_path("/path/to/song1")?;
    let song2 = Song::from_path("/path/to/song2")?;
        
    println!("Distance between song1 and song2 is {}", song1.distance(&song2));
    Ok(())
}

Make a playlist from a song

use bliss_audio::{BlissError, Song};
use noisy_float::prelude::n32;

fn main() -> Result<(), BlissError> {
    let paths = vec!["/path/to/song1", "/path/to/song2", "/path/to/song3"];
    let mut songs: Vec<Song> = paths
        .iter()
        .map(|path| Song::from_path(path))
        .collect::<Result<Vec<Song>, BlissError>>()?;

    // Assuming there is a first song
    let first_song = songs.first().unwrap().to_owned();

    songs.sort_by_cached_key(|song| n32(first_song.distance(&song)));
    println!(
        "Playlist is: {:?}",
        songs
            .iter()
            .map(|song| &song.path)
            .collect::<Vec<&String>>()
    );
    Ok(())
}

Further use

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 module. It implements common analysis functions, and allows analyzed songs to be put in a sqlite database seamlessly.

See blissify for a reference implementation.

Cross-compilation

To cross-compile bliss-rs from linux to x86_64 windows, install the x86_64-pc-windows-gnu target via:

    rustup target add x86_64-pc-windows-gnu

Make sure you have x86_64-w64-mingw32-gcc installed on your computer.

Then after downloading and extracting ffmpeg's prebuilt binaries, running:

    FFMPEG_DIR=/path/to/prebuilt/ffmpeg cargo build --target x86_64-pc-windows-gnu --release

Will produce a .rlib library file. If you want to generate a shared .dll library, add:

    [lib]
    crate-type = ["cdylib"]

to Cargo.toml before compiling, and if you want to generate a .lib static library, add:

    [lib]
    crate-type = ["staticlib"]

You can of course test the examples yourself by compiling them as .exe:

    FFMPEG_DIR=/path/to/prebuilt/ffmpeg cargo build --target x86_64-pc-windows-gnu --release --examples

WARNING: Doing all of the above and making it work on windows requires to have ffmpeg's dll on your Windows %PATH% (avcodec-59.dll, etc). Usually installing ffmpeg on the target windows is enough, but you can also just extract them from /path/to/prebuilt/ffmpeg/bin and put them next to the thing you generated from cargo (either bliss' dll or executable).

Acknowledgements

  • This library relies heavily on aubio's Rust bindings for the spectral / timbral analysis, so a big thanks to both the creators and contributors of librosa, and to @katyo for making aubio bindings for Rust.
  • The first part of the chroma extraction is basically a rewrite of librosa's chroma feature extraction from python to Rust, with just as little features as needed. Thanks to both creators and contributors as well.
  • Finally, a big thanks to Christof Weiss for pointing me in the right direction for the chroma feature summarization, which are basically also a rewrite from Python to Rust of some of the awesome notebooks by AudioLabs Erlangen, that you can find here.