diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dddb3ef..fbbe2d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -115,6 +115,33 @@ jobs: path: releases/ + Linux_symphonia_x86: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Packages + run: sudo apt-get update && sudo apt-get install build-essential yasm -y + + - name: Build x86 static-libav version + run: | + cargo build --release --features=symphonia + strip target/release/bliss-analyser + mkdir releases + cp target/release/bliss-analyser releases/bliss-analyser + cp UserGuide.md releases/README.md + cp LICENSE releases/ + cp configs/linux.ini releases/config.ini + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: bliss-analyser-linux-x86-symphonia + path: releases/ + + Linux_ffmpeg_arm: runs-on: ubuntu-22.04 @@ -183,6 +210,25 @@ jobs: path: releases/ + Linux_symphonia_arm: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build ARM symphonia on Debian + run: | + docker build -t bliss-analyser-cross - < docker/Dockerfile_Bullseye_symphonia + docker run --rm -v $PWD/target:/build -v $PWD:/src bliss-analyser-cross + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: bliss-analyser-linux-arm-symphonia + path: releases/ + + macOS_ffmpeg: runs-on: macos-13 @@ -308,6 +354,54 @@ jobs: # path: releases/ + macOS_symphonia: + runs-on: macos-13 + + steps: + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Checkout + uses: actions/checkout@v2 + + - name: Install deps + run: | + brew install pkg-config + + - name: Install Rust support for ARM64 & prepare environment + run: | + rustup target add aarch64-apple-darwin + mkdir releases + + - name: Build + run: | + cargo build --release --features update-aubio-bindings,symphonia + strip target/release/bliss-analyser + cp target/release/bliss-analyser releases/bliss-analyser-x86_64 + cargo build --target=aarch64-apple-darwin --release --features update-aubio-bindings,symphonia + strip target/aarch64-apple-darwin/release/bliss-analyser + cp target/aarch64-apple-darwin/release/bliss-analyser releases/bliss-analyser-arm64 + + - name: Build fat binary + run: | + lipo -create \ + -arch x86_64 releases/bliss-analyser-x86_64 \ + -arch arm64 releases/bliss-analyser-arm64 \ + -output releases/bliss-analyser + + - name: Remove unused binaries + run: + rm releases/bliss-analyser-x86_64 releases/bliss-analyser-arm64 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: bliss-analyser-mac-symphonia + path: releases/ + + Windows_libav: runs-on: windows-2019 @@ -349,3 +443,34 @@ jobs: with: name: bliss-analyser-windows-libav path: releases/ + + + Windows_symphonia: + runs-on: windows-2019 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Build + run: | + cargo build --release --features=symphonia + mkdir releases + cp target/release/bliss-analyser.exe releases/bliss-analyser.exe + cp UserGuide.md releases/README.md + cp LICENSE releases/ + cp configs/windows.ini releases/config.ini + cp c:\Windows\system32\vcruntime140.dll releases + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: bliss-analyser-windows-symphonia + path: releases/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e7ad179..d47b299 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,21 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.97" @@ -65,6 +80,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "atty" version = "0.2.14" @@ -153,7 +174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.5.2", "constant_time_eq", ] @@ -185,8 +206,7 @@ dependencies = [ [[package]] name = "bliss-audio" version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af3dbc2bc1dd8b43a93d10b1f4752f283c06451f9d3a6e1433fb6bf1c9afc53" +source = "git+https://github.com/Polochon-street/bliss-rs.git#006927ac16752ff2e00bfe0d6b7756f67fa822c0" dependencies = [ "adler32", "bliss-audio-aubio-rs", @@ -198,9 +218,11 @@ dependencies = [ "ndarray-stats", "noisy_float", "rcue", + "rubato", "rustfft", "strum", "strum_macros", + "symphonia", "thiserror", ] @@ -229,6 +251,12 @@ version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "bytemuck" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" + [[package]] name = "byteorder" version = "1.5.0" @@ -262,15 +290,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ - "libc", - "num-integer", + "android-tzdata", + "iana-time-zone", + "js-sys", "num-traits", - "time 0.1.44", - "winapi", + "wasm-bindgen", + "windows-link", ] [[package]] @@ -321,6 +350,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "crc32fast" version = "1.3.2" @@ -409,6 +444,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_home" version = "0.1.0" @@ -438,6 +482,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "extended-isolation-forest" version = "0.2.3" @@ -587,7 +637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a3a7d0916cb01ef108a66108640419767991ea31d11a1c851bed37686a6062" dependencies = [ "chrono", - "time 0.2.27", + "time", ] [[package]] @@ -605,6 +655,29 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.2.3" @@ -670,10 +743,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.56" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -864,11 +938,10 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] @@ -1053,6 +1126,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fca1481d62f18158646de2ec552dd63f8bdc5be6448389b192ba95c939df997e" +[[package]] +name = "realfft" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953d9f7e5cdd80963547b456251296efc2626ed4e3cbf36c869d9564e0220571" +dependencies = [ + "rustfft", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -1102,6 +1184,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "rubato" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd96992d7e24b3d7f35fdfe02af037a356ac90d41b466945cf3333525a86eea" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "realfft", +] + [[package]] name = "rusqlite" version = "0.28.0" @@ -1382,6 +1476,176 @@ dependencies = [ "autocfg", ] +[[package]] +name = "symphonia" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" +dependencies = [ + "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-alac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-ogg", + "symphonia-format-riff", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-aac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-adpcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-alac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" +dependencies = [ + "arrayvec 0.7.6", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", + "rustfft", +] + +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-riff" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.99" @@ -1443,17 +1707,6 @@ dependencies = [ "syn 2.0.99", ] -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.2.27" @@ -1525,9 +1778,9 @@ checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" @@ -1599,34 +1852,35 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.79" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", - "lazy_static", "log", "proc-macro2", "quote", - "syn 1.0.99", + "syn 2.0.99", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1634,22 +1888,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 1.0.99", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" @@ -1735,6 +1992,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index c74dabe..0449021 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ env_logger = "0.8.4" indicatif = "0.16.2" lofty = "0.22.2" dirs = "1" -chrono = "0.4.19" +chrono = "0.4.40" regex = "1" substring = "1.4.5" ureq = "2.4.0" @@ -30,13 +30,14 @@ rcue = { version = "0.1.3", optional = true } hhmmss = { version = "0.1.0", optional = true } [features] -default = ["libav"] libav = ["bliss-audio/ffmpeg"] update-aubio-bindings = ["bliss-audio/update-aubio-bindings"] staticlibav = ["bliss-audio/build-ffmpeg", "bliss-audio/ffmpeg-static"] ffmpeg = ["dep:which", "dep:rcue", "dep:hhmmss"] +symphonia = ["bliss-audio/symphonia-all", "bliss-audio/symphonia-aiff", "bliss-audio/symphonia-alac"] [dependencies.bliss-audio] default-features = false features = ["aubio-static"] -version = "0.9.4" +# version = "0.9.4" +git = "https://github.com/Polochon-street/bliss-rs.git" diff --git a/ChangeLog b/ChangeLog index 2df7f33..9aa0626 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,10 +3,8 @@ 1. Add support for (DSD) WavPack - thanks to Bart Lauret 2. Update version of tag reader library. 3. Update version of bliss library. -4. Use 'ffmpeg' commandline to decode files, and not ffmpeg libraries by - default. Pass '--features=libav' to cargo to build against ffmpeg - libraries. Pass '--features=libav,libavstatic' to cargo to build against - ffmpeg libraries, and statically link these in. +4. Allow builds to either use dynamic ffmpeg libraries, static ffmpeg + libraries, symphonia, or ffmpeg on commandline. 5. Add ability to specify LMS JSONRPC port. 6. If new files analysed and 'ignore' file exists then update DB's 'ignore' flags. diff --git a/README.md b/README.md index 3f366a1..ebff703 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,26 @@ bliss analysis. This is then intended to be used by [Bliss Mixer](https://github # Building -This application can be built in 3 variants: +This application can be built in 4 variants: -1. Using command-line `ffmpeg` to decode files -2. Using `libavcodec`, etc, to decode files +1. Using command-line `ffmpeg` to decode files. +2. Using `libavcodec`, etc, to decode files. 3. Using `libavcodec`, etc, to decode files, but statically linked to `libavcodec`, etc. +24. Using `symphonia` to decode files. -Using `libavcodec` is about 70% faster, but might have issues with library, versioning, etc. -Using `libavcodec` statically linked my reduce supported file formats. -Using `ffmpeg` whilst slower produces a more portable application. +`libavcodec` is the fastest (about 70% faster than `ffmpeg` commandline, and about +3 times faster than `symphonia`), but might have issues with library, versioning, etc., +unless these libraries are statically linked in. + +`libavcodec` statically linked may reduce supported file formats. + +`ffmpeg` whilst slower then `libavcodec` produces a more portable application. + +`symphonia` also produced a more ortable application, but is *much* slower to decode +files, and does not produce identical analysis results. Therefore, it is not advisable +to mix files nalysed with `ffmpeg` (any varaint) and `sympnonia`. + ## Build for 'ffmpeg' command-line usage @@ -80,6 +90,25 @@ dnf install ffmpeg-devel clang pkg-config Build with `cargo build --release --features=libav,libavstatic` +## Build for 'symphonia' + +`clang`, and `pkg-config` are required to build, as well as +[Rust](https://www.rust-lang.org/tools/install) + +To install dependencies on a Debian system: + +``` +apt install -y clang pkg-config +``` + +To install dependencies on a Fedora system: +``` +dnf install clang pkg-config +``` + +Build with `cargo build --release --features=symphonia` + + # Usage Please refer to `UserGuide.md` for details of how this tool may be used. diff --git a/UserGuide.md b/UserGuide.md index 25be2fe..3927f67 100644 --- a/UserGuide.md +++ b/UserGuide.md @@ -14,7 +14,8 @@ Variants -------- `bliss-analyser` can be built to support using either the `ffmpeg` libraries -(`libavcodec`, etc.), or invoking the `ffmpeg` command itself. +(`libavcodec`, etc.), `symphonia` library, or invoking the `ffmpeg` command +itself. If the package used ended with `-libav` then `bliss-analyser` has been built with the `ffmpeg` libraries. This allows faster decoding of files, but will @@ -31,6 +32,11 @@ also have the `ffmpeg` application installed and in your `$PATH`. These builds are roughly 46% slower at analysis, but are more portable as they can use any `ffmpeg` version. +If the package used ended with `-symphonia` then `bliss-analyser` has been built +with the `symphonia` libraries. This allows a more portable binary, but at a +*much* slower decdoding speed (and anlysis results are not the same as those +produced by `ffmpeg`/`libav`). + Quick guide =========== diff --git a/docker/Dockerfile_Bullseye_symphonia b/docker/Dockerfile_Bullseye_symphonia new file mode 100644 index 0000000..3723237 --- /dev/null +++ b/docker/Dockerfile_Bullseye_symphonia @@ -0,0 +1,30 @@ +# Cross compilation environment for bliss-anlyser + +FROM debian:bullseye + +RUN dpkg --add-architecture arm64 && \ + dpkg --add-architecture armhf +RUN apt-get update + +RUN apt-get install -y curl git pkg-config yasm +RUN apt-get install -y build-essential clang +RUN apt-get install -y crossbuild-essential-armhf crossbuild-essential-arm64 + +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y +ENV PATH="/root/.cargo/bin/:${PATH}" +RUN rustup target add aarch64-unknown-linux-gnu && \ + rustup target add arm-unknown-linux-gnueabihf + +RUN mkdir /.cargo && \ + echo '[target.aarch64-unknown-linux-gnu]\nlinker = "aarch64-linux-gnu-gcc"' > /.cargo/config && \ + echo '[target.arm-unknown-linux-gnueabihf]\nlinker = "arm-linux-gnueabihf-gcc"' >> /.cargo/config + +RUN mkdir /build +ENV CARGO_TARGET_DIR /build +ENV CARGO_HOME /build/cache + +RUN mkdir /src + +WORKDIR /src +CMD ["/src/docker/docker-build-arm-symphonia.sh"] + diff --git a/docker/docker-build-arm-symphonia.sh b/docker/docker-build-arm-symphonia.sh new file mode 100755 index 0000000..f422b4d --- /dev/null +++ b/docker/docker-build-arm-symphonia.sh @@ -0,0 +1,29 @@ +#!/bin/bash +## #!/usr/bin/env bash +set -eux + +uname -a +DESTDIR=/src/releases + +mkdir -p $DESTDIR/bin +rm -rf $DESTDIR/bin/* + +function build { + echo Building for $1 to $3... + + if [[ ! -f /build/$1/release/bliss-analyser ]]; then + export RUST_BACKTRACE=full + export PKG_CONFIG=${1//unknown-/}-pkg-config + BINDGEN_EXTRA_CLANG_ARGS="--sysroot /usr/${1//unknown-/}" cargo build --release --features=symphonia --target $1 + fi + + $2 /build/$1/release/bliss-analyser && cp /build/$1/release/bliss-analyser $DESTDIR/$3 +} + +build arm-unknown-linux-gnueabihf arm-linux-gnueabihf-strip bin/bliss-analyser-armhf +build aarch64-unknown-linux-gnu aarch64-linux-gnu-strip bin/bliss-analyser-aarch64 + +cp UserGuide.md $DESTDIR/README.md +cp LICENSE $DESTDIR/ +cp configs/linux.ini $DESTDIR/config.ini +cp scripts/bliss-analyser-arm $DESTDIR/bliss-analyser diff --git a/download.py b/download.py index fea64a4..f700680 100755 --- a/download.py +++ b/download.py @@ -11,10 +11,10 @@ import datetime, os, requests, shutil, subprocess, sys, tempfile, time GITHUB_TOKEN_FILE = "%s/.config/github-token" % os.path.expanduser('~') GITHUB_REPO = "CDrummond/bliss-analyser" -LINUX_ARM_ARTIFACTS = ["bliss-analyser-linux-arm-ffmpeg", "bliss-analyser-linux-arm-static", "bliss-analyser-debian-bullseye-arm-libav", "bliss-analyser-debian-bookworm-arm-libav"] -LINUX_X86_ARTIFACTS = ["bliss-analyser-linux-x86-ffmpeg", "bliss-analyser-linux-x86-static", "bliss-analyser-ubuntu-22.04-x86-libav", "bliss-analyser-ubuntu-24.04-x86-libav"] -MAC_ARTIFACTS = ["bliss-analyser-mac-ffmpeg"] -WINDOWS_ARTIFACTS = ["bliss-analyser-windows-libav"] +LINUX_ARM_ARTIFACTS = ["bliss-analyser-linux-arm-ffmpeg", "bliss-analyser-linux-arm-static", "bliss-analyser-debian-bullseye-arm-libav", "bliss-analyser-debian-bookworm-arm-libav", "bliss-analyser-linux-arm-symphonia"] +LINUX_X86_ARTIFACTS = ["bliss-analyser-linux-x86-ffmpeg", "bliss-analyser-linux-x86-static", "bliss-analyser-ubuntu-22.04-x86-libav", "bliss-analyser-ubuntu-24.04-x86-libav", "bliss-analyser-linux-x86-symphonia"] +MAC_ARTIFACTS = ["bliss-analyser-mac-ffmpeg", "bliss-analyser-mac-symphonia"] +WINDOWS_ARTIFACTS = ["bliss-analyser-windows-libav", "bliss-analyser-windows-symphonia"] UNIX_ARTIFACTS = LINUX_ARM_ARTIFACTS + LINUX_X86_ARTIFACTS + MAC_ARTIFACTS GITHUB_ARTIFACTS = UNIX_ARTIFACTS + WINDOWS_ARTIFACTS @@ -70,7 +70,6 @@ def download_artifacts(version): f.write(chunk) if not os.path.exists(dest): info("Failed to download %s" % item) - break def make_executable(version): diff --git a/src/analyse.rs b/src/analyse.rs index 40c2789..64cdbf1 100644 --- a/src/analyse.rs +++ b/src/analyse.rs @@ -16,7 +16,7 @@ use anyhow::Result; use hhmmss::Hhmmss; use if_chain::if_chain; use indicatif::{ProgressBar, ProgressStyle}; -#[cfg(feature = "libav")] +#[cfg(not(feature = "ffmpeg"))] use std::collections::HashSet; use std::convert::TryInto; use std::fs::{DirEntry, File}; @@ -36,6 +36,8 @@ use num_cpus; use bliss_audio::{decoder::Decoder, decoder::ffmpeg::FFmpeg}; #[cfg(feature = "ffmpeg")] use bliss_audio::{decoder::Decoder, BlissResult, Song}; +#[cfg(feature = "symphonia")] +use bliss_audio::{decoder::Decoder, decoder::symphonia::SymphoniaDecoder}; const DONT_ANALYSE: &str = ".notmusic"; const MAX_ERRORS_TO_SHOW: usize = 100; @@ -86,7 +88,7 @@ fn check_dir_entry(db: &mut db::Db, mpath: &Path, entry: DirEntry, track_paths: let cue_track_sname = String::from(cue_track_stripped.to_string_lossy()); if let Ok(id) = db.get_rowid(&cue_track_sname) { - #[cfg(feature = "libav")] + #[cfg(not(feature = "ffmpeg"))] if id<=0 { track_paths.push(String::from(cue_file.to_string_lossy())); *file_count+=1; @@ -255,6 +257,93 @@ fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec, max Ok(()) } +#[cfg(feature = "symphonia")] +fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec, max_threads: usize, use_tags: bool) -> Result<()> { + let total = track_paths.len(); + let progress = ProgressBar::new(total.try_into().unwrap()).with_style( + ProgressStyle::default_bar() + .template("[{elapsed_precise}] [{bar:25}] {percent:>3}% {pos:>6}/{len:6} {wide_msg}") + .progress_chars("=> "), + ); + let cpu_threads: NonZeroUsize = match max_threads { + 0 => NonZeroUsize::new(num_cpus::get()).unwrap(), + _ => NonZeroUsize::new(max_threads).unwrap(), + }; + + let mut analysed = 0; + let mut failed: Vec = Vec::new(); + let mut tag_error: Vec = Vec::new(); + let mut reported_cue:HashSet = HashSet::new(); + + log::info!("Analysing new files"); + for (path, result) in ::analyze_paths_with_cores(track_paths, cpu_threads) { + let stripped = path.strip_prefix(mpath).unwrap(); + let spbuff = stripped.to_path_buf(); + let sname = String::from(spbuff.to_string_lossy()); + progress.set_message(format!("{}", sname)); + let mut inc_progress = true; // Only want to increment progress once for cue tracks + match result { + Ok(track) => { + let cpath = String::from(path.to_string_lossy()); + match track.cue_info { + Some(cue) => { + match track.track_number { + Some(track_num) => { + if reported_cue.contains(&cpath) { + inc_progress = false; + } else { + analysed += 1; + reported_cue.insert(cpath); + } + let meta = db::Metadata { + title: track.title.unwrap_or_default().to_string(), + artist: track.artist.unwrap_or_default().to_string(), + album: track.album.unwrap_or_default().to_string(), + album_artist: track.album_artist.unwrap_or_default().to_string(), + genre: track.genre.unwrap_or_default().to_string(), + duration: track.duration.as_secs() as u32, + analysis: None + }; + + // Remove prefix from audio_file_path + let pbuff = PathBuf::from(&cue.audio_file_path); + let stripped = pbuff.strip_prefix(mpath).unwrap(); + let spbuff = stripped.to_path_buf(); + let sname = String::from(spbuff.to_string_lossy()); + + let db_path = format!("{}{}{}", sname, db::CUE_MARKER, track_num); + db.add_track(&db_path, &meta, &track.analysis); + } + None => { failed.push(format!("{} - No track number?", sname)); } + } + } + None => { + let meta = tags::read(&cpath, false); + if meta.is_empty() { + tag_error.push(sname.clone()); + } + if use_tags { + tags::write_analysis(&cpath, &track.analysis); + } + db.add_track(&sname, &meta, &track.analysis); + } + } + analysed += 1; + } + Err(e) => { failed.push(format!("{} - {}", sname, e)); } + }; + + if inc_progress { + progress.inc(1); + } + } + + progress.finish_with_message("Finished!"); + log::info!("{} Analysed. {} Failure(s).", analysed, failed.len()); + show_errors(&mut failed, &mut tag_error); + Ok(()) +} + #[cfg(feature = "ffmpeg")] fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec, max_threads: usize, use_tags: bool) -> Result<()> { let total = track_paths.len(); diff --git a/src/cue.rs b/src/cue.rs index c5162e1..68aed94 100644 --- a/src/cue.rs +++ b/src/cue.rs @@ -22,7 +22,7 @@ pub const LAST_TRACK_DURATION:u64 = 60*60*24; #[cfg(feature = "ffmpeg")] const GENRE:&str = "GENRE"; -#[cfg(feature = "libav")] +#[cfg(not(feature = "ffmpeg"))] #[derive(Clone)] pub struct CueTrack { pub track_path:PathBuf