Compare commits

...

5 Commits

Author SHA1 Message Date
阿斌
d26fe8cefc
Pre Merge pull request !36 from 阿斌/N/A 2025-09-08 08:09:19 +00:00
lin
18be8aff6c abl 支持拉流代理 2025-09-08 16:09:01 +08:00
648540858
6ebeef33ae
Merge pull request #1969 from ShuiFan0/docker
实现docker的开箱即用
2025-09-05 09:22:00 +08:00
氵帆
021e7a908f 实现docker的开箱即用 2025-09-04 14:52:25 +08:00
阿斌
da98101aac
update src/main/resources/civilCode.csv.
行政规划错误。江苏南通海门市,修改为海门区,浙江杭州删除下城区、江干区,新增钱塘区,临平区

Signed-off-by: 阿斌 <38912748@qq.com>
2024-12-15 08:58:42 +00:00
18 changed files with 273 additions and 1917 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
docker/volumes

2
.gitignore vendored
View File

@ -28,3 +28,5 @@ hs_err_pid*
/src/main/resources/static/
certificates
/.vs
/docker/volumes

View File

@ -1,7 +1,7 @@
version: '3'
services:
polaris-redis:
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-redis:latest
image: redis:latest # 使用官方Redis镜像
restart: unless-stopped
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
@ -11,8 +11,8 @@ services:
start_period: 10s
networks:
- media-net
ports:
- 6379:6379
# ports:
# - 6379:6379
volumes:
- ./redis/conf/redis.conf:/opt/polaris/redis/redis.conf
- ./volumes/redis/data/:/data
@ -21,7 +21,7 @@ services:
command: redis-server /opt/polaris/redis/redis.conf --appendonly yes
polaris-mysql:
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-mysql:latest
image: mysql:8 # 使用官方MySQL 8镜像
restart: unless-stopped
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306" ]
@ -34,18 +34,18 @@ services:
environment:
MYSQL_DATABASE: wvp
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_USER: wvp_user
MYSQL_PASSWORD: wvp_password
TZ: Asia/Shanghai
ports:
- 3306:3306
# ports:
# - 3306:3306
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./logs/mysql:/logs
- ./volumes/mysql/data:/var/lib/mysql
- ../数据库/2.7.4/初始化-mysql-2.7.4.sql:/docker-entrypoint-initdb.d/init.sql # 初始化SQL脚本目录
command: [
'mysqld',
'--default-authentication-plugin=mysql_native_password',
# '--default-authentication-plugin=mysql_native_password',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_general_ci',
@ -54,7 +54,7 @@ services:
]
polaris-media:
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-media:latest
image: zlmediakit/zlmediakit:master # 替换为官方镜像
restart: always
networks:
- media-net
@ -65,9 +65,18 @@ services:
volumes:
- ./volumes/video:/opt/media/www/record/
- ./logs/media:/opt/media/log/
- ./media/config.ini:/conf/config.ini
command: [
'MediaServer',
'-c', '/conf/config.ini',
'-l', '0'
]
polaris-wvp:
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-wvp:latest
# 显式指定构建上下文和Dockerfile路径
build:
context: .. # 构建上下文的根路径
dockerfile: ./docker/wvp/Dockerfile # 相对于上下文路径的Dockerfile位置
restart: always
networks:
- media-net
@ -84,7 +93,7 @@ services:
- polaris-mysql
- polaris-media
volumes:
- ./wvp/wvp/:/opt/wvp/wvp/
- ./wvp/wvp/:/opt/ylcx/wvp/
- ./logs/wvp:/opt/wvp/logs/
environment:
TZ: "Asia/Shanghai"
@ -98,13 +107,16 @@ services:
REDIS_PORT: 6379
DATABASE_HOST: polaris-mysql
DATABASE_PORT: 3306
DATABASE_USER: wvp
DATABASE_PASSWORD: wvp
DATABASE_USER: wvp_user
DATABASE_PASSWORD: wvp_password
# 前端跨域配置nginx容器所在物理机IP
NGINX_HOST: http://127.0.0.1:8080
polaris-nginx:
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-nginx:latest
# 显式指定构建上下文和Dockerfile路径
build:
context: .. # 构建上下文的根路径
dockerfile: ./docker/nginx/Dockerfile # 相对于上下文路径的Dockerfile位置
ports:
- "8080:8080"
depends_on:

View File

@ -52,21 +52,21 @@ alive_interval=10.0
enable=1
on_flow_report=
on_http_access=
on_play=
on_publish=
on_record_mp4=
on_play=http://127.0.0.1:18978/index/hook/on_play
on_publish=http://127.0.0.1:18978/index/hook/on_publish
on_record_mp4=http://127.0.0.1:18978/index/hook/on_record_mp4
on_record_ts=
on_rtp_server_timeout=
on_rtp_server_timeout=http://127.0.0.1:18978/index/hook/on_rtp_server_timeout
on_rtsp_auth=
on_rtsp_realm=
on_send_rtp_stopped=
on_send_rtp_stopped=http://127.0.0.1:18978/index/hook/on_send_rtp_stopped
on_server_exited=
on_server_keepalive=
on_server_started=
on_server_keepalive=http://127.0.0.1:18978/index/hook/on_server_keepalive
on_server_started=http://127.0.0.1:18978/index/hook/on_server_started
on_shell_login=
on_stream_changed=
on_stream_none_reader=
on_stream_not_found=
on_stream_changed=http://127.0.0.1:18978/index/hook/on_stream_changed
on_stream_none_reader=http://127.0.0.1:18978/index/hook/on_stream_none_reader
on_stream_not_found=http://127.0.0.1:18978/index/hook/on_stream_not_found
retry=1
retry_delay=3.0
stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
@ -111,7 +111,7 @@ hls_save_path=./www
modify_stamp=2
mp4_as_player=0
mp4_max_second=3600
mp4_save_path=/home
mp4_save_path=/opt/media
paced_sender_ms=0
rtmp_demand=0
rtsp_demand=0
@ -126,6 +126,7 @@ fileRepeat=0
sampleMS=500
[rtc]
bfilter=0
datachannel_echo=0
externIP=
maxRtpCacheMS=5000
@ -165,6 +166,7 @@ dumpDir=
gop_cache=1
h264_pt=98
h265_pt=99
merge_frame=1
opus_pt=100
port=10000
port_range=30000-30500
@ -189,6 +191,7 @@ port=0
[srt]
latencyMul=4
passPhrase=
pktBufSize=8192
port=9000
timeoutSec=5

View File

@ -1,19 +1,28 @@
FROM ubuntu:24.04 AS builder
RUN apt-get update && \
apt-get install -y nodejs npm && \
rm -rf /var/lib/apt/lists/*
COPY ./web /build
WORKDIR /build
RUN npm --registry=https://registry.npmmirror.com install
RUN npm run build:prod
WORKDIR /src/main/resources
RUN ls
WORKDIR /src/main/resources/static
RUN ls
FROM nginx:alpine
RUN apk add --no-cache bash
ARG TZ=Asia/Shanghai
RUN \
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
apk update && \
apk add tzdata
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
echo '${TZ}' > /etc/timezone
RUN rm -rf /etc/nginx/conf.d/*
RUN mkdir /opt/dist
COPY ./dist /opt/dist
COPY ./conf/nginx.conf /etc/nginx/conf.d
COPY --from=builder /src/main/resources/static /opt/dist
CMD ["nginx","-g","daemon off;"]

View File

@ -1,64 +1,84 @@
FROM ubuntu:20.04 AS build
ARG Platfrom=amd64
ARG JDK_NAME
FROM ringcentral/jdk:11 AS builder
EXPOSE 18978/tcp
EXPOSE 8116/tcp
EXPOSE 8116/udp
EXPOSE 8080/tcp
RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" \
apt-get install -y --no-install-recommends \
wget \
cmake \
maven \
git \
ca-certificates \
tzdata \
curl \
libpcre3 \
libpcre3-dev \
zlib1g-dev \
openssl \
libssl-dev \
gdb && \
apt-get autoremove -y && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*
#RUN apt-get update && \
#DEBIAN_FRONTEND="noninteractive" \
#apt-get install -y --no-install-recommends \
#wget \
#cmake \
#maven \
#git \
#ca-certificates \
#tzdata \
#curl \
#libpcre3 \
#libpcre3-dev \
#zlib1g-dev \
#openssl \
#libssl-dev \
#gdb && \
#apt-get autoremove -y && \
#apt-get clean -y && \
#rm -rf /var/lib/apt/lists/*
# install jdk1.8
RUN mkdir -p /opt/download
WORKDIR /opt/download
RUN if [ "$Platfrom" = "arm64" ]; \
then \
wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u411-linux-aarch64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_411/java/' && \
rm /opt/download/jdk-8.tar.gz; \
else \
wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u202-linux-x64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_202/java/' && \
rm /opt/download/jdk-8.tar.gz; \
fi
## install jdk1.8
#RUN mkdir -p /opt/download
#WORKDIR /opt/download
#RUN if [ "$Platfrom" = "arm64" ]; \
#then \
#wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u411-linux-aarch64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
#tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_411/java/' && \
#rm /opt/download/jdk-8.tar.gz; \
#else \
#wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u202-linux-x64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
#tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_202/java/' && \
#rm /opt/download/jdk-8.tar.gz; \
#fi
ENV JAVA_HOME /usr/local/java/
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH ${JAVA_HOME}/bin:$PATH
#ENV JAVA_HOME /usr/local/java/
#ENV JRE_HOME ${JAVA_HOME}/jre
#ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
#ENV PATH ${JAVA_HOME}/bin:$PATH
RUN java -version && javac -version
#RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources && \
RUN apt-get update && \
apt-get install -y maven && \
rm -rf /var/lib/apt/lists/*
COPY . /build
WORKDIR /build
RUN ls && mvn clean package -Dmaven.test.skip=true
WORKDIR /build/target
RUN mv wvp-pro-*.jar wvp.jar
FROM ringcentral/jdk:11
RUN mkdir -p /opt/wvp
WORKDIR /opt/wvp
COPY ./wvp /opt/wvp
COPY --from=builder /build/target /opt/wvp
COPY ./docker/wvp/wvp /opt/wvp
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]
WORKDIR /home
RUN cd /home && \
git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
RUN cd /home/wvp-GB28181-pro && \
mvn clean package -Dmaven.test.skip=true && \
cp /home/wvp-GB28181-pro/target/*.jar /opt/wvp/wvp.jar
WORKDIR /opt/wvp
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]
#RUN mkdir -p /opt/wvp
#WORKDIR /opt/wvp
#COPY ./wvp /opt/wvp
#
#WORKDIR /home
#RUN cd /home && \
#git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
#
#RUN cd /home/wvp-GB28181-pro && \
#mvn clean package -Dmaven.test.skip=true && \
#cp /home/wvp-GB28181-pro/target/*.jar /opt/wvp/wvp.jar
#
#WORKDIR /opt/wvp
#ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]

View File

@ -1010,7 +1010,7 @@ public class PlayServiceImpl implements IPlayService {
return;
}
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
log.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channel, startTime, endTime);
log.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channel.getDeviceId(), startTime, endTime);
}else {
if (callback != null) {
callback.run(code, msg, null);

View File

@ -8,13 +8,13 @@ import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.media.abl.bean.AblServerConfig;
import com.genersoft.iot.vmp.media.abl.bean.hook.OnStreamArriveABLHookParam;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.event.media.MediaRecordProcessEvent;
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService;
@ -23,6 +23,7 @@ import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -76,7 +77,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
logger.info("关闭RTP Server " + jsonObject);
if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) {
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("msg"));
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("memo"));
}
}else {
// 检查ZLM状态
@ -99,7 +100,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
logger.info("关闭RTP Server " + jsonObject);
if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) {
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("msg"));
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("memo"));
}
}else {
// 检查ZLM状态
@ -115,7 +116,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
JSONObject jsonObject = ablresTfulUtils.closeStreams(mediaServer, app, streamId);
if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) {
logger.error("[closeStreams] 失败: " + jsonObject.getString("msg"));
logger.error("[closeStreams] 失败: " + jsonObject.getString("memo"));
}
}else {
// 检查ZLM状态
@ -264,32 +265,24 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
@Override
public String getFfmpegCmd(MediaServer mediaServer, String cmdKey) {
logger.warn("[abl-getFfmpegCmd] 未实现");
return null;
}
@Override
public WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey) {
logger.warn("[abl-addFFmpegSource] 未实现");
return null;
return "";
}
@Override
public Boolean delFFmpegSource(MediaServer mediaServer, String streamKey) {
logger.warn("[abl-delFFmpegSource] 未实现");
return null;
JSONObject jsonObject = ablresTfulUtils.delFFmpegProxy(mediaServer, streamKey);
return jsonObject.getInteger("code") == 0;
}
@Override
public Boolean delStreamProxy(MediaServer mediaServer, String streamKey) {
logger.warn("[abl-delStreamProxy] 未实现");
return null;
JSONObject jsonObject = ablresTfulUtils.delStreamProxy(mediaServer, streamKey);
return jsonObject.getInteger("code") == 0;
}
@Override
public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) {
logger.warn("[abl-getFFmpegCMDs] 未实现");
return null;
return new HashMap<>();
}
// 接受进度通知
@ -352,8 +345,13 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
@Override
public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout) {
logger.warn("[abl-addStreamProxy] 未实现");
return null;
JSONObject jsonObject = ablresTfulUtils.addStreamProxy(mediaServer, app, stream, url, !enableAudio, enableMp4, rtpType, timeout);
if (jsonObject.getInteger("code") != 0) {
return WVPResult.fail(ErrorCode.ERROR100.getCode(), jsonObject.getString("memo"));
}else {
return WVPResult.success(jsonObject.getString("key"));
}
}
@Override
@ -374,18 +372,70 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
}
@Override
public void startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
logger.warn("[abl-startProxy] 未实现");
public String startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
MediaInfo mediaInfo = getMediaInfo(mediaServer, streamProxy.getApp(), streamProxy.getStream());
if (mediaInfo != null) {
closeStreams(mediaServer, streamProxy.getApp(), streamProxy.getStream());
}
JSONObject jsonObject = null;
if ("ffmpeg".equalsIgnoreCase(streamProxy.getType())){
if (streamProxy.getTimeout() == 0) {
streamProxy.setTimeout(15);
}
jsonObject = ablresTfulUtils.addFFmpegProxy(mediaServer, streamProxy.getApp(), streamProxy.getStream(), streamProxy.getSrcUrl().trim(),
!streamProxy.isEnableAudio(), streamProxy.isEnableMp4(), streamProxy.getRtspType(), streamProxy.getTimeout());
}else {
jsonObject = ablresTfulUtils.addStreamProxy(mediaServer, streamProxy.getApp(), streamProxy.getStream(), streamProxy.getSrcUrl().trim(),
streamProxy.isEnableAudio(), streamProxy.isEnableMp4(), streamProxy.getRtspType(), streamProxy.getTimeout());
}
if (jsonObject == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "请求失败");
}else if (jsonObject.getInteger("code") != 0) {
throw new ControllerException(jsonObject.getInteger("code"), jsonObject.getString("memo"));
}else {
String key = jsonObject.getString("key");
if (key == null) {
throw new ControllerException(jsonObject.getInteger("code"), "代理结果异常: " + jsonObject);
}else {
return key;
}
}
}
@Override
public void stopProxy(MediaServer mediaServer, String streamKey) {
logger.warn("[abl-stopProxy] 未实现");
public void stopProxy(MediaServer mediaServer, String streamKey, String type) {
JSONObject jsonObject = null;
if ("ffmpeg".equalsIgnoreCase(type)){
jsonObject = ablresTfulUtils.delFFmpegProxy(mediaServer, streamKey);
}else {
jsonObject = ablresTfulUtils.delStreamProxy(mediaServer, streamKey);
}
if (jsonObject == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "请求失败");
}else if (jsonObject.getInteger("code") != 0) {
throw new ControllerException(jsonObject.getInteger("code"), jsonObject.getString("memo"));
}
}
@Override
public List<String> listRtpServer(MediaServer mediaServer) {
return Collections.emptyList();
JSONObject jsonObject = ablresTfulUtils.getMediaList(mediaServer, "rtp", null);
if (jsonObject == null || jsonObject.getInteger("code") != 0) {
return null;
}
JSONArray mediaList = jsonObject.getJSONArray("mediaList");
if (mediaList == null || mediaList.isEmpty()) {
return new ArrayList<>();
}
List<String> result = new ArrayList<>();
for (int i = 0; i < mediaList.size(); i++) {
JSONObject mediaJSON = mediaList.getJSONObject(i);
result.add(mediaJSON.getString("stream"));
}
return result;
}
@Override

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -48,14 +47,6 @@ public class ABLRESTfulUtils {
httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS);
// 设置连接池
httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
if (logger.isDebugEnabled()) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
logger.debug("http请求参数" + message);
});
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
// OkHttp進行添加攔截器loggingInterceptor
httpClientBuilder.addInterceptor(logging);
}
client = httpClientBuilder.build();
}
return client;
@ -376,7 +367,9 @@ public class ABLRESTfulUtils {
public JSONObject getMediaList(MediaServer mediaServer, String app, String stream) {
Map<String, Object> param = new HashMap<>();
param.put("app", app);
param.put("stream", stream);
if (stream != null) {
param.put("stream", stream);
}
return sendPost(mediaServer,"getMediaList", param, null);
}
@ -404,4 +397,38 @@ public class ABLRESTfulUtils {
}
public JSONObject addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean disableAudio, boolean enableMp4, String rtpType, Integer timeout) {
Map<String, Object> param = new HashMap<>();
param.put("app", app);
param.put("stream", stream);
param.put("url", url);
param.put("disableAudio", disableAudio? "1" : "0");
param.put("enable_mp4", enableMp4 ? "1" : "0");
// TODO rtpType timeout 尚不支持
return sendPost(mediaServer,"addStreamProxy", param, null);
}
public JSONObject addFFmpegProxy(MediaServer mediaServer, String app, String stream, String url, boolean disableAudio, boolean enableMp4, String rtpType, Integer timeout) {
Map<String, Object> param = new HashMap<>();
param.put("app", app);
param.put("stream", stream);
param.put("url", url);
param.put("disableAudio", disableAudio);
param.put("enable_mp4", enableMp4);
// TODO rtpType timeout 尚不支持
return sendPost(mediaServer,"addFFmpegProxy", param, null);
}
public JSONObject delStreamProxy(MediaServer mediaServer, String streamKey) {
Map<String, Object> param = new HashMap<>();
param.put("key", streamKey);
return sendPost(mediaServer,"delStreamProxy", param, null);
}
public JSONObject delFFmpegProxy(MediaServer mediaServer, String streamKey) {
Map<String, Object> param = new HashMap<>();
param.put("key", streamKey);
return sendPost(mediaServer,"delFFmpegProxy", param, null);
}
}

View File

@ -52,8 +52,6 @@ public interface IMediaNodeServerService {
String getFfmpegCmd(MediaServer mediaServer, String cmdKey);
WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey);
WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout);
Boolean delFFmpegSource(MediaServer mediaServer, String streamKey);
@ -70,9 +68,9 @@ public interface IMediaNodeServerService {
Long updateDownloadProcess(MediaServer mediaServer, String app, String stream);
void startProxy(MediaServer mediaServer, StreamProxy streamProxy);
String startProxy(MediaServer mediaServer, StreamProxy streamProxy);
void stopProxy(MediaServer mediaServer, String streamKey);
void stopProxy(MediaServer mediaServer, String streamKey, String type);
List<String> listRtpServer(MediaServer mediaServer);

View File

@ -101,8 +101,6 @@ public interface IMediaServerService {
void closeStreams(MediaServer mediaServerItem, String app, String stream);
WVPResult<String> addFFmpegSource(MediaServer mediaServerItem, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey);
WVPResult<String> addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout);
Boolean delFFmpegSource(MediaServer mediaServerItem, String streamKey);
@ -156,9 +154,9 @@ public interface IMediaServerService {
Long updateDownloadProcess(MediaServer mediaServerItem, String app, String stream);
void startProxy(MediaServer mediaServer, StreamProxy streamProxy);
String startProxy(MediaServer mediaServer, StreamProxy streamProxy);
void stopProxy(MediaServer mediaServer, String streamKey);
void stopProxy(MediaServer mediaServer, String streamKey, String type);
StreamInfo getMediaByAppAndStream(String app, String stream);

View File

@ -760,16 +760,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
mediaNodeServerService.closeStreams(mediaServer, app, stream);
}
@Override
public WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
if (mediaNodeServerService == null) {
log.info("[addFFmpegSource] 失败, mediaServer的类型 {},未找到对应的实现类", mediaServer.getType());
return WVPResult.fail(ErrorCode.ERROR400);
}
return mediaNodeServerService.addFFmpegSource(mediaServer, srcUrl, dstUrl, timeoutMs, enableAudio, enableMp4, ffmpegCmdKey);
}
@Override
public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url,
boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout) {
@ -998,23 +988,23 @@ public class MediaServerServiceImpl implements IMediaServerService {
}
@Override
public void startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
public String startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
if (mediaNodeServerService == null) {
log.info("[startProxy] 失败, mediaServer的类型 {},未找到对应的实现类", mediaServer.getType());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到mediaServer对应的实现类");
}
mediaNodeServerService.startProxy(mediaServer, streamProxy);
return mediaNodeServerService.startProxy(mediaServer, streamProxy);
}
@Override
public void stopProxy(MediaServer mediaServer, String streamKey) {
public void stopProxy(MediaServer mediaServer, String streamKey, String type) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
if (mediaNodeServerService == null) {
log.info("[stopProxy] 失败, mediaServer的类型 {},未找到对应的实现类", mediaServer.getType());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到mediaServer对应的实现类");
}
mediaNodeServerService.stopProxy(mediaServer, streamKey);
mediaNodeServerService.stopProxy(mediaServer, streamKey, type);
}
@Override

View File

@ -301,22 +301,6 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
return mediaServerConfig.getString(cmdKey);
}
@Override
public WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey) {
JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(mediaServer, srcUrl, dstUrl, timeoutMs, enableAudio, enableMp4, ffmpegCmdKey);
if (jsonObject.getInteger("code") != 0) {
log.warn("[getFfmpegCmd] 添加FFMPEG代理失败");
return WVPResult.fail(ErrorCode.ERROR100.getCode(), "添加FFMPEG代理失败");
}else {
JSONObject data = jsonObject.getJSONObject("data");
if (data == null) {
return WVPResult.fail(ErrorCode.ERROR100.getCode(), "代理结果异常: " + jsonObject);
}else {
return WVPResult.success(data.getString("key"));
}
}
}
@Override
public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url,
boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout) {
@ -461,7 +445,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
}
@Override
public void startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
public String startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
String dstUrl;
if ("ffmpeg".equalsIgnoreCase(streamProxy.getType())) {
@ -522,6 +506,8 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
JSONObject data = jsonObject.getJSONObject("data");
if (data == null) {
throw new ControllerException(jsonObject.getInteger("code"), "代理结果异常: " + jsonObject);
}else {
return data.getString("key");
}
}
}
@ -546,7 +532,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
}
@Override
public void stopProxy(MediaServer mediaServer, String streamKey) {
public void stopProxy(MediaServer mediaServer, String streamKey, String type) {
JSONObject jsonObject = zlmresTfulUtils.delStreamProxy(mediaServer, streamKey);
if (jsonObject == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "请求失败");

View File

@ -247,6 +247,7 @@ public class ZLMMediaServerStatusManager {
}else {
mediaServerItem.setTranscodeSuffix(zlmServerConfig.getTranscodeSuffix());
}
mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
mediaServerItem.setHookAliveInterval(10F);
}
@ -288,8 +289,6 @@ public class ZLMMediaServerStatusManager {
// 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项
if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
}else {
param.put("rtp_proxy.port", mediaServerItem.getRtpProxyPort());
}
if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) {

View File

@ -117,13 +117,14 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
// hook响应
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
subscribe.removeSubscribe(rtpHook);
streamProxy.setPulling(true);
streamProxyMapper.updateStream(streamProxy);
});
mediaServerService.startProxy(mediaServer, streamProxy);
if (mediaServerId == null || !mediaServerId.equals(mediaServer.getId())) {
streamProxy.setMediaServerId(mediaServer.getId());
streamProxyMapper.updateStream(streamProxy);
}
String key = mediaServerService.startProxy(mediaServer, streamProxy);
streamProxy.setStreamKey(key);
streamProxy.setMediaServerId(mediaServer.getId());
streamProxyMapper.updateStream(streamProxy);
}
@Override
@ -152,7 +153,7 @@ public class StreamProxyPlayServiceImpl implements IStreamProxyPlayService {
if (ObjectUtils.isEmpty(streamProxy.getStreamKey())) {
mediaServerService.closeStreams(mediaServer, streamProxy.getApp(), streamProxy.getStream());
}else {
mediaServerService.stopProxy(mediaServer, streamProxy.getStreamKey());
mediaServerService.stopProxy(mediaServer, streamProxy.getStreamKey(), streamProxy.getType());
}
streamProxyMapper.removeStream(streamProxy.getId());
}

View File

@ -861,7 +861,7 @@
320623,如东县,3206
320681,启东市,3206
320682,如皋市,3206
320684,海门,3206
320684,海门,3206
320685,海安市,3206
3207,连云港市,32
320703,连云区,3207
@ -918,8 +918,6 @@
33,浙江省,
3301,杭州市,33
330102,上城区,3301
330103,下城区,3301
330104,江干区,3301
330105,拱墅区,3301
330106,西湖区,3301
330108,滨江区,3301
@ -927,6 +925,8 @@
330110,余杭区,3301
330111,富阳区,3301
330112,临安区,3301
330113,临平区,3301
330114,钱塘区,3301
330122,桐庐县,3301
330127,淳安县,3301
330182,建德市,3301

1 编号 名称 上级
861 320623 如东县 3206
862 320681 启东市 3206
863 320682 如皋市 3206
864 320684 海门市 海门区 3206
865 320685 海安市 3206
866 3207 连云港市 32
867 320703 连云区 3207
918 33 浙江省
919 3301 杭州市 33
920 330102 上城区 3301
330103 下城区 3301
330104 江干区 3301
921 330105 拱墅区 3301
922 330106 西湖区 3301
923 330108 滨江区 3301
925 330110 余杭区 3301
926 330111 富阳区 3301
927 330112 临安区 3301
928 330113 临平区 3301
929 330114 钱塘区 3301
930 330122 桐庐县 3301
931 330127 淳安县 3301
932 330182 建德市 3301

View File

@ -88,6 +88,9 @@ server:
certificate: xx.pem
# 私钥文件
certificate-private-key: xx.key
# protocols: TLSv1.2
# ciphers: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
# 作为28181服务器的配置
sip: