Some checks failed
Release / semantic-release (push) Successful in 31s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / build-linux (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
tests / Unit tests (Linux, Python 3.11) (push) Has been cancelled
The user chose Microsoft Edge TTS, voice ko-KR-HyunsuMultilingualNeural at rate +45% (~1.45x), as the natural Korean voice. Wire it into the bridge and make it the default engine. - bridge/server.py: _edge_synthesize() calls edge-tts and transcodes the MP3 to PCM16 mono WAV with the system ffmpeg (temp file for a correct header); TTS_ENGINE default -> edge; EDGE_TTS_VOICE / EDGE_TTS_RATE env-driven - requirements-bridge.txt: add edge-tts (lightweight; httpx) - compose/.env.example/README: TTS_ENGINE=edge + EDGE_TTS_* knobs; note the online/privacy trade-off (reply text is sent to Microsoft, needs internet) - drop the now-unused MeloTTS build layer (Dockerfile) and melo-worker (supervisord) — edge synthesises in-process, no model/worker baked, slimmer and faster image; settings UI engine list -> edge/piper, restart only bridge Verified on host: edge-tts -> ffmpeg yields a valid 16-bit mono 24kHz WAV; envsubst renders tts_engine=edge; docker build --check + 26 tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
237 lines
13 KiB
Plaintext
237 lines
13 KiB
Plaintext
# ============================================================================
|
||
# Javis Bot — environment configuration
|
||
# Copy to `.env` and fill in. Never commit your real `.env`.
|
||
# ============================================================================
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Discord bot (normal bot account) — voice I/O + slash commands
|
||
# ---------------------------------------------------------------------------
|
||
# OPTIONAL — leave BLANK to run in userbot/selfbot mode (a single user account
|
||
# does voice + broadcast; see DISCORD_SELFBOT_TOKEN below). When this is empty
|
||
# and a selfbot token is present, the app runs as a userbot automatically.
|
||
# Only fill this in if you specifically want the legacy normal-bot path.
|
||
# From https://discord.com/developers/applications → your app
|
||
DISCORD_BOT_TOKEN=
|
||
DISCORD_APP_ID=
|
||
# The (single) server this bot serves. Guild-scoped commands appear instantly.
|
||
DISCORD_GUILD_ID=
|
||
# Voice channel used by the stream-test scripts (bot/scripts/stream-test).
|
||
DISCORD_VOICE_CHANNEL_ID=
|
||
# Optional text channel for posting conversation transcripts (blank = disabled).
|
||
DISCORD_TRANSCRIPT_CHANNEL_ID=
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Brain bridge (Python service in bridge/) — STT + reply engine + TTS
|
||
# ---------------------------------------------------------------------------
|
||
BRIDGE_URL=http://127.0.0.1:8765
|
||
BRIDGE_HOST=127.0.0.1
|
||
BRIDGE_PORT=8765
|
||
JARVIS_BRAIN_ENABLED=1
|
||
JARVIS_TTS_ENABLED=1
|
||
# faster-whisper device/compute. GPU by default (RTX 5050 / sm_120, verified).
|
||
# Falls back to CPU automatically if no GPU is passed to the container.
|
||
WHISPER_DEVICE=cuda
|
||
WHISPER_COMPUTE_TYPE=float16
|
||
# Optional explicit Piper voice model (.onnx). If empty, the jarvis default is used.
|
||
TTS_PIPER_MODEL_PATH=
|
||
# TTS engine: "edge" (default) uses Microsoft Edge TTS, a natural Korean neural
|
||
# voice. Set to "piper" for the offline English voice. NOTE: edge is ONLINE —
|
||
# reply text is sent to Microsoft's servers and needs internet.
|
||
TTS_ENGINE=edge
|
||
# Edge voice + speaking rate. Rate is a percentage (+45% ≈ 1.45×). Korean voices:
|
||
# ko-KR-HyunsuMultilingualNeural (M), ko-KR-InJoonNeural (M), ko-KR-SunHiNeural (F).
|
||
EDGE_TTS_VOICE=ko-KR-HyunsuMultilingualNeural
|
||
EDGE_TTS_RATE=+45%
|
||
# Neural-only by default: if synthesis fails the bridge returns no audio rather
|
||
# than speaking Korean through the English Piper voice. Set to 1 to allow the
|
||
# Piper fallback.
|
||
MELO_FALLBACK_PIPER=0
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Jarvis brain (Ollama-backed). In Docker these populate the rendered
|
||
# config (docker/jarvis-config.template.json). See src/jarvis/config.py.
|
||
# ---------------------------------------------------------------------------
|
||
# In docker-compose this is overridden to http://ollama:11434 automatically.
|
||
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||
# qwen2.5:3b — small non-reasoning instruct model. ~2.4GB, runs 100% on the GPU
|
||
# (the 8B offloads ~8% to CPU), warm voice turns ~2-4s vs ~5-7s on 8B. Clean
|
||
# Korean on factual/tool replies; can occasionally leak a trailing CJK phrase on
|
||
# free-form chit-chat. Swap back to qwen3:8b for the strongest tool-calling.
|
||
OLLAMA_CHAT_MODEL=qwen2.5:3b
|
||
# Model for the auxiliary small-model calls: intent judge, tool router, weather
|
||
# place extraction, query decomposition. BLANK (default) reuses OLLAMA_CHAT_MODEL
|
||
# so the stack runs on one already-warm model. The code's built-in default
|
||
# (gemma4:e2b) is NOT pulled by this stack, so leaving this unset previously made
|
||
# every router/extractor call silently fail. Only set this if you also pull the
|
||
# model into Ollama.
|
||
OLLAMA_INTENT_MODEL=
|
||
OLLAMA_EMBED_MODEL=nomic-embed-text
|
||
WHISPER_MODEL=small
|
||
|
||
# Lock every reply to one language, e.g. OUTPUT_LANGUAGE=Korean. Leave BLANK to
|
||
# keep the default behaviour of replying in whatever language the user wrote in.
|
||
# A fixed value also suppresses stray characters from other scripts (e.g. the
|
||
# occasional trailing CJK fragment small models leak on free-form chat).
|
||
OUTPUT_LANGUAGE=
|
||
|
||
# Operator instruction folder: every *.md in this dir is appended to the main
|
||
# reply LLM's system prompt (filename order), re-read each turn so edits apply
|
||
# without a rebuild/restart. ./agents is bind-mounted here read-only; only
|
||
# change this to relocate the folder inside the container. See README "운영자 지시문".
|
||
AGENTS_DIR=/app/agents
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Docker desktop (VNC) — used only by the container image
|
||
# ---------------------------------------------------------------------------
|
||
# Host ports the container publishes the VNC + noVNC servers on. Defaults match
|
||
# the compose file (5901 / 6080); override if the host already uses them.
|
||
VNC_PORT=5901
|
||
NOVNC_PORT=6080
|
||
# VNC viewer password (max 8 chars effective). Watch the screen at localhost:5901.
|
||
# Also used by the broadcast keepalive: TigerVNC only refreshes its framebuffer
|
||
# while a VNC client is attached, so the stream keeps a tiny client connected to
|
||
# avoid a choppy (~1.5 fps) capture. Must match the VNC server's password. If
|
||
# unset, the keepalive falls back to the obfuscated passwd file (VNC_PASSWD_FILE,
|
||
# default ~/.config/tigervnc/passwd).
|
||
VNC_PASSWORD=javis123
|
||
# VNC_PASSWD_FILE=/home/claude/.config/tigervnc/passwd
|
||
# Auto-opened page in the in-container Chrome.
|
||
CHROME_START_URL=about:blank
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Screen-share + browser mode.
|
||
# true = the bot may go Live (screen-share the VNC desktop) and drive the
|
||
# on-screen browser for real-time info (search / play / read screen).
|
||
# false = no screen share; voice only, real-time info via the Gemini API.
|
||
STREAM_BROWSER=true
|
||
# Optional: profile dir for browser-based Google search in plain text turns
|
||
# (no active broadcast). When set, the search helper opens Chrome against this
|
||
# profile instead of a fresh anonymous one. Sign that profile into Google once
|
||
# (run a real Chrome with --user-data-dir=<this path> and log in) so Google
|
||
# treats later searches as a returning user and does not serve the bot-detection
|
||
# page. Leave blank to use an ephemeral headless session (works only where
|
||
# Google does not challenge it). Use a DEDICATED dir, not your everyday Chrome
|
||
# profile, to avoid the "profile in use" lock while Chrome is open.
|
||
CHROME_USER_DATA_DIR=
|
||
# Gemini auth for real-time info when STREAM_BROWSER=false.
|
||
# oauth = use the Gemini CLI with a Google-account login (no API key).
|
||
# Install once: npm i -g @google/gemini-cli ; then run `gemini` and
|
||
# "Sign in with Google". Uses the CLI's built-in web-search grounding.
|
||
# NOTE (2026-06): Google is blocking personal Google accounts on this
|
||
# path ("This client is no longer supported for Gemini Code Assist for
|
||
# individuals"). Workspace/org accounts may still work; personal
|
||
# accounts should use apikey below instead.
|
||
# apikey = REST path; needs GEMINI_API_KEY below
|
||
# (get one at https://aistudio.google.com/app/apikey). Recommended for
|
||
# personal Google accounts now that individual OAuth login is blocked.
|
||
# Either way, real-time search fail-opens to DDG/Brave/Wikipedia if Gemini is
|
||
# unavailable, so this is optional, not required.
|
||
GEMINI_AUTH=oauth
|
||
GEMINI_API_KEY=
|
||
GEMINI_MODEL=gemini-2.0-flash
|
||
# OAuth login source for Docker. The container mounts this into ~/.gemini.
|
||
# Default (blank) = ./docker/gemini-oauth (project-local, cross-platform). Seed
|
||
# it once: cp -r ~/.gemini/. docker/gemini-oauth/ (copy the whole login state).
|
||
# Or point at an existing host login instead, e.g. GEMINI_OAUTH_DIR=~/.gemini
|
||
GEMINI_OAUTH_DIR=
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# VNC screen broadcast
|
||
# selfbot = real live "Go Live" stream (needs a USER/burner token; ToS risk)
|
||
# novnc = share a noVNC browser link (safe, real-time, not native)
|
||
# screenshot = periodic screenshots to the channel (safe, low fps)
|
||
# none = disabled
|
||
# ---------------------------------------------------------------------------
|
||
STREAM_BACKEND=selfbot
|
||
|
||
# The VNC desktop runs on X display :1 (see docs/vnc-xfce-setup.md)
|
||
VNC_DISPLAY=:1
|
||
VNC_RESOLUTION=1920x1080
|
||
# 1080p60 broadcast. 8 Mbps suits 60fps (YouTube-style 1080p60 sits ~8-12 Mbps);
|
||
# drop to 30/4000 for a lighter stream. Max bitrate is 1.5x this value.
|
||
VNC_FRAMERATE=60
|
||
VNC_BITRATE_KBPS=8000
|
||
|
||
# --- selfbot backend ---
|
||
# A THROWAWAY/burner Discord user account token. NEVER your main account.
|
||
# Using a selfbot violates Discord ToS and can get the account banned.
|
||
DISCORD_SELFBOT_TOKEN=
|
||
# Dedicated burner account for the Go-Live BROADCAST, separate from the
|
||
# conversation account above. REQUIRED in userbot mode for the broadcast to
|
||
# work: Discord allows only one voice presence per account, so the conversation
|
||
# and the broadcast cannot share one account (the broadcaster's voice connection
|
||
# never connects). Leave empty in normal-bot mode (the conversation runs on the
|
||
# bot account, so the selfbot account is already broadcast-only). Both burner
|
||
# accounts must be in the server. Use a second throwaway account, never a main.
|
||
DISCORD_STREAM_TOKEN=
|
||
# Hardware (NVENC) encode for the stream. 1 = use the GPU (recommended for
|
||
# 1080p60), 0 = software x264. Requires an NVIDIA GPU + ffmpeg built with nvenc.
|
||
STREAM_HW=1
|
||
# Capture desktop audio into the broadcast so the stream has sound. 1 = on,
|
||
# 0 = mute. Pulls the PipeWire/Pulse monitor of the default sink; override the
|
||
# source with STREAM_AUDIO_SOURCE (e.g. a specific "<sink>.monitor").
|
||
STREAM_AUDIO=1
|
||
STREAM_AUDIO_SOURCE=@DEFAULT_MONITOR@
|
||
|
||
# --- novnc backend ---
|
||
# e.g. http://192.168.10.9:6080/vnc.html (websockify --web=/usr/share/novnc 6080 localhost:5901)
|
||
NOVNC_URL=
|
||
|
||
# --- screenshot backend ---
|
||
SCREENSHOT_INTERVAL_SEC=5
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Voice behaviour
|
||
# ---------------------------------------------------------------------------
|
||
# Silence (ms) that marks the end of an utterance before sending to the brain.
|
||
VOICE_SILENCE_MS=800
|
||
|
||
# ===========================================================================
|
||
# Split deployment & cross-platform (Ubuntu + Windows 11)
|
||
# ===========================================================================
|
||
# JARVIS_ROLE selects what this machine runs (see docker/run-if-role.sh):
|
||
# full (default) everything in one container
|
||
# browser ONLY the desktop + Chrome + control-server (driven over the LAN)
|
||
# bot ONLY the bot + bridge + TTS (drives a REMOTE browser)
|
||
JARVIS_ROLE=full
|
||
|
||
# --- GPU per OS: pick the matching compose override via COMPOSE_FILE ---
|
||
# IMPORTANT: the file separator is OS-specific. Linux/macOS use ":" (colon);
|
||
# Windows uses ";" (semicolon), because ":" is taken by the drive letter (C:).
|
||
# Using the wrong one makes Docker treat the whole string as a single missing
|
||
# filename ("...gpu-windows.yml: The system cannot find the file specified").
|
||
# Ubuntu / macOS (nvidia-container-toolkit / CDI):
|
||
# COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml
|
||
# Windows 11 (Docker Desktop + WSL2 + NVIDIA) — note the ";" separator:
|
||
# COMPOSE_FILE=docker-compose.yml;docker-compose.gpu-windows.yml
|
||
# Browser-only host (no GPU needed): leave COMPOSE_FILE unset (base only).
|
||
# Default below is the Linux form; Windows users must change ":" to ";" AND
|
||
# swap gpu-linux for gpu-windows. If unsure, comment this out and pass the
|
||
# files explicitly: docker compose -f docker-compose.yml -f <gpu-override> ...
|
||
COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml
|
||
|
||
# --- Browser HOST (JARVIS_ROLE=browser) — e.g. this LAN machine ---
|
||
# Expose Chrome control to the internal network (no auth, internal only):
|
||
# CDP_BIND=0.0.0.0
|
||
# BROWSER_CONTROL_BIND=0.0.0.0
|
||
# CDP_PUBLISH_BIND=0.0.0.0
|
||
# Defaults are loopback-only.
|
||
|
||
# --- BOT host (JARVIS_ROLE=bot) — e.g. your PC driving the remote browser ---
|
||
# Point the controlBrowser tool at the browser host's control-server:
|
||
# BROWSER_CONTROL_URL=http://192.168.10.9:8777
|
||
# (Leave BROWSER_CONTROL_URL empty on full/browser layouts.)
|
||
|
||
# --- Models (tune per machine) ---
|
||
# OLLAMA_CHAT_MODEL=qwen2.5:7b # quality (needs ~5GB VRAM + whisper small)
|
||
# OLLAMA_CHAT_MODEL=qwen2.5:3b # speed (fits easily, faster on 8GB GPUs)
|
||
# WHISPER_MODEL=small # small frees VRAM for a bigger LLM; medium=more accurate
|
||
# MELO_DEVICE=cuda # cpu if no GPU on the bot host
|
||
|
||
# --- Settings web UI (http://localhost:8765/settings on the bot host) ---
|
||
# To reach it, expose the bridge to the host loopback:
|
||
# BRIDGE_HOST=0.0.0.0
|
||
# SETTINGS_PUBLISH_BIND=127.0.0.1 # 0.0.0.0 to allow LAN access (no auth)
|
||
# Change models / STT / TTS speed / language / LLM instructions live; "적용"
|
||
# restarts the bridge + TTS worker so changes take effect.
|