#!/bin/bash # ═══════════════════════════════════════════════════════════════ # Alfred Linux v2.0-b4 — Voice (Kokoro TTS + Welcome Greeting) # # Installs Kokoro TTS for offline voice synthesis. # Alfred speaks on first boot. # BUILD: v2.0-b4 (Voice) # ═══════════════════════════════════════════════════════════════ set +e # Voice is optional — don't kill the build if TTS install fails echo "[Alfred Linux v2.0-b4] Installing Voice subsystem..." # ── 0. Ensure DNS works inside chroot ── if ! getent hosts deb.debian.org &>/dev/null 2>&1; then rm -f /etc/resolv.conf 2>/dev/null || true printf 'nameserver 9.9.9.9\nnameserver 1.1.1.1\n' > /etc/resolv.conf fi # ── 1. Install Python audio dependencies ── PYVER=$(python3 --version 2>/dev/null | grep -oP '\d+\.\d+' | head -1) apt-get install -y python3-pip "python${PYVER}-venv" espeak-ng sox libsox-fmt-all 2>/dev/null || \ apt-get install -y python3-pip python3-venv espeak-ng sox libsox-fmt-all 2>/dev/null || true # ── 2. Install Kokoro TTS (CPU-only — no CUDA/NVIDIA bloat) ── # Install CPU-only PyTorch FIRST to prevent pulling the full 3.4GB CUDA stack. # This keeps the ISO under 4GB (ISO 9660 single-file limit). pip3 install --break-system-packages torch --index-url https://download.pytorch.org/whl/cpu 2>/dev/null || true pip3 install --break-system-packages kokoro 2>/dev/null || { echo "[WARN] kokoro system install failed, trying with venv..." python3 -m venv /opt/alfred-voice /opt/alfred-voice/bin/pip install torch --index-url https://download.pytorch.org/whl/cpu /opt/alfred-voice/bin/pip install kokoro ln -sf /opt/alfred-voice/bin/python3 /usr/local/bin/alfred-voice-python } # Clean up empty fallback venv dir if system-wide install worked if python3 -c "import kokoro" 2>/dev/null && [[ -d /opt/alfred-voice ]] && [[ ! -f /opt/alfred-voice/bin/python3 ]]; then rm -rf /opt/alfred-voice echo "[Alfred Voice] Kokoro installed system-wide, removed empty venv dir" fi # ── 3. Create welcome script ── cat > /usr/local/bin/alfred-welcome.sh << 'WELCOME' #!/bin/bash # Alfred Linux — First Boot Welcome # Speaks a greeting via Kokoro TTS on first login if [[ -f "$HOME/.alfred-welcomed" ]]; then exit 0 fi # Try Kokoro TTS first VOICE_PYTHON="python3" [[ -x /usr/local/bin/alfred-voice-python ]] && VOICE_PYTHON="/usr/local/bin/alfred-voice-python" $VOICE_PYTHON -c " try: from kokoro import KPipeline pipe = KPipeline(lang_code='a') generator = pipe('Welcome to Alfred Linux. I am Alfred, your AI companion. Everything here is sovereign. Everything here is yours.', voice='af_heart', speed=1.0) import soundfile as sf for i, (gs, ps, audio) in enumerate(generator): sf.write('/tmp/alfred-welcome.wav', audio, 24000) break except Exception as e: print(f'Kokoro TTS failed: {e}') import subprocess subprocess.run(['espeak-ng', '-w', '/tmp/alfred-welcome.wav', 'Welcome to Alfred Linux. I am Alfred, your AI companion.']) " 2>/dev/null # Play the audio if [[ -f /tmp/alfred-welcome.wav ]]; then aplay /tmp/alfred-welcome.wav 2>/dev/null || paplay /tmp/alfred-welcome.wav 2>/dev/null || true rm -f /tmp/alfred-welcome.wav fi # Mark as welcomed touch "$HOME/.alfred-welcomed" WELCOME chmod +x /usr/local/bin/alfred-welcome.sh # ── 4. XFCE autostart entry ── mkdir -p /etc/skel/.config/autostart cat > /etc/skel/.config/autostart/alfred-welcome.desktop << 'DESK' [Desktop Entry] Type=Application Name=Alfred Welcome Comment=Alfred greets you on first login Exec=/usr/local/bin/alfred-welcome.sh Hidden=false X-GNOME-Autostart-enabled=true X-GNOME-Autostart-Delay=3 DESK # ── 5. Alfred TTS CLI wrapper ── cat > /usr/local/bin/alfred-say << 'SAY' #!/bin/bash # Alfred TTS — speak any text # Usage: alfred-say "Hello, Commander" TEXT="${*:-Hello, I am Alfred.}" VOICE_PYTHON="python3" [[ -x /usr/local/bin/alfred-voice-python ]] && VOICE_PYTHON="/usr/local/bin/alfred-voice-python" $VOICE_PYTHON -c " try: from kokoro import KPipeline pipe = KPipeline(lang_code='a') generator = pipe('''$TEXT''', voice='af_heart', speed=1.0) import soundfile as sf for i, (gs, ps, audio) in enumerate(generator): sf.write('/tmp/alfred-tts.wav', audio, 24000) break except Exception: import subprocess subprocess.run(['espeak-ng', '-w', '/tmp/alfred-tts.wav', '''$TEXT''']) " 2>/dev/null if [[ -f /tmp/alfred-tts.wav ]]; then aplay /tmp/alfred-tts.wav 2>/dev/null || paplay /tmp/alfred-tts.wav 2>/dev/null rm -f /tmp/alfred-tts.wav fi SAY chmod +x /usr/local/bin/alfred-say echo "[Alfred Linux v2.0-b4] Voice subsystem installed."