From 4a8641571fa5c6881a70fdb728ad4b45d8ce8fbf Mon Sep 17 00:00:00 2001 From: lzh Date: Wed, 29 Apr 2026 11:02:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(video):=20Release=20=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E7=8B=AC=E7=AB=8B=20ZLM=20+=20video-server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 zlmediakit-release 容器(host 网络) - 添加 video-server 连接本地 ZLM - ZLM HTTP 7080 / RTSP 7554 / RTMP 7935 / RTP 30000-30500 - Hook URL 指向 127.0.0.1:48093 (video-server) - SIP ID 末位 02 与 Prod 区分 - Secret 统一使用 u3UapOhmZa9er7S37Hc2k695NlZOBYdB Co-Authored-By: Claude Opus 4.7 --- docker-compose.release.yml | 68 +++++++++ docker-compose/zlm-config-release.ini | 201 ++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 docker-compose/zlm-config-release.ini diff --git a/docker-compose.release.yml b/docker-compose.release.yml index b0eb75ad..fcc1d4d6 100644 --- a/docker-compose.release.yml +++ b/docker-compose.release.yml @@ -20,6 +20,7 @@ networks: volumes: app-logs: + zlm-data: # ZLM 录像存储 # ============================================ # 公共环境变量片段(YAML anchor) @@ -236,3 +237,70 @@ services: depends_on: viewsh-module-iot-server: condition: service_healthy + + # ===== ZLMediaKit 媒体服务器(Release 环境独立部署) ===== + zlmediakit: + image: zlmediakit/zlmediakit:master + container_name: zlmediakit-release + restart: on-failure:5 + network_mode: host # 使用宿主机网络,简化 RTP 端口映射 + environment: + TZ: Asia/Shanghai + volumes: + - ./docker-compose/zlm-config-release.ini:/opt/media/conf/config.ini:ro + - zlm-data:/opt/media/bin/www # 录像持久化 + deploy: + resources: + limits: + memory: 512m + cpus: '0.5' + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:7080/index/api/api_summary"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + + # ===== Video 视频模块(连接本地 ZLM) ===== + viewsh-module-video-server: + image: ${REGISTRY_HOST:-172.17.16.7:5000}/viewsh-module-video-server:${IMAGE_TAG:-latest} + container_name: aiot-video-server-release + restart: on-failure:5 + ports: + - "48093:48093" # 应用端口 + - "5060:5060" # SIP UDP/TCP(设备注册) + - "5060:5060/udp" + - "9905:9905" # XXL-Job executor + environment: + <<: *common-env + JAVA_OPTS: "-Xms512m -Xmx1024m -XX:+UseContainerSupport -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs" + XXL_JOB_EXECUTOR_PORT: 9905 + + # ===== SIP 配置(Release 环境独立 SIP ID) ===== + SIP_ID: "44010200492000000002" + SIP_DOMAIN: "4401020049" + + # ===== ZLMediaKit 连接配置(连接本地 host 网络 ZLM) ===== + ZLM_SERVER_ID: "zlmediakit-release" + ZLM_IP: "127.0.0.1" # host 网络,直接用宿主机地址 + ZLM_HTTP_PORT: "7080" # ZLM HTTP 端口(避免与宿主机 80 冲突) + ZLM_SECRET: "u3UapOhmZa9er7S37Hc2k695NlZOBYdB" + ZLM_AUTO_CONFIG: "true" + volumes: + - app-logs:/app/logs + deploy: + resources: + limits: + memory: 1536m + cpus: '1.0' + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:48093/actuator/health"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 120s + depends_on: + viewsh-module-ops-server: + condition: service_healthy + zlmediakit: + condition: service_healthy diff --git a/docker-compose/zlm-config-release.ini b/docker-compose/zlm-config-release.ini new file mode 100644 index 00000000..eba4c343 --- /dev/null +++ b/docker-compose/zlm-config-release.ini @@ -0,0 +1,201 @@ +; ZLMediaKit 配置文件 - Release 环境(172.17.16.7) +; 最后更新: 2026-04-29 +; 与 Prod ZLM 完全隔离,Hook 指向本地 video-server + +[api] +apiDebug=0 +defaultSnap=./www/logo.png +downloadRoot=./www +secret=u3UapOhmZa9er7S37Hc2k695NlZOBYdB +snapRoot=./www/snap/ + +[cluster] +origin_url= +retry_count=3 +timeout_sec=15 + +[ffmpeg] +bin=/usr/bin/ffmpeg +cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s +log=./ffmpeg/ffmpeg.log +restart_sec=0 +snap=%s -rtsp_transport tcp -i %s -y -f mjpeg -frames:v 1 %s + +[general] +broadcast_player_count_changed=0 +check_nvidia_dev=0 +enableVhost=0 +enable_ffmpeg_log=0 +flowThreshold=1024 +listen_ip=:: +maxStreamWaitMS=15000 +mediaServerId=zlmediakit-release +mergeWriteMS=0 +resetWhenRePlay=1 +streamNoneReaderDelayMS=20000 +unready_frame_cache=100 +wait_add_track_ms=3000 +wait_audio_track_data_ms=1000 +wait_track_ready_ms=10000 + +[hls] +broadcastRecordTs=0 +deleteDelaySec=10 +fastRegister=0 +fileBufSize=65536 +segDelay=0 +segDur=2 +segKeep=0 +segNum=3 +segRetain=5 + +[hook] +alive_interval=30.000000 +enable=1 +on_flow_report= +on_http_access= +; ===== Hook URL - 指向 video-server ===== +; ZLM 使用 host 网络,video-server 端口映射到宿主机 +; 所以用 127.0.0.1 + 映射端口 48093 +on_play=http://127.0.0.1:48093/index/hook/on_play +on_publish=http://127.0.0.1:48093/index/hook/on_publish +on_record_mp4=http://127.0.0.1:48093/index/hook/on_record_mp4 +on_record_ts= +on_rtp_server_timeout=http://127.0.0.1:48093/index/hook/on_rtp_server_timeout +on_rtsp_auth= +on_rtsp_realm= +on_send_rtp_stopped=http://127.0.0.1:48093/index/hook/on_send_rtp_stopped +on_server_exited= +on_server_keepalive=http://127.0.0.1:48093/index/hook/on_server_keepalive +on_server_started=http://127.0.0.1:48093/index/hook/on_server_started +on_shell_login= +on_stream_changed=http://127.0.0.1:48093/index/hook/on_stream_changed +on_stream_none_reader=http://127.0.0.1:48093/index/hook/on_stream_none_reader +on_stream_not_found=http://127.0.0.1:48093/index/hook/on_stream_not_found +retry=1 +retry_delay=3.000000 +stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4 +timeoutSec=30 + +[http] +allow_cross_domains=1 +allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255 +charSet=utf-8 +dirMenu=1 +forbidCacheSuffix= +forwarded_ip_header= +keepAliveSecond=15 +maxReqSize=40960 +; HTTP 端口 7080,避免与宿主机 80 冲突 +port=7080 +rootPath=./www +sendBufSize=65536 +sslport=0 +virtualPath= + +[multicast] +addrMax=239.255.255.255 +addrMin=239.0.0.0 +udpTTL=64 + +[protocol] +add_mute_audio=1 +auto_close=0 +continue_push_ms=3000 +enable_audio=1 +enable_fmp4=1 +enable_hls=1 +enable_hls_fmp4=0 +enable_mp4=0 +enable_rtmp=1 +enable_rtsp=1 +enable_ts=1 +fmp4_demand=0 +hls_demand=0 +hls_save_path=./www +modify_stamp=2 +mp4_as_player=0 +mp4_max_second=3600 +mp4_save_path=./www +paced_sender_ms=0 +rtmp_demand=0 +rtsp_demand=0 +ts_demand=0 + +[record] +appName=record +enableFmp4=0 +fastStart=0 +fileBufSize=65536 +fileRepeat=0 +sampleMS=500 + +[rtc] +datachannel_echo=1 +externIP=172.17.16.7 +maxRtpCacheMS=5000 +maxRtpCacheSize=2048 +max_bitrate=0 +min_bitrate=0 +nackIntervalRatio=1.000000 +nackMaxCount=15 +nackMaxMS=3000 +nackMaxSize=2048 +nackRtpSize=8 +port=8000 +preferredCodecA=PCMA,PCMU,opus,mpeg4-generic +preferredCodecV=H264,H265,AV1,VP9,VP8 +rembBitRate=0 +start_bitrate=0 +tcpPort=8000 +timeoutSec=15 + +[rtmp] +directProxy=1 +enhanced=0 +handshakeSecond=15 +keepAliveSecond=15 +; RTMP 端口 7935,避免与标准 1935 冲突(如果 Prod 有 RTMP) +port=7935 +sslport=0 + +[rtp] +audioMtuSize=600 +h264_stap_a=1 +lowLatency=0 +rtpMaxSize=10 +videoMtuSize=1400 + +[rtp_proxy] +dumpDir= +gop_cache=1 +h264_pt=98 +h265_pt=99 +opus_pt=100 +port=10000 +port_range=30000-30500 +ps_pt=96 +rtp_g711_dur_ms=100 +timeoutSec=15 +udp_recv_socket_buffer=4194304 + +[rtsp] +authBasic=0 +directProxy=1 +handshakeSecond=15 +keepAliveSecond=15 +lowLatency=0 +; RTSP 端口 7554,避免与标准 554 冲突 +port=7554 +rtpTransportType=-1 +sslport=0 + +[shell] +maxReqSize=1024 +port=0 + +[srt] +latencyMul=4 +pktBufSize=8192 +port=0 +timeoutSec=5 \ No newline at end of file