Compare commits

...

5 Commits

Author SHA1 Message Date
阿斌
d6f8e02e8a
Pre Merge pull request !41 from 阿斌/N/A 2025-09-08 08:09:21 +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
阿斌
34d1dbb399
修复两次密码不一致时,任然可以修改密码,且成功提交,密码用*代替
还有以下一处需要修改web\src\layout\components\dialog\changePassword.vue

Signed-off-by: 阿斌 <38912748@qq.com>
2025-08-23 15:03:02 +00:00
18 changed files with 280 additions and 1916 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/ /src/main/resources/static/
certificates certificates
/.vs
/docker/volumes

View File

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

View File

@ -52,21 +52,21 @@ alive_interval=10.0
enable=1 enable=1
on_flow_report= on_flow_report=
on_http_access= on_http_access=
on_play= on_play=http://127.0.0.1:18978/index/hook/on_play
on_publish= on_publish=http://127.0.0.1:18978/index/hook/on_publish
on_record_mp4= on_record_mp4=http://127.0.0.1:18978/index/hook/on_record_mp4
on_record_ts= 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_auth=
on_rtsp_realm= 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_exited=
on_server_keepalive= on_server_keepalive=http://127.0.0.1:18978/index/hook/on_server_keepalive
on_server_started= on_server_started=http://127.0.0.1:18978/index/hook/on_server_started
on_shell_login= on_shell_login=
on_stream_changed= on_stream_changed=http://127.0.0.1:18978/index/hook/on_stream_changed
on_stream_none_reader= on_stream_none_reader=http://127.0.0.1:18978/index/hook/on_stream_none_reader
on_stream_not_found= on_stream_not_found=http://127.0.0.1:18978/index/hook/on_stream_not_found
retry=1 retry=1
retry_delay=3.0 retry_delay=3.0
stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4 stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
@ -111,7 +111,7 @@ hls_save_path=./www
modify_stamp=2 modify_stamp=2
mp4_as_player=0 mp4_as_player=0
mp4_max_second=3600 mp4_max_second=3600
mp4_save_path=/home mp4_save_path=/opt/media
paced_sender_ms=0 paced_sender_ms=0
rtmp_demand=0 rtmp_demand=0
rtsp_demand=0 rtsp_demand=0
@ -126,6 +126,7 @@ fileRepeat=0
sampleMS=500 sampleMS=500
[rtc] [rtc]
bfilter=0
datachannel_echo=0 datachannel_echo=0
externIP= externIP=
maxRtpCacheMS=5000 maxRtpCacheMS=5000
@ -165,6 +166,7 @@ dumpDir=
gop_cache=1 gop_cache=1
h264_pt=98 h264_pt=98
h265_pt=99 h265_pt=99
merge_frame=1
opus_pt=100 opus_pt=100
port=10000 port=10000
port_range=30000-30500 port_range=30000-30500
@ -189,6 +191,7 @@ port=0
[srt] [srt]
latencyMul=4 latencyMul=4
passPhrase=
pktBufSize=8192 pktBufSize=8192
port=9000 port=9000
timeoutSec=5 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 FROM nginx:alpine
RUN apk add --no-cache bash
ARG TZ=Asia/Shanghai 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 --from=builder /src/main/resources/static /opt/dist
COPY ./dist /opt/dist
COPY ./conf/nginx.conf /etc/nginx/conf.d
CMD ["nginx","-g","daemon off;"] CMD ["nginx","-g","daemon off;"]

View File

@ -1,64 +1,84 @@
FROM ubuntu:20.04 AS build FROM ringcentral/jdk:11 AS builder
ARG Platfrom=amd64
ARG JDK_NAME
EXPOSE 18978/tcp EXPOSE 18978/tcp
EXPOSE 8116/tcp EXPOSE 8116/tcp
EXPOSE 8116/udp EXPOSE 8116/udp
EXPOSE 8080/tcp EXPOSE 8080/tcp
RUN apt-get update && \ #RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" \ #DEBIAN_FRONTEND="noninteractive" \
apt-get install -y --no-install-recommends \ #apt-get install -y --no-install-recommends \
wget \ #wget \
cmake \ #cmake \
maven \ #maven \
git \ #git \
ca-certificates \ #ca-certificates \
tzdata \ #tzdata \
curl \ #curl \
libpcre3 \ #libpcre3 \
libpcre3-dev \ #libpcre3-dev \
zlib1g-dev \ #zlib1g-dev \
openssl \ #openssl \
libssl-dev \ #libssl-dev \
gdb && \ #gdb && \
apt-get autoremove -y && \ #apt-get autoremove -y && \
apt-get clean -y && \ #apt-get clean -y && \
rm -rf /var/lib/apt/lists/* #rm -rf /var/lib/apt/lists/*
# install jdk1.8 ## install jdk1.8
RUN mkdir -p /opt/download #RUN mkdir -p /opt/download
WORKDIR /opt/download #WORKDIR /opt/download
RUN if [ "$Platfrom" = "arm64" ]; \ #RUN if [ "$Platfrom" = "arm64" ]; \
then \ #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 && \ #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/' && \ #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; \ #rm /opt/download/jdk-8.tar.gz; \
else \ #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 && \ #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/' && \ #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; \ #rm /opt/download/jdk-8.tar.gz; \
fi #fi
ENV JAVA_HOME /usr/local/java/ #ENV JAVA_HOME /usr/local/java/
ENV JRE_HOME ${JAVA_HOME}/jre #ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib #ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH ${JAVA_HOME}/bin:$PATH #ENV PATH ${JAVA_HOME}/bin:$PATH
RUN java -version && javac -version 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 RUN mkdir -p /opt/wvp
WORKDIR /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 #RUN mkdir -p /opt/wvp
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"] #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; return;
} }
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); 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 { }else {
if (callback != null) { if (callback != null) {
callback.run(code, msg, 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.common.StreamInfo;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting; 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.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService; 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.AblServerConfig;
import com.genersoft.iot.vmp.media.abl.bean.hook.OnStreamArriveABLHookParam; 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.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer; 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.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.event.media.MediaRecordProcessEvent; import com.genersoft.iot.vmp.media.event.media.MediaRecordProcessEvent;
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; 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.storager.dao.CloudRecordServiceMapper;
import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy; import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -76,7 +77,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
logger.info("关闭RTP Server " + jsonObject); logger.info("关闭RTP Server " + jsonObject);
if (jsonObject != null ) { if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) { if (jsonObject.getInteger("code") != 0) {
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("msg")); logger.error("[closeRtpServer] 失败: " + jsonObject.getString("memo"));
} }
}else { }else {
// 检查ZLM状态 // 检查ZLM状态
@ -99,7 +100,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
logger.info("关闭RTP Server " + jsonObject); logger.info("关闭RTP Server " + jsonObject);
if (jsonObject != null ) { if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) { if (jsonObject.getInteger("code") != 0) {
logger.error("[closeRtpServer] 失败: " + jsonObject.getString("msg")); logger.error("[closeRtpServer] 失败: " + jsonObject.getString("memo"));
} }
}else { }else {
// 检查ZLM状态 // 检查ZLM状态
@ -115,7 +116,7 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
JSONObject jsonObject = ablresTfulUtils.closeStreams(mediaServer, app, streamId); JSONObject jsonObject = ablresTfulUtils.closeStreams(mediaServer, app, streamId);
if (jsonObject != null ) { if (jsonObject != null ) {
if (jsonObject.getInteger("code") != 0) { if (jsonObject.getInteger("code") != 0) {
logger.error("[closeStreams] 失败: " + jsonObject.getString("msg")); logger.error("[closeStreams] 失败: " + jsonObject.getString("memo"));
} }
}else { }else {
// 检查ZLM状态 // 检查ZLM状态
@ -264,32 +265,24 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
@Override @Override
public String getFfmpegCmd(MediaServer mediaServer, String cmdKey) { public String getFfmpegCmd(MediaServer mediaServer, String cmdKey) {
logger.warn("[abl-getFfmpegCmd] 未实现"); return "";
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;
} }
@Override @Override
public Boolean delFFmpegSource(MediaServer mediaServer, String streamKey) { public Boolean delFFmpegSource(MediaServer mediaServer, String streamKey) {
logger.warn("[abl-delFFmpegSource] 未实现"); JSONObject jsonObject = ablresTfulUtils.delFFmpegProxy(mediaServer, streamKey);
return null; return jsonObject.getInteger("code") == 0;
} }
@Override @Override
public Boolean delStreamProxy(MediaServer mediaServer, String streamKey) { public Boolean delStreamProxy(MediaServer mediaServer, String streamKey) {
logger.warn("[abl-delStreamProxy] 未实现"); JSONObject jsonObject = ablresTfulUtils.delStreamProxy(mediaServer, streamKey);
return null; return jsonObject.getInteger("code") == 0;
} }
@Override @Override
public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) { public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) {
logger.warn("[abl-getFFmpegCMDs] 未实现"); return new HashMap<>();
return null;
} }
// 接受进度通知 // 接受进度通知
@ -352,8 +345,13 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
@Override @Override
public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType, Integer timeout) { 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 @Override
@ -374,18 +372,70 @@ public class ABLMediaNodeServerService implements IMediaNodeServerService {
} }
@Override @Override
public void startProxy(MediaServer mediaServer, StreamProxy streamProxy) { public String startProxy(MediaServer mediaServer, StreamProxy streamProxy) {
logger.warn("[abl-startProxy] 未实现");
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 @Override
public void stopProxy(MediaServer mediaServer, String streamKey) { public void stopProxy(MediaServer mediaServer, String streamKey, String type) {
logger.warn("[abl-stopProxy] 未实现"); 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 @Override
public List<String> listRtpServer(MediaServer mediaServer) { 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 @Override

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import okhttp3.*; import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -48,14 +47,6 @@ public class ABLRESTfulUtils {
httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS); httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS);
// 设置连接池 // 设置连接池
httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES)); 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(); client = httpClientBuilder.build();
} }
return client; return client;
@ -376,7 +367,9 @@ public class ABLRESTfulUtils {
public JSONObject getMediaList(MediaServer mediaServer, String app, String stream) { public JSONObject getMediaList(MediaServer mediaServer, String app, String stream) {
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>();
param.put("app", app); param.put("app", app);
param.put("stream", stream); if (stream != null) {
param.put("stream", stream);
}
return sendPost(mediaServer,"getMediaList", param, null); 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); 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); 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); Boolean delFFmpegSource(MediaServer mediaServer, String streamKey);
@ -70,9 +68,9 @@ public interface IMediaNodeServerService {
Long updateDownloadProcess(MediaServer mediaServer, String app, String stream); 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); List<String> listRtpServer(MediaServer mediaServer);

View File

@ -101,8 +101,6 @@ public interface IMediaServerService {
void closeStreams(MediaServer mediaServerItem, String app, String stream); 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); 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); Boolean delFFmpegSource(MediaServer mediaServerItem, String streamKey);
@ -156,9 +154,9 @@ public interface IMediaServerService {
Long updateDownloadProcess(MediaServer mediaServerItem, String app, String stream); 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); StreamInfo getMediaByAppAndStream(String app, String stream);

View File

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

View File

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

View File

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

View File

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

View File

@ -88,6 +88,9 @@ server:
certificate: xx.pem certificate: xx.pem
# 私钥文件 # 私钥文件
certificate-private-key: xx.key 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服务器的配置 # 作为28181服务器的配置
sip: sip:

View File

@ -13,10 +13,10 @@
<div id="shared" style="margin-right: 20px;"> <div id="shared" style="margin-right: 20px;">
<el-form ref="passwordForm" :rules="rules" status-icon label-width="80px"> <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
<el-form-item label="新密码" prop="newPassword"> <el-form-item label="新密码" prop="newPassword">
<el-input v-model="newPassword" autocomplete="off" /> <el-input v-model="newPassword" autocomplete="off" type="password" />
</el-form-item> </el-form-item>
<el-form-item label="确认密码" prop="confirmPassword"> <el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="confirmPassword" autocomplete="off" /> <el-input v-model="confirmPassword" autocomplete="off" type="password" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -88,6 +88,14 @@ export default {
} }
}, },
onSubmit: function() { onSubmit: function() {
if (this.newPassword !== this.confirmPassword) {
this.$message({
showClose: true,
message: '两次输入密码不一致!',
type: 'error'
})
return
}
this.$store.dispatch('user/changePasswordForAdmin', { this.$store.dispatch('user/changePasswordForAdmin', {
password: this.newPassword, password: this.newPassword,
userId: this.form.id userId: this.form.id