fix docker port
This commit is contained in:
@@ -91,8 +91,10 @@ POSTGRES_PORT=45432
|
||||
# DEMO_ORCHESTRATOR_RTSP_PORT=18554
|
||||
# 联调台 HLS 预览(MediaMTX 8888 映射到宿主机端口;API 反代给浏览器)
|
||||
# DEMO_HLS_PREVIEW_PORT=18888
|
||||
# API 在 Docker 内时设为 host.docker.internal
|
||||
# API 在 Docker 内访问宿主机 HLS:host.docker.internal(docker -p 会自动绑定 127.0.0.1)
|
||||
# DEMO_HLS_PREVIEW_HOST=127.0.0.1
|
||||
# 可选:显式指定 docker -p 绑定地址(一般留空)
|
||||
# DEMO_HLS_PREVIEW_BIND_HOST=127.0.0.1
|
||||
# Docker 内 API 访问宿主机假流时写入站点 JSON 的主机名(默认 host.docker.internal)
|
||||
# DOCKER_DEMO_ORCHESTRATOR_RTSP_JSON_HOST=host.docker.internal
|
||||
# 链路 2 simulated-start / fake_rtsp_from_file 起 MediaMTX 容器用
|
||||
|
||||
@@ -36,7 +36,11 @@ from app.schemas import (
|
||||
build_consumption_summary,
|
||||
)
|
||||
from app.services.recording_live import accept_live_recording
|
||||
from app.services.hls_preview import HlsPreviewManager, fetch_hls_upstream
|
||||
from app.services.hls_preview import (
|
||||
HlsPreviewManager,
|
||||
docker_publish_bind_host,
|
||||
fetch_hls_upstream,
|
||||
)
|
||||
from app.services.rtsp_preview import capture_rtsp_jpeg_frame
|
||||
from app.services.surgery_pipeline import SurgeryPipeline
|
||||
from app.services.video.backend_resolver import BackendResolver
|
||||
@@ -213,6 +217,10 @@ async def hls_preview_ensure(
|
||||
)
|
||||
hls_host = (settings.demo_hls_preview_host or "127.0.0.1").strip() or "127.0.0.1"
|
||||
hls_port = int(settings.demo_hls_preview_port)
|
||||
bind_host = docker_publish_bind_host(
|
||||
hls_host,
|
||||
explicit_bind=(settings.demo_hls_preview_bind_host or "").strip(),
|
||||
)
|
||||
|
||||
resolver = BackendResolver(settings, hikvision_runtime=None)
|
||||
sources: dict[str, str] = {}
|
||||
@@ -238,6 +246,7 @@ async def hls_preview_ensure(
|
||||
sources=sources,
|
||||
hls_host=hls_host,
|
||||
hls_port=hls_port,
|
||||
bind_host=bind_host,
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -190,7 +190,13 @@ class Settings(BaseSettings):
|
||||
demo_hls_preview_port: int = Field(default=18888, ge=1, le=65535)
|
||||
demo_hls_preview_host: str = Field(
|
||||
default="127.0.0.1",
|
||||
description="MediaMTX HLS 监听地址;API 反代目标。容器内 API 可设为 host.docker.internal。",
|
||||
description="API 反代访问的 MediaMTX HLS 地址;容器内 API 可设为 host.docker.internal。",
|
||||
)
|
||||
demo_hls_preview_bind_host: str = Field(
|
||||
default="",
|
||||
description=(
|
||||
"docker run -p 绑定到宿主机的地址;留空时 host.docker.internal/localhost 自动用 127.0.0.1。"
|
||||
),
|
||||
)
|
||||
|
||||
#: 视觉管线记账默认 ``doctor_id``(TSV 未提供医生列时的回退);语音确认仍为独立常量 ``voice``。
|
||||
|
||||
@@ -22,6 +22,20 @@ from app.services.synthetic_rtsp import MEDIAMTX_IMAGE
|
||||
CONTAINER_NAME_PREFIX = "orm-hls-preview-"
|
||||
_MEDIAMTX_HLS_INTERNAL_PORT = 8888
|
||||
_PATH_SAFE = re.compile(r"[^a-zA-Z0-9._-]+")
|
||||
# docker -p 只接受 IP/0.0.0.0,不能写 host.docker.internal
|
||||
_DOCKER_PUBLISH_ALIAS_HOSTS = frozenset(
|
||||
{"host.docker.internal", "host.containers.internal", "localhost"}
|
||||
)
|
||||
|
||||
|
||||
def docker_publish_bind_host(hls_host: str, *, explicit_bind: str = "") -> str:
|
||||
"""``docker run -p <bind>:port`` 用的宿主机地址;与 API 反代用的 ``hls_host`` 可不同。"""
|
||||
if (explicit_bind or "").strip():
|
||||
return explicit_bind.strip()
|
||||
h = (hls_host or "").strip().lower()
|
||||
if h in _DOCKER_PUBLISH_ALIAS_HOSTS:
|
||||
return "127.0.0.1"
|
||||
return (hls_host or "").strip() or "127.0.0.1"
|
||||
|
||||
|
||||
def sanitize_mediamtx_path(name: str) -> str:
|
||||
@@ -107,6 +121,7 @@ class HlsPreviewManager:
|
||||
sources: dict[str, str],
|
||||
hls_host: str,
|
||||
hls_port: int,
|
||||
bind_host: str | None = None,
|
||||
ready_timeout_sec: float = 30.0,
|
||||
) -> HlsPreviewSession:
|
||||
"""链路 1:独立 MediaMTX 容器按路径拉取各 RTSP。"""
|
||||
@@ -129,6 +144,7 @@ class HlsPreviewManager:
|
||||
cfg = work / "mediamtx.yml"
|
||||
_write_mediamtx_config(cfg, mtx_paths)
|
||||
|
||||
publish_host = docker_publish_bind_host(hls_host, explicit_bind=bind_host or "")
|
||||
container = CONTAINER_NAME_PREFIX + uuid.uuid4().hex[:12]
|
||||
cmd = [
|
||||
"docker",
|
||||
@@ -139,7 +155,7 @@ class HlsPreviewManager:
|
||||
"-v",
|
||||
f"{cfg.resolve()}:/mediamtx.yml:ro",
|
||||
"-p",
|
||||
f"{hls_host}:{hls_port}:{_MEDIAMTX_HLS_INTERNAL_PORT}",
|
||||
f"{publish_host}:{hls_port}:{_MEDIAMTX_HLS_INTERNAL_PORT}",
|
||||
MEDIAMTX_IMAGE,
|
||||
]
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
||||
@@ -164,9 +180,11 @@ class HlsPreviewManager:
|
||||
)
|
||||
cls._active = sess
|
||||
logger.info(
|
||||
"HLS preview (pull) started container={} cameras={} hls=http://{}:{}/",
|
||||
"HLS preview (pull) started container={} cameras={} publish={}:{} upstream=http://{}:{}/",
|
||||
container,
|
||||
list(path_by_camera),
|
||||
publish_host,
|
||||
hls_port,
|
||||
hls_host,
|
||||
hls_port,
|
||||
)
|
||||
|
||||
@@ -10,7 +10,11 @@ from fastapi.testclient import TestClient
|
||||
|
||||
from app.api import router as api_router
|
||||
from app.config import Settings
|
||||
from app.services.hls_preview import HlsPreviewManager, HlsPreviewSession
|
||||
from app.services.hls_preview import (
|
||||
HlsPreviewManager,
|
||||
HlsPreviewSession,
|
||||
docker_publish_bind_host,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -28,6 +32,12 @@ def hls_client(tmp_path) -> TestClient:
|
||||
HlsPreviewManager.stop()
|
||||
|
||||
|
||||
def test_docker_publish_bind_host_maps_docker_internal() -> None:
|
||||
assert docker_publish_bind_host("host.docker.internal") == "127.0.0.1"
|
||||
assert docker_publish_bind_host("127.0.0.1") == "127.0.0.1"
|
||||
assert docker_publish_bind_host("host.docker.internal", explicit_bind="0.0.0.0") == "0.0.0.0"
|
||||
|
||||
|
||||
def test_hls_preview_ensure_pull(hls_client: TestClient) -> None:
|
||||
fake_sess = HlsPreviewSession(
|
||||
hls_host="127.0.0.1",
|
||||
|
||||
@@ -67,8 +67,8 @@ SDK **不作为构建期依赖**:将厂商提供的 Linux x86_64 动态库挂
|
||||
| **链路 2**(模拟实时) | 不使用 HLS/RTSP 预览;联调台在各路槽位用本地 `<video>` 预览所选文件 |
|
||||
|
||||
- 播放地址形如:`GET /internal/demo/hls-preview/{camera_id}/index.m3u8`(playlist 内分片 URL 会重写为 API 路径)。
|
||||
- **API 在 Docker 内**时须设 `DEMO_HLS_PREVIEW_HOST=host.docker.internal`(compose 已默认),且宿主机需有 **docker** CLI 供拉流模式起 MediaMTX。
|
||||
- 环境变量:`DEMO_HLS_PREVIEW_PORT`(默认 18888)、`DEMO_HLS_PREVIEW_HOST`(本机默认 `127.0.0.1`)。
|
||||
- **API 在 Docker 内**时设 `DEMO_HLS_PREVIEW_HOST=host.docker.internal`(compose 已默认):API 经该主机名访问宿主机上的 HLS;`docker run -p` 会自动绑定 `127.0.0.1:18888`(不能写 `host.docker.internal` 作 `-p` 地址)。
|
||||
- 环境变量:`DEMO_HLS_PREVIEW_PORT`(默认 18888)、`DEMO_HLS_PREVIEW_HOST`(反代上游)、可选 `DEMO_HLS_PREVIEW_BIND_HOST`(显式 `-p` 绑定,一般留空)。
|
||||
|
||||
单帧 JPEG 预览仍保留:`GET /internal/demo/rtsp-preview/{camera_id}/frame.jpg`(不依赖 MediaMTX)。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user