mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:41:09 +02:00
✨ feat(stt): add speech-to-text service for Mac Mini
Add mana-stt service with Whisper and Voxtral support for local transcription. Includes setup script and launchd integration for automatic startup on Mac Mini server. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
aeabd21d4a
commit
bf0fa04e7e
10 changed files with 1206 additions and 0 deletions
|
|
@ -23,6 +23,7 @@ cd ~/projects/manacore-monorepo
|
|||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `setup-autostart.sh` | Configure automatic startup on boot (run once) |
|
||||
| `setup-stt.sh` | Setup STT service (Whisper + Voxtral) |
|
||||
| `startup.sh` | Main startup script (called by launchd) |
|
||||
| `health-check.sh` | Check all services health |
|
||||
| `status.sh` | Show full system status |
|
||||
|
|
@ -143,6 +144,7 @@ Three services are configured to run automatically:
|
|||
| Cloudflared | `com.cloudflare.cloudflared` | Tunnel to Cloudflare |
|
||||
| Docker Startup | `com.manacore.docker-startup` | Start containers on boot |
|
||||
| Health Check | `com.manacore.health-check` | Check every 5 minutes |
|
||||
| STT Service | `com.manacore.stt` | Speech-to-Text (Whisper + Voxtral) |
|
||||
|
||||
### Manual Service Control
|
||||
|
||||
|
|
@ -238,4 +240,49 @@ Once running, services are available at:
|
|||
| Calendar API | https://calendar-api.mana.how |
|
||||
| Clock | https://clock.mana.how |
|
||||
| Clock API | https://clock-api.mana.how |
|
||||
| STT API | http://localhost:3020 (internal only) |
|
||||
| SSH | ssh mac-mini (via cloudflared) |
|
||||
|
||||
## Native Services (non-Docker)
|
||||
|
||||
### Ollama (LLM)
|
||||
|
||||
Ollama runs natively on Mac Mini for LLM inference:
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
curl http://localhost:11434/api/tags
|
||||
|
||||
# List models
|
||||
ollama list
|
||||
|
||||
# Pull a model
|
||||
ollama pull gemma3:4b
|
||||
```
|
||||
|
||||
### STT Service (Speech-to-Text)
|
||||
|
||||
The STT service provides Whisper and Voxtral transcription:
|
||||
|
||||
```bash
|
||||
# Setup (first time)
|
||||
./scripts/mac-mini/setup-stt.sh
|
||||
|
||||
# Check status
|
||||
curl http://localhost:3020/health
|
||||
|
||||
# Transcribe audio
|
||||
curl -X POST http://localhost:3020/transcribe \
|
||||
-F "file=@audio.mp3" \
|
||||
-F "language=de"
|
||||
|
||||
# View logs
|
||||
tail -f /tmp/manacore-stt.log
|
||||
```
|
||||
|
||||
**Available endpoints:**
|
||||
- `POST /transcribe` - Whisper transcription (recommended)
|
||||
- `POST /transcribe/voxtral` - Voxtral transcription
|
||||
- `POST /transcribe/auto` - Auto-select model
|
||||
- `GET /health` - Health check
|
||||
- `GET /models` - List available models
|
||||
|
|
|
|||
153
scripts/mac-mini/setup-stt.sh
Executable file
153
scripts/mac-mini/setup-stt.sh
Executable file
|
|
@ -0,0 +1,153 @@
|
|||
#!/bin/bash
|
||||
# Setup STT Service on Mac Mini
|
||||
# Creates launchd service for auto-start
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
STT_DIR="$REPO_DIR/services/mana-stt"
|
||||
PLIST_NAME="com.manacore.stt"
|
||||
PLIST_PATH="$HOME/Library/LaunchAgents/$PLIST_NAME.plist"
|
||||
|
||||
echo "=============================================="
|
||||
echo " ManaCore STT Service Setup (Mac Mini)"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
|
||||
# Check if STT service directory exists
|
||||
if [ ! -d "$STT_DIR" ]; then
|
||||
echo "Error: STT service directory not found at $STT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run the main setup script first
|
||||
echo "1. Running STT service setup..."
|
||||
cd "$STT_DIR"
|
||||
if [ ! -d ".venv" ]; then
|
||||
echo " Installing dependencies..."
|
||||
./setup.sh
|
||||
else
|
||||
echo " Virtual environment already exists"
|
||||
echo " Skipping dependency installation"
|
||||
fi
|
||||
|
||||
# Create launchd plist
|
||||
echo ""
|
||||
echo "2. Creating launchd service..."
|
||||
|
||||
cat > "$PLIST_PATH" << EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>$PLIST_NAME</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>$STT_DIR/.venv/bin/uvicorn</string>
|
||||
<string>app.main:app</string>
|
||||
<string>--host</string>
|
||||
<string>0.0.0.0</string>
|
||||
<string>--port</string>
|
||||
<string>3020</string>
|
||||
</array>
|
||||
|
||||
<key>WorkingDirectory</key>
|
||||
<string>$STT_DIR</string>
|
||||
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>$STT_DIR/.venv/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
<key>PORT</key>
|
||||
<string>3020</string>
|
||||
<key>WHISPER_MODEL</key>
|
||||
<string>large-v3-turbo</string>
|
||||
<key>PRELOAD_MODELS</key>
|
||||
<string>false</string>
|
||||
<key>CORS_ORIGINS</key>
|
||||
<string>https://mana.how,https://chat.mana.how,https://todo.mana.how</string>
|
||||
</dict>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>KeepAlive</key>
|
||||
<dict>
|
||||
<key>SuccessfulExit</key>
|
||||
<false/>
|
||||
<key>Crashed</key>
|
||||
<true/>
|
||||
</dict>
|
||||
|
||||
<key>ThrottleInterval</key>
|
||||
<integer>10</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/manacore-stt.log</string>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/manacore-stt.error.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
echo " Created: $PLIST_PATH"
|
||||
|
||||
# Unload if already loaded
|
||||
echo ""
|
||||
echo "3. Loading launchd service..."
|
||||
launchctl unload "$PLIST_PATH" 2>/dev/null || true
|
||||
launchctl load "$PLIST_PATH"
|
||||
|
||||
# Wait for service to start
|
||||
sleep 2
|
||||
|
||||
# Check if service is running
|
||||
echo ""
|
||||
echo "4. Checking service status..."
|
||||
if launchctl list | grep -q "$PLIST_NAME"; then
|
||||
echo " Service is running"
|
||||
|
||||
# Check health endpoint
|
||||
sleep 3
|
||||
if curl -s http://localhost:3020/health > /dev/null 2>&1; then
|
||||
echo " Health check passed"
|
||||
HEALTH=$(curl -s http://localhost:3020/health)
|
||||
echo " $HEALTH"
|
||||
else
|
||||
echo " Warning: Health check failed (service may still be starting)"
|
||||
echo " Check logs: tail -f /tmp/manacore-stt.log"
|
||||
fi
|
||||
else
|
||||
echo " Warning: Service may not be running"
|
||||
echo " Check logs: tail -f /tmp/manacore-stt.error.log"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " STT Service Setup Complete!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "Service URL: http://localhost:3020"
|
||||
echo ""
|
||||
echo "Useful commands:"
|
||||
echo " # View logs"
|
||||
echo " tail -f /tmp/manacore-stt.log"
|
||||
echo ""
|
||||
echo " # Restart service"
|
||||
echo " launchctl kickstart -k gui/\$(id -u)/$PLIST_NAME"
|
||||
echo ""
|
||||
echo " # Stop service"
|
||||
echo " launchctl unload $PLIST_PATH"
|
||||
echo ""
|
||||
echo " # Start service"
|
||||
echo " launchctl load $PLIST_PATH"
|
||||
echo ""
|
||||
echo " # Test transcription"
|
||||
echo " curl -X POST http://localhost:3020/transcribe \\"
|
||||
echo " -F 'file=@audio.mp3' \\"
|
||||
echo " -F 'language=de'"
|
||||
echo ""
|
||||
|
|
@ -46,6 +46,7 @@ check_launchd() {
|
|||
check_launchd "com.cloudflare.cloudflared" "Cloudflared Tunnel"
|
||||
check_launchd "com.manacore.docker-startup" "Docker Startup"
|
||||
check_launchd "com.manacore.health-check" "Health Check (5min)"
|
||||
check_launchd "com.manacore.stt" "STT Service (Whisper/Voxtral)"
|
||||
|
||||
# ============================================
|
||||
# Docker Status
|
||||
|
|
@ -83,6 +84,27 @@ if docker info >/dev/null 2>&1; then
|
|||
done
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# Native Services (non-Docker)
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BOLD}Native Services:${NC}"
|
||||
|
||||
# Ollama
|
||||
if curl -s --max-time 2 http://localhost:11434/api/tags >/dev/null 2>&1; then
|
||||
OLLAMA_MODELS=$(curl -s http://localhost:11434/api/tags | grep -o '"name":"[^"]*"' | wc -l | tr -d ' ')
|
||||
echo -e " ${GREEN}[Running]${NC} Ollama (${OLLAMA_MODELS} models)"
|
||||
else
|
||||
echo -e " ${YELLOW}[Stopped]${NC} Ollama"
|
||||
fi
|
||||
|
||||
# STT Service
|
||||
if curl -s --max-time 2 http://localhost:3020/health >/dev/null 2>&1; then
|
||||
echo -e " ${GREEN}[Running]${NC} STT Service (port 3020)"
|
||||
else
|
||||
echo -e " ${YELLOW}[Stopped]${NC} STT Service"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# Network/Tunnel Status
|
||||
# ============================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue