feat: 语音确认、联调与运维增强

- 语音:序数解析(第一个/第二个等)、解析失败计数与 API detail.retry_remaining;
  百度 ASR 固定 dev_pid 为普通话;SurgeryPipelineError 支持 extra 并入 HTTP detail。
- Demo:demo 路由与假 RTSP、客户端 index 与 README;BackendResolver 与配置调整。
- 可观测:消耗 TSV 日志、语音文件日志、终端 Markdown 辅助;相关测试与依赖更新。
- 注意:.env 仍被 gitignore,本地密钥不会进入本提交。

Made-with: Cursor
This commit is contained in:
Kevin
2026-04-23 14:24:20 +08:00
parent 42720f81cf
commit 0c05463617
39 changed files with 3030 additions and 143 deletions

View File

@@ -1,10 +1,11 @@
# Local development stack. You can either:
# 1. run `docker compose -f docker-compose.dev.yml up --build` for API + DB in containers, or
# 2. run `./start.sh` to start only DB and keep the API on the host with hot reload.
# 本地仅起 PostgreSQL + MinIOFastAPI 在宿主机跑(如 ./start.sh、uv run uvicorn
#
# Default host ports avoid common 5432/8000 clashes when many services run in parallel:
# Postgres published: POSTGRES_PORT -> 35432 (container still listens on 5432)
# API published: API_PORT -> 38080 (uvicorn inside container still listens on 8000)
# docker compose -f docker-compose.dev.yml up -d
#
# 默认端口避开工区常见占用:
# Postgres: 宿主机 ${POSTGRES_PORT:-35432} -> 容器 5432
# MinIO API: 9000控制台: 9001
services:
db:
image: postgres:16-alpine
@@ -23,57 +24,19 @@ services:
retries: 20
start_period: 5s
api:
build:
context: .
dockerfile: Dockerfile
# S3 兼容:语音确认原始 WAV与本项目 .env 中 MINIO_ACCESS_KEY / MINIO_SECRET_KEY 一致
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-operation_room}
POSTGRES_HOST: db
POSTGRES_PORT: 5432
CONSUMABLE_CLASSIFIER_IMGSZ: ${CONSUMABLE_CLASSIFIER_IMGSZ:-224}
CONSUMABLE_CLASSIFIER_DEVICE: ${CONSUMABLE_CLASSIFIER_DEVICE:-}
CONSUMABLE_CLASSIFIER_TOPK: ${CONSUMABLE_CLASSIFIER_TOPK:-5}
CONSUMABLE_MIN_CLS_CONFIDENCE: ${CONSUMABLE_MIN_CLS_CONFIDENCE:-0.5}
CONSUMABLE_VISION_WINDOW_SEC: ${CONSUMABLE_VISION_WINDOW_SEC:-15}
CONSUMABLE_CATALOG_XLSX_PATH: ${CONSUMABLE_CATALOG_XLSX_PATH:-}
HAND_DETECTION_WEIGHTS: ${HAND_DETECTION_WEIGHTS:-}
HAND_DETECTION_IMGSZ: ${HAND_DETECTION_IMGSZ:-640}
HAND_DETECTION_DEVICE: ${HAND_DETECTION_DEVICE:-}
VIDEO_DEFAULT_BACKEND: ${VIDEO_DEFAULT_BACKEND:-rtsp}
VIDEO_RTSP_URL_TEMPLATE: ${VIDEO_RTSP_URL_TEMPLATE:-}
VIDEO_RTSP_URLS_JSON_FILE: ${VIDEO_RTSP_URLS_JSON_FILE:-}
VIDEO_RTSP_URLS_JSON: ${VIDEO_RTSP_URLS_JSON:-}
VIDEO_CAMERA_BACKEND_OVERRIDES_JSON: ${VIDEO_CAMERA_BACKEND_OVERRIDES_JSON:-}
HIKVISION_SDK_ENABLED: ${HIKVISION_SDK_ENABLED:-false}
HIKVISION_LIB_DIR: ${HIKVISION_LIB_DIR:-/opt/hikvision/lib}
HIKVISION_DEVICE_IP: ${HIKVISION_DEVICE_IP:-}
HIKVISION_USER: ${HIKVISION_USER:-}
HIKVISION_PASSWORD: ${HIKVISION_PASSWORD:-}
HIKVISION_PREVIEW_RTSP_TEMPLATE: ${HIKVISION_PREVIEW_RTSP_TEMPLATE:-}
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
ports:
- "${API_PORT:-38080}:8000"
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
- "${MINIO_PORT:-9000}:9000"
- "${MINIO_CONSOLE_PORT:-9001}:9001"
volumes:
- ./app:/app/app
- ./main.py:/app/main.py
depends_on:
db:
condition: service_healthy
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)",
]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
- minio_data_dev:/data
volumes:
pgdata_dev:
minio_data_dev: