#!/bin/bash # # Meeting Assistant - Browser Mode Startup Script # 使用瀏覽器運行 Meeting Assistant(完整功能,包含即時語音轉寫) # # 此模式下: # - 後端會自動啟動並管理 Sidecar(Whisper 語音轉寫引擎) # - 前端在 Chrome/Edge 瀏覽器中運行 # - 所有功能皆可正常使用 # set -e # 顏色定義 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 專案路徑 PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BACKEND_DIR="$PROJECT_DIR/backend" SIDECAR_DIR="$PROJECT_DIR/sidecar" # Server Configuration (can be overridden by .env) BACKEND_HOST="${BACKEND_HOST:-0.0.0.0}" BACKEND_PORT="${BACKEND_PORT:-8000}" # Whisper Configuration (can be overridden by .env) export WHISPER_MODEL="${WHISPER_MODEL:-medium}" export WHISPER_DEVICE="${WHISPER_DEVICE:-cpu}" export WHISPER_COMPUTE="${WHISPER_COMPUTE:-int8}" # Browser mode flag - tells backend to manage sidecar export BROWSER_MODE="true" # 函數:印出訊息 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[OK]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Load environment variables from .env file if it exists if [ -f "$BACKEND_DIR/.env" ]; then log_info "Loading backend environment from $BACKEND_DIR/.env" export $(grep -v '^#' "$BACKEND_DIR/.env" | grep -v '^$' | xargs) fi # 函數:檢查 port 是否被佔用 check_port() { local port=$1 if lsof -i :$port > /dev/null 2>&1; then return 0 # port 被佔用 else return 1 # port 可用 fi } # 函數:開啟瀏覽器 open_browser() { local url=$1 log_info "Opening browser at $url" # Try different browser commands if command -v xdg-open &> /dev/null; then xdg-open "$url" & elif command -v wslview &> /dev/null; then wslview "$url" & elif command -v explorer.exe &> /dev/null; then # WSL: use Windows browser explorer.exe "$url" & elif command -v open &> /dev/null; then # macOS open "$url" & else log_warn "Could not find a browser to open. Please manually visit: $url" fi } # 函數:檢查環境 check_environment() { local all_ok=true # 檢查後端虛擬環境 if [ ! -d "$BACKEND_DIR/venv" ]; then log_error "Backend virtual environment not found" log_error "Please run: cd $BACKEND_DIR && python3 -m venv venv && source venv/bin/activate && pip install -r requirements.txt" all_ok=false fi # 檢查 Sidecar 虛擬環境 if [ ! -d "$SIDECAR_DIR/venv" ]; then log_warn "Sidecar virtual environment not found" log_warn "即時語音轉寫功能將無法使用" log_warn "To enable: cd $SIDECAR_DIR && python3 -m venv venv && source venv/bin/activate && pip install -r requirements.txt" else log_success "Sidecar environment found - 即時語音轉寫功能可用" fi if [ "$all_ok" = false ]; then exit 1 fi } # 函數:啟動後端(包含 Sidecar) start_backend() { log_info "Checking backend status..." # Check if backend is already running if check_port $BACKEND_PORT; then # Verify it's our backend by checking health endpoint if curl -s http://localhost:$BACKEND_PORT/api/health > /dev/null 2>&1; then log_success "Backend is already running on port $BACKEND_PORT" return 0 else log_warn "Port $BACKEND_PORT is in use but not by our backend" log_error "Please stop the process using port $BACKEND_PORT and try again" exit 1 fi fi log_info "Starting backend server (with Sidecar management)..." log_info "Whisper config: model=$WHISPER_MODEL, device=$WHISPER_DEVICE, compute=$WHISPER_COMPUTE" cd "$BACKEND_DIR" source venv/bin/activate # Start uvicorn in background nohup uvicorn app.main:app --host $BACKEND_HOST --port $BACKEND_PORT > "$PROJECT_DIR/backend-browser.log" 2>&1 & local backend_pid=$! # Wait for backend to be ready log_info "Waiting for backend and sidecar to start..." log_info "(This may take a minute if Whisper model needs to download)" local max_wait=120 # 2 minutes for model download local waited=0 while [ $waited -lt $max_wait ]; do sleep 2 waited=$((waited + 2)) if curl -s http://localhost:$BACKEND_PORT/api/health > /dev/null 2>&1; then log_success "Backend started (PID: $backend_pid)" # Check sidecar status local sidecar_status=$(curl -s http://localhost:$BACKEND_PORT/api/sidecar/status 2>/dev/null) if echo "$sidecar_status" | grep -q '"ready":true'; then log_success "Sidecar (Whisper) ready" elif echo "$sidecar_status" | grep -q '"available":false'; then log_warn "Sidecar not available - transcription disabled" else log_info "Sidecar loading... (model may be downloading)" fi return 0 fi # Show progress every 10 seconds if [ $((waited % 10)) -eq 0 ]; then log_info "Still waiting... ($waited seconds)" fi done log_error "Backend failed to start. Check $PROJECT_DIR/backend-browser.log for details" exit 1 } # 函數:停止服務 stop_services() { log_info "Stopping services..." pkill -f "uvicorn app.main:app" 2>/dev/null || true sleep 1 log_success "Services stopped" } # 主程式 main() { echo "" echo "==========================================" echo " Meeting Assistant - Browser Mode" echo "==========================================" echo "" # Check environment check_environment # Start backend (which manages sidecar) start_backend # Give it a moment sleep 1 # Open browser local url="http://localhost:$BACKEND_PORT" open_browser "$url" echo "" echo "==========================================" log_success "Browser mode started!" echo "==========================================" echo "" echo " Access URL: $url" echo " API Docs: $url/docs" echo "" echo " Features:" echo " - 即時語音轉寫(透過後端 Sidecar)" echo " - 上傳音訊轉寫" echo " - AI 摘要" echo " - 匯出 Excel" echo "" echo " To stop: $0 stop" echo "" log_info "Press Ctrl+C to exit (backend will keep running)" echo "" # Keep script running trap 'echo ""; log_info "Exiting (backend still running)"; exit 0' INT TERM while true; do sleep 60 done } # 處理命令 case "${1:-start}" in start) main ;; stop) stop_services ;; restart) stop_services sleep 2 main ;; status) if check_port $BACKEND_PORT; then log_success "Backend running on port $BACKEND_PORT" curl -s http://localhost:$BACKEND_PORT/api/sidecar/status | python3 -m json.tool 2>/dev/null || echo "(Could not parse sidecar status)" else log_warn "Backend not running" fi ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 ;; esac