start_server.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/bash
# Speech-to-Text Start Script (Linux & macOS)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
VENV_PYTHON="$SCRIPT_DIR/.venv/bin/python3"
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Show current version + update status (git) — like update_server.sh. The app
# applies any pending update itself on startup (server.log); this just surfaces it.
if command -v git >/dev/null 2>&1 && git -C "$SCRIPT_DIR" rev-parse --git-dir >/dev/null 2>&1; then
echo -e "${GREEN}[GIT]${NC} $(git -C "$SCRIPT_DIR" rev-parse --abbrev-ref HEAD) @ $(git -C "$SCRIPT_DIR" log --oneline -1)"
UPSTREAM=$(git -C "$SCRIPT_DIR" rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null)
if [ -n "$UPSTREAM" ]; then
git -C "$SCRIPT_DIR" fetch --quiet 2>/dev/null
BEHIND=$(git -C "$SCRIPT_DIR" rev-list --count "HEAD..$UPSTREAM" 2>/dev/null || echo 0)
if [ "${BEHIND:-0}" -gt 0 ]; then
echo -e "${YELLOW}[GIT]${NC} Update available: $BEHIND commit(s) behind $UPSTREAM — applied on startup"
else
echo -e "${GREEN}[GIT]${NC} Up to date with $UPSTREAM"
fi
fi
fi
# Determine Python binary
if [ -f "$VENV_PYTHON" ]; then
PYTHON_BIN="$VENV_PYTHON"
else
PYTHON_BIN="python3"
fi
# The config the server reads, and the port it binds, from stt/server_port.py — the
# invoking user's under sudo, never root's (see restart_server.sh).
# -B: run as root, a helper must not leave root-owned __pycache__ in the checkout.
DATA_DIR=$(PYTHONPATH="$SCRIPT_DIR" "$PYTHON_BIN" -B -m stt.server_port --data-dir 2>/dev/null)
[ -n "$DATA_DIR" ] || DATA_DIR="${STT_DATA_DIR:-$HOME/.stt}"
PORT=$(STT_DATA_DIR="$DATA_DIR" PYTHONPATH="$SCRIPT_DIR" "$PYTHON_BIN" -B -m stt.server_port 2>/dev/null || echo 8080)
# Claim a port only once the server answers on it, rather than the one this script guessed.
report_started() {
if command -v curl >/dev/null 2>&1; then
for _ in $(seq 1 30); do
if curl -s -o /dev/null --max-time 2 "http://127.0.0.1:$PORT/" 2>/dev/null; then
echo -e "${GREEN}[OK]${NC} Server started ($1) on port $PORT"
return 0
fi
sleep 1
done
echo -e "${YELLOW}[WARNING]${NC} Server started ($1), but nothing answered on port $PORT yet — check the log"
return 0
fi
echo -e "${GREEN}[OK]${NC} Server started ($1); expected on port $PORT"
}
# Check if already running
if pgrep -f "speech_to_text\.py" > /dev/null 2>&1; then
echo -e "${YELLOW}[WARNING]${NC} Server is already running"
echo "Use ./restart_server.sh to restart or ./stop_server.sh to stop"
exit 1
fi
# Check if port is in use
if command -v fuser &> /dev/null && fuser "$PORT/tcp" 2>/dev/null; then
echo -e "${RED}[ERROR]${NC} Port $PORT is already in use by another process"
exit 1
elif command -v lsof &> /dev/null && lsof -i :"$PORT" -sTCP:LISTEN > /dev/null 2>&1; then
echo -e "${RED}[ERROR]${NC} Port $PORT is already in use by another process"
exit 1
fi
# ─── Optional dependency preflight ──────────────────────────────────
# requirements.txt deliberately omits a few large, rarely-used packages (see the
# commented block at its end), so the hash-gated sync in update_server.sh can never
# notice one *missing* — it installs what that file lists, and these are not in it.
# A rebuilt venv therefore dropped llama-cpp-python silently, and live translation
# degraded to handing every caption back untranslated with HTTP 200. This asks the
# question that sync cannot: does the venv have what the live config is asking it to
# do? Best-effort and always exits 0 — a missing optional package degrades one
# feature, a start script that refuses to start degrades everything.
# Set STT_SKIP_DEP_CHECK=1 to skip it.
if [ -z "$STT_SKIP_DEP_CHECK" ] && [ -f "$VENV_PYTHON" ]; then
PYTHONPATH="$SCRIPT_DIR" "$VENV_PYTHON" -B -m stt.optional_deps --repo-dir "$SCRIPT_DIR" --data-dir "$DATA_DIR" 2>&1
fi
OS=$(uname -s)
if [ "$OS" = "Linux" ]; then
# Linux: try systemd first
for service_name in stt-server stt; do
if systemctl list-unit-files "${service_name}.service" 2>/dev/null | grep -q "$service_name"; then
echo "Starting via systemd ($service_name)..."
sudo systemctl start "$service_name"
sleep 2
if systemctl is-active --quiet "$service_name"; then
report_started "systemd: $service_name"
echo "View logs: sudo journalctl -u $service_name -f"
exit 0
fi
fi
done
fi
# macOS launchd check
if [ "$OS" = "Darwin" ]; then
if launchctl list com.stt.server &> /dev/null; then
echo "Starting via launchd..."
launchctl start com.stt.server
sleep 2
report_started "launchd: com.stt.server"
echo "View logs: tail -f $SCRIPT_DIR/server.log"
exit 0
fi
fi
# Fallback: start manually
echo "Starting server on port $PORT..."
if [ "$PORT" -le 1024 ] && [ "$EUID" -ne 0 ]; then
echo -e "${YELLOW}[WARNING]${NC} Port $PORT requires root. Running with sudo..."
# STT_DATA_DIR: a root server would otherwise read /root/.stt — a different config,
# models and sessions, and so possibly not the port printed above.
sudo env STT_DATA_DIR="$DATA_DIR" STT_MANAGED=0 nohup "$PYTHON_BIN" "$SCRIPT_DIR/speech_to_text.py" > "$SCRIPT_DIR/server.log" 2>&1 &
else
nohup "$PYTHON_BIN" "$SCRIPT_DIR/speech_to_text.py" > "$SCRIPT_DIR/server.log" 2>&1 &
fi
sleep 3
if pgrep -f "speech_to_text\.py" > /dev/null; then
report_started "manual"
echo "View logs: tail -f $SCRIPT_DIR/server.log"
else
echo -e "${RED}[ERROR]${NC} Server failed to start. Check server.log"
exit 1
fi