fix(install): fix model download and VOSK-only option in interactive mode (#132)

* fix(install): fix model download and VOSK-only option in interactive mode

- Add missing option 3 handling in interactive prompt to create VOSK
  config when user selects VOSK-only mode (mirrors --no-whisper flag)
- Set WITH_WHISPER and WHISPER_CPU flags correctly for options 1 and 2
- Fix Whisper model download logic to check actual installation status
  using venv python instead of relying on unreliable flag combinations
- Always download Whisper tiny model when Whisper is installed since
  it's the default engine in config_manager.py
- Add informative messages about model download status

Fixes issues where:
1. Selecting option 2 or 3 didn't properly configure the system
2. Whisper tiny model wasn't downloaded even when Whisper was selected
3. App defaulted to Whisper engine but model wasn't available

* fix(install): use explicit venv python path and simplify condition

- Use $VENV_DIR/bin/python instead of bare 'python' in run_tests() and
  verify_installation() for consistency and reliability
- Simplify Whisper install condition since WITH_WHISPER is already set
  by auto-detection in non-interactive mode (lines 412-424)
- Update comments to better explain the logic flow

* style(install): restore ASCII art logo and improve formatting

- Restore beautiful VOCALINUX ASCII art banner in interactive installer
- Restore ASCII art banner in installation complete message
- Use Unicode box-drawing characters (━) for section separators
- Use bullet points (•) instead of dashes for lists
- Add colored terminal output for commands
- Add star emoji for GitHub link

* style(install): show ASCII art banner in all installation modes

The ASCII art logo is now displayed at the start of installation
regardless of mode (interactive, curl|bash, or with flags).

* fix(install): remove duplicate ASCII art in interactive mode

The ASCII art banner is now shown once at script start for all modes.
Remove the duplicate from run_interactive_install() to avoid showing
it twice when running with -i/--interactive flag.

* docs(install): rename options to 'Full install' and 'Minimal install'

Clarify that VOSK is always installed as a fallback engine:
- 'Full install' = Whisper + VOSK (recommended, highest accuracy)
- 'Minimal install' = VOSK only (lightweight, ~40MB)

Updates both the -i interactive installer and the fallback prompt.
Also improves the installation summary display.

* fix(install): update desktop database so app appears in menu immediately

Previously only the icon cache was updated after installation, but not
the desktop database. This caused the app to not appear in application
menus until the user logged out and back in (or manually ran
update-desktop-database).

Now the installer runs update-desktop-database after installing the
.desktop file, so Vocalinux appears in the app launcher immediately.
This commit is contained in:
Jatin K Malik
2026-02-05 13:45:26 -08:00
committed by GitHub
parent b62fb9049b
commit 2becfb5a98
+137 -63
View File
@@ -116,6 +116,18 @@ if [[ "$DEV_MODE" == "yes" ]]; then
RUN_TESTS="yes"
fi
# Display ASCII art banner
cat << "EOF"
▗▖ ▗▖ ▗▄▖ ▗▄▄▖ ▗▄▖ ▗▖ ▗▄▄▄▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖
▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌ ▐▌▐▌ █ ▐▛▚▖▐▌▐▌ ▐▌ ▝▚▞▘
▐▌ ▐▌▐▌ ▐▌▐▌ ▐▛▀▜▌▐▌ █ ▐▌ ▝▜▌▐▌ ▐▌ ▐▌
▝▚▞▘ ▝▚▄▞▘▝▚▄▄▖▐▌ ▐▌▐▙▄▄▖▗▄█▄▖▐▌ ▐▌▝▚▄▞▘▗▞▘▝▚▖
Voice Dictation for Linux
EOF
print_info "Vocalinux Installer"
print_info "=============================="
echo ""
@@ -253,8 +265,8 @@ run_interactive_install() {
clear_screen
cat << "EOF"
Vocalinux - Interactive Installation Guide
==========================================
Interactive Installation Guide
===============================
EOF
@@ -281,31 +293,31 @@ EOF
fi
echo ""
# Step 2: Choose speech engine
print_header "Step 2: Speech Recognition Engine"
echo "Vocalinux supports two speech recognition engines:"
# Step 2: Choose installation type
print_header "Step 2: Installation Type"
echo "Choose what to install:"
echo ""
echo " 1. Whisper AI (recommended)"
echo " - Highest accuracy available"
echo " - 99+ languages supported"
echo " - Created by OpenAI"
echo " 1. Full install (recommended)"
echo " • Whisper AI - highest accuracy, 99+ languages"
echo " • VOSK - fast fallback engine"
echo " • Can switch between engines in Settings"
echo ""
echo " 2. VOSK"
echo " - Lightweight and fast"
echo " - Works on older/low-RAM systems"
echo " - 20+ languages supported"
echo " 2. Minimal install"
echo " • VOSK only - lightweight and fast"
echo " • Works on older/low-RAM systems"
echo " • ~40MB vs ~2GB+ for full install"
echo ""
read -p "Choose your speech engine [1-2] (default: 1): " ENGINE_CHOICE
read -p "Choose installation type [1-2] (default: 1): " ENGINE_CHOICE
ENGINE_CHOICE=${ENGINE_CHOICE:-1}
if [[ "$ENGINE_CHOICE" == "2" ]]; then
WITH_WHISPER="no"
NO_WHISPER_EXPLICIT="yes"
SELECTED_ENGINE="VOSK"
SELECTED_ENGINE="Minimal (VOSK only)"
else
WITH_WHISPER="yes"
SELECTED_ENGINE="Whisper AI"
SELECTED_ENGINE="Full (Whisper + VOSK)"
# Step 3: Whisper variant (if Whisper selected)
print_header "Step 3: Whisper Installation Type"
@@ -352,7 +364,10 @@ EOF
# Summary
print_header "Installation Summary"
echo "Speech engine: $SELECTED_ENGINE${SELECTED_VARIANT:+ ($SELECTED_VARIANT)}"
echo "Install type: $SELECTED_ENGINE"
if [[ "$WITH_WHISPER" == "yes" ]]; then
echo "Whisper variant: ${SELECTED_VARIANT:-GPU}"
fi
echo "Models: $([[ "$SKIP_MODELS" == "yes" ]] && echo "Download on first use" || echo "Download now")"
echo ""
read -p "Press Enter to continue, or Ctrl+C to cancel..."
@@ -971,8 +986,8 @@ VOSK_CONFIG
print_warning "Failed to install Whisper."
print_warning "Voice recognition will fall back to VOSK."
}
elif [ "$WITH_WHISPER" = "yes" ] || [ "$NON_INTERACTIVE" = "yes" ]; then
# Default: Install Whisper with GPU support (either explicitly requested or non-interactive default)
elif [ "$WITH_WHISPER" = "yes" ]; then
# Install Whisper with GPU support (set by --with-whisper flag or auto-detected in non-interactive mode)
print_info "Installing Whisper AI support with GPU/CUDA (~2.3GB download, ~5-10 min)..."
print_info "This enables high-accuracy speech recognition with GPU acceleration."
print_info "Tip: Use --whisper-cpu for a smaller download if you don't have an NVIDIA GPU."
@@ -983,21 +998,23 @@ VOSK_CONFIG
else
# Interactive mode: Prompt user
echo ""
print_info "Whisper AI provides better accuracy but requires more disk space."
print_info "Options:"
print_info " 1) Full install with GPU support (~2.3GB) - best if you have NVIDIA GPU"
print_info " 2) CPU-only install (~200MB) - works on any system, slightly slower"
print_info " 3) Skip Whisper - use VOSK only"
print_info "Choose installation type:"
print_info " 1) Full install - GPU (~2.3GB) - Whisper + VOSK, best accuracy"
print_info " 2) Full install - CPU (~200MB) - Whisper + VOSK, no GPU needed"
print_info " 3) Minimal install (~40MB) - VOSK only, lightweight"
read -p "Choose option [1/2/3]: " -n 1 -r
echo
if [[ $REPLY == "1" ]]; then
print_info "Installing Whisper with GPU support (this might take a while)..."
WITH_WHISPER="yes"
print_info "Installing full (Whisper + VOSK) with GPU support..."
pip install ".[whisper]" --log "$PIP_LOG_FILE" || {
print_warning "Failed to install Whisper support."
print_warning "Voice recognition will fall back to VOSK."
}
elif [[ $REPLY == "2" ]]; then
print_info "Installing Whisper with CPU-only PyTorch..."
WITH_WHISPER="yes"
WHISPER_CPU="yes"
print_info "Installing full (Whisper + VOSK) with CPU-only PyTorch..."
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu --log "$PIP_LOG_FILE" || {
print_warning "Failed to install CPU-only PyTorch."
}
@@ -1005,6 +1022,43 @@ VOSK_CONFIG
print_warning "Failed to install Whisper."
print_warning "Voice recognition will fall back to VOSK."
}
elif [[ $REPLY == "3" ]]; then
# User selected minimal install (VOSK only)
NO_WHISPER_EXPLICIT="yes"
print_info "Installing minimal (VOSK only)..."
# Create config file with VOSK as default engine
local CONFIG_FILE_PATH="$CONFIG_DIR/config.json"
if [ ! -f "$CONFIG_FILE_PATH" ]; then
print_info "Creating config with VOSK as default engine..."
cat > "$CONFIG_FILE_PATH" << 'VOSK_INTERACTIVE_CONFIG'
{
"speech_recognition": {
"engine": "vosk",
"model_size": "small",
"vosk_model_size": "small",
"whisper_model_size": "tiny",
"vad_sensitivity": 3,
"silence_timeout": 2.0
},
"audio": {
"device_index": null,
"device_name": null
},
"shortcuts": {
"toggle_recognition": "ctrl+ctrl"
},
"ui": {
"start_minimized": false,
"show_notifications": true
},
"advanced": {
"debug_logging": false,
"wayland_mode": false
}
}
VOSK_INTERACTIVE_CONFIG
fi
fi
fi
fi
@@ -1342,7 +1396,7 @@ install_icons() {
fi
}
# Function to update icon cache
# Function to update icon cache and desktop database
update_icon_cache() {
print_info "Updating icon cache..."
@@ -1354,6 +1408,16 @@ update_icon_cache() {
else
print_warning "gtk-update-icon-cache command not found, skipping icon cache update"
fi
# Update desktop database so the app appears in application menus immediately
print_info "Updating desktop database..."
if command_exists update-desktop-database; then
update-desktop-database "${XDG_DATA_HOME:-$HOME/.local/share}/applications" 2>/dev/null || {
print_warning "Failed to update desktop database"
}
else
print_warning "update-desktop-database command not found - app may not appear in menu until next login"
fi
}
# Install desktop entry
@@ -1362,21 +1426,27 @@ install_desktop_entry || print_warning "Desktop entry installation failed"
# Install icons
install_icons || print_warning "Icon installation failed"
# Install Whisper tiny model (if Whisper was installed)
if [ "$WITH_WHISPER" = "yes" ] || [ "$NON_INTERACTIVE" = "yes" ]; then
# Check if Whisper is actually installed before downloading model
if python -c "import whisper" 2>/dev/null; then
if [ "$SKIP_MODELS" = "no" ]; then
install_whisper_model || print_warning "Whisper model download failed - model will be downloaded on first run"
else
print_info "Skipping Whisper model download (--skip-models specified)"
fi
# Install Whisper tiny model if Whisper is available
# This is important because Whisper is the default engine in config_manager.py
# We check if Whisper was actually installed (importable) rather than relying on flags
if [ "$SKIP_MODELS" = "no" ]; then
if "$VENV_DIR/bin/python" -c "import whisper" 2>/dev/null; then
print_info "Whisper is installed - downloading tiny model (default engine)..."
install_whisper_model || print_warning "Whisper model download failed - model will be downloaded on first run"
elif [ "$NO_WHISPER_EXPLICIT" != "yes" ]; then
# Whisper is not installed but wasn't explicitly disabled
# This shouldn't happen in normal flow, but warn the user
print_warning "Whisper not available but is the default engine."
print_warning "The app will try to download the model on first run."
else
print_info "Whisper not available, skipping model download"
print_info "Whisper not installed (VOSK-only mode), skipping Whisper model download"
fi
else
print_info "Skipping Whisper model download (--skip-models specified)"
print_info "Model will be downloaded automatically on first application run"
fi
# Install VOSK models (as fallback)
# Install VOSK models (always useful as fallback, and required for VOSK-only mode)
if [ "$SKIP_MODELS" = "no" ]; then
install_vosk_models || print_warning "VOSK model installation failed - models will be downloaded on first run"
else
@@ -1391,8 +1461,8 @@ update_icon_cache
run_tests() {
print_info "Running tests..."
# Check if pytest is installed
if ! python -c "import pytest" &>/dev/null; then
# Check if pytest is installed in the virtual environment
if ! "$VENV_DIR/bin/python" -c "import pytest" &>/dev/null; then
print_info "Installing pytest and related packages..."
pip install pytest pytest-mock pytest-cov || {
print_error "Failed to install pytest. Cannot run tests."
@@ -1471,8 +1541,8 @@ verify_installation() {
((ISSUES++))
fi
# Check if Python package is importable
if ! python -c "import vocalinux" &>/dev/null; then
# Check if Python package is importable using venv python
if ! "$VENV_DIR/bin/python" -c "import vocalinux" &>/dev/null; then
print_error "Vocalinux Python package cannot be imported."
((ISSUES++))
fi
@@ -1487,10 +1557,15 @@ print_welcome_message() {
clear_screen
# ASCII art header
cat << "EOF"
Vocalinux - Installation Complete
================================
▗▖ ▗▖ ▗▄▖ ▗▄▄▖ ▗▄▖ ▗▖ ▗▄▄▄▖▗▖ ▗▖▗▖ ▗▖▗▖ ▗▖
▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌ ▐▌▐▌ █ ▐▛▚▖▐▌▐▌ ▐▌ ▝▚▞▘
▐▌ ▐▌▐▌ ▐▌▐▌ ▐▛▀▜▌▐▌ █ ▐▌ ▝▜▌▐▌ ▐▌ ▐▌
▝▚▞▘ ▝▚▄▞▘▝▚▄▄▖▐▌ ▐▌▐▙▄▄▖▗▄█▄▖▐▌ ▐▌▝▚▄▞▘▗▞▘▝▚▖
✓ Installation Complete!
EOF
@@ -1503,45 +1578,44 @@ EOF
fi
echo ""
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Getting Started"
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "1. Launch Vocalinux from your app menu"
echo " Look for 'Vocalinux' in your application launcher."
echo ""
echo " Or from terminal:"
echo " vocalinux"
echo -e " Or from terminal: \e[36mvocalinux\e[0m"
echo ""
echo "2. Find Vocalinux in your system tray (top bar)"
echo " - Click the icon to access settings"
echo " - Right-click for options (Quit, Settings, etc.)"
echo " • Click the icon to access settings"
echo " • Right-click for options (Quit, Settings, etc.)"
echo ""
echo "3. Start dictating!"
echo " Double-tap Ctrl anywhere to start/stop dictation"
echo -e " \e[1mDouble-tap Ctrl\e[0m anywhere to start/stop dictation"
echo ""
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " First Run Tips"
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "- Speak clearly and at a natural pace"
echo "- Use voice commands: 'period', 'comma', 'new line', 'delete that'"
echo "- Both engines are 100% offline - your privacy is protected"
echo "• Speak clearly and at a natural pace"
echo "• Use voice commands: 'period', 'comma', 'new line', 'delete that'"
echo "• Both engines are 100% offline - your privacy is protected"
echo ""
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Need Help?"
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "- Report issues: https://github.com/jatinkrmalik/vocalinux/issues"
echo "- Documentation: https://github.com/jatinkrmalik/vocalinux"
echo "- Star us on GitHub: https://github.com/jatinkrmalik/vocalinux"
echo "• Report issues: https://github.com/jatinkrmalik/vocalinux/issues"
echo "• Documentation: https://github.com/jatinkrmalik/vocalinux"
echo "• Star us on GitHub: ⭐ https://github.com/jatinkrmalik/vocalinux"
echo ""
# Installation details (optional, for debugging)
if [[ "$VERBOSE" == "yes" ]]; then
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Installation Details"
echo "============================================================"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Virtual environment: $VENV_DIR"
echo "Desktop entry: $DESKTOP_DIR/vocalinux.desktop"