Merge pull request 'feat(talk): ElevenLabs TTS voice notification package' (#17) from feat/talk-package into master
Reviewed-on: #17
This commit was merged in pull request #17.
This commit is contained in:
@@ -33,6 +33,7 @@ in {
|
|||||||
openwork = pkgs.callPackage ./openwork {};
|
openwork = pkgs.callPackage ./openwork {};
|
||||||
zellij-ps = pkgs.callPackage ./zellij-ps {};
|
zellij-ps = pkgs.callPackage ./zellij-ps {};
|
||||||
vibetyper = pkgs.callPackage ./vibetyper {};
|
vibetyper = pkgs.callPackage ./vibetyper {};
|
||||||
|
talk = pkgs.callPackage ./talk {};
|
||||||
|
|
||||||
# ── Pass-through packages ──────────────────────────────────────────
|
# ── Pass-through packages ──────────────────────────────────────────
|
||||||
# Imported directly from flake inputs. No local modifications.
|
# Imported directly from flake inputs. No local modifications.
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
writeShellScriptBin,
|
||||||
|
curl,
|
||||||
|
python3,
|
||||||
|
mpv,
|
||||||
|
libnotify,
|
||||||
|
busybox,
|
||||||
|
}: let
|
||||||
|
script = writeShellScriptBin "talk" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Toggle: VOICE_NOTIFY=0 deaktiviert alles ───────────────────
|
||||||
|
if [ "''${VOICE_NOTIFY:-1}" = "0" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Config ──────────────────────────────────────────────────────
|
||||||
|
API_KEY="''${ELEVENLABS_API_KEY:?Set ELEVENLABS_API_KEY in your environment}"
|
||||||
|
VOICE_ID="''${ELEVENLABS_VOICE_ID:-KXxZd16DiBqt82nbarJx}"
|
||||||
|
TEXT="''${1:?Usage: talk \"Text zum Sprechen\"}"
|
||||||
|
AUDIO_FILE="/tmp/voice-notify-$$.mp3"
|
||||||
|
ACTION_FILE="/tmp/voice-action-$$"
|
||||||
|
|
||||||
|
CURL="${lib.getExe curl}"
|
||||||
|
PYTHON="${lib.getExe python3}"
|
||||||
|
MPV="${lib.getExe mpv}"
|
||||||
|
NOTIFY="${lib.getExe libnotify}"
|
||||||
|
RM="${busybox}/bin/rm"
|
||||||
|
CAT="${busybox}/bin/cat"
|
||||||
|
GREP="${busybox}/bin/grep"
|
||||||
|
SLEEP="${busybox}/bin/sleep"
|
||||||
|
KILL="${busybox}/bin/kill"
|
||||||
|
STAT="${busybox}/bin/stat"
|
||||||
|
|
||||||
|
trap '$RM -f "$AUDIO_FILE" "$ACTION_FILE"' EXIT
|
||||||
|
|
||||||
|
# ── TTS generieren ──────────────────────────────────────────────
|
||||||
|
PAYLOAD=$("$PYTHON" -c '
|
||||||
|
import json, sys
|
||||||
|
print(json.dumps({
|
||||||
|
"text": sys.argv[1],
|
||||||
|
"model_id": "eleven_multilingual_v2",
|
||||||
|
"voice_settings": {"stability": 0.5, "similarity_boost": 0.75}
|
||||||
|
}))
|
||||||
|
' "$TEXT")
|
||||||
|
|
||||||
|
HTTP_CODE=$("$CURL" -s -o "$AUDIO_FILE" -w "%{http_code}" \
|
||||||
|
-X POST "https://api.elevenlabs.io/v1/text-to-speech/''${VOICE_ID}" \
|
||||||
|
-H "xi-api-key: ''${API_KEY}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$PAYLOAD") || HTTP_CODE="000"
|
||||||
|
|
||||||
|
if [ "$HTTP_CODE" != "200" ]; then
|
||||||
|
ERR=$($CAT "$AUDIO_FILE" 2>/dev/null | head -c 300)
|
||||||
|
$RM -f "$AUDIO_FILE"
|
||||||
|
"$NOTIFY" -u critical "❌ Voice Fehler" "HTTP ''${HTTP_CODE}\n''${ERR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Gleichzeitig: Audio + Notification ──────────────────────────
|
||||||
|
"$MPV" --no-video --no-terminal --really-quiet "$AUDIO_FILE" &
|
||||||
|
MPV_PID=$!
|
||||||
|
|
||||||
|
(
|
||||||
|
exec "$NOTIFY" \
|
||||||
|
--action=cancel="⛔ Abbrechen" \
|
||||||
|
--urgency=normal \
|
||||||
|
--icon=audio-x-generic \
|
||||||
|
"🔊 KI Antwort" \
|
||||||
|
"$TEXT" > "$ACTION_FILE" 2>/dev/null
|
||||||
|
) &
|
||||||
|
NOTIFY_PID=$!
|
||||||
|
|
||||||
|
# ── Poll-Loop ───────────────────────────────────────────────────
|
||||||
|
while true; do
|
||||||
|
if ! $KILL -0 "$MPV_PID" 2>/dev/null; then
|
||||||
|
$KILL "$NOTIFY_PID" 2>/dev/null || true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ -f "$ACTION_FILE" ]; then
|
||||||
|
if $GREP -q "cancel" "$ACTION_FILE" 2>/dev/null; then
|
||||||
|
$KILL "$MPV_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
$SLEEP 0.2
|
||||||
|
done
|
||||||
|
|
||||||
|
wait "$MPV_PID" 2>/dev/null || true
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "talk";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
dontUnpack = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p "$out/bin"
|
||||||
|
ln -s ${script}/bin/talk "$out/bin/talk"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "ElevenLabs TTS voice notifications with dismissable popup";
|
||||||
|
homepage = "https://code.m3ta.dev/m3tam3re/nixpkgs";
|
||||||
|
license = licenses.mit;
|
||||||
|
platforms = platforms.linux;
|
||||||
|
mainProgram = "talk";
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user