# SmartMeeting SmartMeeting is a Docker Compose deployment for Speakr, FunASR Paraformer ASR, speaker embedding extraction, and the realtime WebSocket bridge. ## Directory Layout ```text /storage01/home/xll/202607/voice ├── docker-compose.yml # Main Compose file ├── config.env # Runtime configuration to edit ├── asr/main.py # ASR adapter service code ├── speakr/ # Speakr frontend/backend code ├── voice-dected/ # Speaker embedding service code ├── fastapi_wss/ # Realtime WebSocket bridge code └── deploy/data/ # Runtime data, ignored by git ``` ## Start And Stop Run all services: ```bash cd /storage01/home/xll/202607/voice docker compose up -d ``` Check status and logs: ```bash docker compose ps docker compose logs -f ``` Stop services: ```bash docker compose down ``` ## Services And Ports | Service | Container | Port | Purpose | | --- | --- | --- | --- | | Speakr | `voice-speakr` | `8899` | Web UI and backend | | ASR | `asr-test` | `59805` | Paraformer HTTP and WebSocket ASR | | Speaker embedding | `voice-dected` | `18000` | `/extract_embedding` voiceprint service | | Realtime bridge | `fastapi-wss` | `10095` | Browser realtime ASR WebSocket bridge | | Redis | `voice-redis` | `16380` | Cache/session storage for realtime bridge | Main access URL: ```text http://192.168.0.46:8899/tool/speakr/ ``` For browser microphone recording, use a secure context. The quickest local workaround is an SSH tunnel: ```bash ssh -L 8899:127.0.0.1:8899 xll@192.168.0.46 ``` Then open: ```text http://localhost:8899/tool/speakr/ ``` ## Configuration Most runtime settings are in: ```text /storage01/home/xll/202607/voice/config.env ``` Edit this file first when changing service addresses, model endpoints, LLM settings, or speaker matching behavior. After editing: ```bash cd /storage01/home/xll/202607/voice docker compose up -d ``` Important variables: ```env ASR_BASE_URL=http://asr-test:59805 TARGET_WS_URL=ws://asr-test:59805/ws/asr VOICE_DETECTED_URL=http://voice-dected:8000 SPEAKER_DET_URL=http://voice-dected:8000/extract_embedding REDIS_URL=redis://redis:6379/0 TEXT_MODEL_BASE_URL=http://192.168.0.46:59800/v1 TEXT_MODEL_NAME=46-qwen3.5-35B TEXT_MODEL_API_KEY=none VOICEPRINT_STORE=/data/asr_voiceprints.json VOICEPRINT_MATCH_THRESHOLD=0.45 ``` Notes: - Inside Docker Compose, use service names such as `asr-test`, `voice-dected`, and `redis`. - From outside Docker, use host ports such as `192.168.0.46:59805`, `192.168.0.46:18000`, and `192.168.0.46:10095`. - `VOICEPRINT_MATCH_THRESHOLD` controls how strict speaker matching is. Lower values match more easily; higher values reduce false matches. ## Runtime Data Runtime data is stored under: ```text /storage01/home/xll/202607/voice/deploy/data/ ``` Important subdirectories: ```text deploy/data/speakr/uploads/ # Uploaded/recorded audio deploy/data/speakr/instance/ # Speakr SQLite database deploy/data/asr/ # ASR voiceprint store deploy/data/redis/ # Redis persistence ``` These files are ignored by git. ## Voiceprint Flow Speakr calls the ASR adapter for voiceprint platform compatibility: ```text POST /voice_insert GET /get_voice_name DELETE /delete_voice ``` The ASR adapter stores embeddings in: ```text deploy/data/asr/asr_voiceprints.json ``` During `/asr` transcription, the adapter converts uploaded audio to 16 kHz mono WAV, calls `voice-dected`, compares the embedding with stored voiceprints, and returns a matched speaker name when the similarity passes the threshold. ## Useful Checks ```bash curl http://127.0.0.1:59805/health curl http://127.0.0.1:59805/get_voice_name curl http://127.0.0.1:8899/tool/speakr/api/config ``` WebSocket check: ```bash docker exec -it fastapi-wss python - <<'PY' import asyncio, json, websockets async def main(): async with websockets.connect("ws://127.0.0.1:10095") as ws: await ws.send(json.dumps({"mode": "2pass", "is_speaking": True})) await ws.send(json.dumps({"type": "stop", "is_speaking": False})) print(await ws.recv()) asyncio.run(main()) PY ```