From 6c69d82156f2e8af388a4b10e6cdc650e8d2106e Mon Sep 17 00:00:00 2001 From: Zuckerberg Date: Tue, 5 Aug 2025 19:37:46 -0700 Subject: [PATCH] Add support for Home Assistant voice (whisper + piper + cloud llm) and Music Assistant via Spotify by librespot Music assistant has custom modifications they made to librespot that they haven't bothered to even try to upstream. Thus, they require a custom librespot. I tried and tried and tried and tried to just override the one already in nixpkgs but I had trouble doing so despite copying the pattern already shown in nixpkgs for overriding the src of a cargo pkg (See mopidy) but it just didn't work... Oh well. So I just patch nixpkgs instead with the new source. It works I guess. This is about where I gave up... ```nix nixpkgs.overlays = [ (final: prev: { # Cannot use librespot upstream because music-assistant requires custom changes # that they never bothered to even try to uptream librespot = prev.librespot.overrideAttrs (oldAttrs: rec { src = prev.fetchFromGitHub { owner = "music-assistant"; repo = "librespot"; rev = "786cc46199e583f304a84c786acb0a9b37bc3fbd"; sha256 = "sha256-xaOrqC8yCjF23Tz31RD3CzqZ3xxrDM6ncW1yoovEaGQ="; }; cargoDeps = oldAttrs.cargoDeps.overrideAttrs (oldAttrs': { vendorStaging = oldAttrs'.vendorStaging.overrideAttrs { outputHash = "sha256-SqvJSHkyd1IicT6c4pE96dBJNNodULhpyG14HRGVWCk="; }; }); }); }) ]; ``` --- flake.nix | 4 +++ machines/storage/s0/default.nix | 2 +- machines/storage/s0/home-automation.nix | 44 ++++++++++++++++++++++++- patches/librespot-pin.patch | 28 ++++++++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 patches/librespot-pin.patch diff --git a/flake.nix b/flake.nix index f16c4bd..8c11ffe 100644 --- a/flake.nix +++ b/flake.nix @@ -120,6 +120,10 @@ patches = [ # ./patches/gamepadui.patch ./patches/dont-break-nix-serve.patch + # music-assistant needs a specific custom version of librespot + # I tried to use an overlay but my attempts to override the rust package did not work out + # despite me following guides and examples specific to rust packages. + ./patches/librespot-pin.patch ]; }; patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; }); diff --git a/machines/storage/s0/default.nix b/machines/storage/s0/default.nix index a2414a7..6245a21 100644 --- a/machines/storage/s0/default.nix +++ b/machines/storage/s0/default.nix @@ -237,7 +237,7 @@ globalRedirect = "s0.neet.dev"; }; } - (mkVirtualHost "ha.s0.neet.dev" "http://localhost:8123") # home assistant + (mkVirtualHost "ha.s0.neet.dev" "http://localhost:${toString config.services.home-assistant.config.http.server_port}") (mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052") (mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834") { diff --git a/machines/storage/s0/home-automation.nix b/machines/storage/s0/home-automation.nix index 55c4cbd..8247a0f 100644 --- a/machines/storage/s0/home-automation.nix +++ b/machines/storage/s0/home-automation.nix @@ -15,7 +15,14 @@ ]; }; networking.firewall.allowedTCPPorts = [ - 1883 # mqtt + # mqtt + 1883 + + # Must be exposed so some local devices (such as HA voice preview) can pair with home assistant + config.services.home-assistant.config.http.server_port + + # Music assistant (must be exposed so local devices can fetch the audio stream from it) + 8097 ]; services.zigbee2mqtt = { @@ -75,12 +82,23 @@ "homekit_controller" "zha" "bluetooth" + "whisper" + "piper" + "wyoming" + "tts" + "music_assistant" + "openai_conversation" ]; config = { # Includes dependencies for a basic setup # https://www.home-assistant.io/integrations/default_config/ default_config = { }; + homeassistant = { + external_url = "https://ha.s0.neet.dev"; + internal_url = "http://192.168.1.2:${toString config.services.home-assistant.config.http.server_port}"; + }; + # Enable reverse proxy support http = { use_x_forwarded_for = true; @@ -105,4 +123,28 @@ }; }; }; + + services.wyoming.faster-whisper.servers."hass" = { + enable = true; + uri = "tcp://0.0.0.0:45785"; + model = "distil-small.en"; + language = "en"; + }; + + services.wyoming.piper.servers."hass" = { + enable = true; + uri = "tcp://0.0.0.0:45786"; + voice = "en_US-joe-medium"; + }; + + services.music-assistant = { + enable = true; + providers = [ + "hass" + "hass_players" + "jellyfin" + "radiobrowser" + "spotify" + ]; + }; } diff --git a/patches/librespot-pin.patch b/patches/librespot-pin.patch new file mode 100644 index 0000000..1e27f26 --- /dev/null +++ b/patches/librespot-pin.patch @@ -0,0 +1,28 @@ +diff --git a/pkgs/applications/audio/librespot/default.nix b/pkgs/applications/audio/librespot/default.nix +index 9694c3d0cf4f..ca9502de7ee1 100644 +--- a/pkgs/applications/audio/librespot/default.nix ++++ b/pkgs/applications/audio/librespot/default.nix +@@ -25,14 +25,19 @@ rustPlatform.buildRustPackage rec { + version = "0.6.0"; + + src = fetchFromGitHub { +- owner = "librespot-org"; ++ owner = "googlebot42"; + repo = "librespot"; +- rev = "v${version}"; +- sha256 = "sha256-dGQDRb7fgIkXelZKa+PdodIs9DxbgEMlVGJjK/hU3Mo="; ++ rev = "786cc46199e583f304a84c786acb0a9b37bc3fbd"; ++ sha256 = "sha256-xaOrqC8yCjF23Tz31RD3CzqZ3xxrDM6ncW1yoovEaGQ="; + }; + + useFetchCargoVendor = true; +- cargoHash = "sha256-SqvJSHkyd1IicT6c4pE96dBJNNodULhpyG14HRGVWCk="; ++ cargoHash = "sha256-sUAZgOuBD9CGAy1mRqLRzVnVfxB0DqSCNAc2yzItTCA="; ++ ++ cargoBuildFlags = [ ++ "--features" ++ "passthrough-decoder" ++ ]; + + nativeBuildInputs = [ + pkg-config