可切换是否使用ffmpeg处理视频
This commit is contained in:
parent
7d71478baf
commit
00b2d42a68
BIN
ffmpeg/ffmpeg-git-amd64-static.tar.xz
Normal file
BIN
ffmpeg/ffmpeg-git-amd64-static.tar.xz
Normal file
Binary file not shown.
@ -10,10 +10,10 @@ public class DevicePageDTO {
|
|||||||
@Schema(description = "页数", example = "1")
|
@Schema(description = "页数", example = "1")
|
||||||
@NotNull(message = "page 不能为空")
|
@NotNull(message = "page 不能为空")
|
||||||
@Min(value = 1, message = "page 必须为正整数")
|
@Min(value = 1, message = "page 必须为正整数")
|
||||||
int page;
|
Integer page;
|
||||||
|
|
||||||
@Schema(description = "每页条数", example = "10")
|
@Schema(description = "每页条数", example = "10")
|
||||||
@NotNull(message = "size 不能为空")
|
@NotNull(message = "size 不能为空")
|
||||||
@Min(value = 1, message = "size 必须为正整数")
|
@Min(value = 1, message = "size 必须为正整数")
|
||||||
int size;
|
Integer size;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import org.springdoc.core.annotations.ParameterObject;
|
|||||||
import org.springdoc.core.models.GroupedOpenApi;
|
import org.springdoc.core.models.GroupedOpenApi;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
@ -196,6 +196,13 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-exec</artifactId>
|
||||||
|
<version>1.3</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package cn.skcks.docking.gb28181.wvp.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "ffmpeg-support")
|
||||||
|
@Configuration
|
||||||
|
@Data
|
||||||
|
public class FfmpegConfig {
|
||||||
|
private String ffmpeg;
|
||||||
|
private String ffprobe;
|
||||||
|
|
||||||
|
private Rtp rtp;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Rtp {
|
||||||
|
private String download = "-i";
|
||||||
|
private String input = "-re -i";
|
||||||
|
private String output = "-vcodec h264 -acodec aac -f mp4";
|
||||||
|
private String logLevel = "fatal";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Debug debug;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Debug {
|
||||||
|
private Boolean download = false;
|
||||||
|
private Boolean input = false;
|
||||||
|
private Boolean output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task task;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Task {
|
||||||
|
private Integer max = 4;
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@ConfigurationProperties(prefix = "proxy.wvp")
|
@ConfigurationProperties(prefix = "proxy.wvp")
|
||||||
@Data
|
@Data
|
||||||
public class WvpProxyConfig {
|
public class WvpProxyConfig {
|
||||||
|
private Boolean enable = true;
|
||||||
private String url;
|
private String url;
|
||||||
private String user;
|
private String user;
|
||||||
private String passwd;
|
private String passwd;
|
||||||
@ -15,4 +16,9 @@ public class WvpProxyConfig {
|
|||||||
* 是否尝试通过 wvp-assist 服务下载
|
* 是否尝试通过 wvp-assist 服务下载
|
||||||
*/
|
*/
|
||||||
private Boolean useWvpAssist = true;
|
private Boolean useWvpAssist = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用 ffmpeg 编/解码, 否则使用内置 javacv
|
||||||
|
*/
|
||||||
|
private Boolean useFfmpeg = false;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package cn.skcks.docking.gb28181.wvp.service.ffmpeg;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.skcks.docking.gb28181.wvp.config.FfmpegConfig;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.exec.*;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FfmpegSupportService {
|
||||||
|
private final FfmpegConfig ffmpegConfig;
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Executor downloadToStream(String input, long time, TimeUnit unit, ExecuteStreamHandler streamHandler, ExecuteResultHandler executeResultHandler) {
|
||||||
|
FfmpegConfig.Rtp rtp = ffmpegConfig.getRtp();
|
||||||
|
FfmpegConfig.Debug debug = ffmpegConfig.getDebug();
|
||||||
|
String inputParam = debug.getInput() ? rtp.getInput() : StringUtils.joinWith(" ", rtp.getInput(), input);
|
||||||
|
log.info("视频输入参数 {}", inputParam);
|
||||||
|
|
||||||
|
String outputParam = debug.getOutput() ? rtp.getOutput() : StringUtils.joinWith(" ", rtp.getOutput(), "-");
|
||||||
|
log.info("视频输出参数 {}", outputParam);
|
||||||
|
|
||||||
|
return ffmpegExecutor(inputParam, outputParam, time, unit, streamHandler, executeResultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Executor ffmpegExecutor(String inputParam,String outputParam, long time, TimeUnit unit,ExecuteStreamHandler streamHandler,ExecuteResultHandler executeResultHandler){
|
||||||
|
FfmpegConfig.Rtp rtp = ffmpegConfig.getRtp();
|
||||||
|
String logLevelParam = StringUtils.joinWith(" ","-loglevel", rtp.getLogLevel());
|
||||||
|
String command = StringUtils.joinWith(" ", ffmpegConfig.getFfmpeg(), inputParam, outputParam, logLevelParam);
|
||||||
|
CommandLine commandLine = CommandLine.parse(command);
|
||||||
|
Executor executor = new DefaultExecutor();
|
||||||
|
ExecuteWatchdog watchdog = new ExecuteWatchdog(unit.toMillis(time));
|
||||||
|
executor.setStreamHandler(streamHandler);
|
||||||
|
executor.setExitValues(null);
|
||||||
|
executor.setWatchdog(watchdog);
|
||||||
|
if(executeResultHandler == null){
|
||||||
|
executor.execute(commandLine);
|
||||||
|
} else {
|
||||||
|
executor.execute(commandLine, executeResultHandler);
|
||||||
|
}
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,26 @@
|
|||||||
package cn.skcks.docking.gb28181.wvp.service.video;
|
package cn.skcks.docking.gb28181.wvp.service.video;
|
||||||
|
|
||||||
|
import cn.skcks.docking.gb28181.wvp.config.WvpProxyConfig;
|
||||||
|
import cn.skcks.docking.gb28181.wvp.service.ffmpeg.FfmpegSupportService;
|
||||||
import jakarta.servlet.AsyncContext;
|
import jakarta.servlet.AsyncContext;
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.exec.*;
|
||||||
import org.bytedeco.ffmpeg.avcodec.AVPacket;
|
import org.bytedeco.ffmpeg.avcodec.AVPacket;
|
||||||
import org.bytedeco.ffmpeg.global.avcodec;
|
import org.bytedeco.ffmpeg.global.avcodec;
|
||||||
import org.bytedeco.ffmpeg.global.avutil;
|
import org.bytedeco.ffmpeg.global.avutil;
|
||||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||||
import org.bytedeco.javacv.FFmpegFrameRecorder;
|
import org.bytedeco.javacv.FFmpegFrameRecorder;
|
||||||
import org.bytedeco.javacv.FrameGrabber;
|
import org.bytedeco.javacv.FrameGrabber;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -24,7 +28,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class RecordService {
|
public class RecordService {
|
||||||
|
private final FfmpegSupportService ffmpegSupportService;
|
||||||
|
private final WvpProxyConfig wvpProxyConfig;
|
||||||
/**
|
/**
|
||||||
* 写入 flv 响应头信息
|
* 写入 flv 响应头信息
|
||||||
* @param response HttpServletResponse 响应
|
* @param response HttpServletResponse 响应
|
||||||
@ -66,6 +73,21 @@ public class RecordService {
|
|||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void record(ServletResponse response, String url, long time) {
|
public void record(ServletResponse response, String url, long time) {
|
||||||
|
if (wvpProxyConfig.getUseFfmpeg()) {
|
||||||
|
ffmpegRecord(response, url, time);
|
||||||
|
} else {
|
||||||
|
javaCVrecord(response, url, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 录制视频 并写入 异步响应
|
||||||
|
* @param response AsyncContext.getResponse 异步响应
|
||||||
|
* @param url 要录制的视频地址
|
||||||
|
* @param time 录制时长 (单位: 秒)
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public void javaCVrecord(ServletResponse response, String url, long time) {
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
OutputStream outputStream = response.getOutputStream();
|
OutputStream outputStream = response.getOutputStream();
|
||||||
log.info("准备录制 url {}, time: {}", url, time);
|
log.info("准备录制 url {}, time: {}", url, time);
|
||||||
@ -120,8 +142,40 @@ public class RecordService {
|
|||||||
} catch (FFmpegFrameRecorder.Exception | FrameGrabber.Exception e) {
|
} catch (FFmpegFrameRecorder.Exception | FrameGrabber.Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (IOException ignore){}
|
} catch (IOException ignore){}
|
||||||
|
finally {
|
||||||
|
log.info("结束录制 {}", url);
|
||||||
|
stream.close();
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.info("结束录制 {}", url);
|
/**
|
||||||
outputStream.close();
|
* 录制视频 并写入 异步响应
|
||||||
|
* @param response AsyncContext.getResponse 异步响应
|
||||||
|
* @param url 要录制的视频地址
|
||||||
|
* @param time 录制时长 (单位: 秒)
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public void ffmpegRecord(ServletResponse response, String url, long time){
|
||||||
|
ServletOutputStream outputStream = response.getOutputStream();
|
||||||
|
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
|
||||||
|
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
|
||||||
|
DefaultExecuteResultHandler defaultExecuteResultHandler = new DefaultExecuteResultHandler();
|
||||||
|
Executor executor = ffmpegSupportService.downloadToStream(url, time, TimeUnit.SECONDS,streamHandler,defaultExecuteResultHandler);
|
||||||
|
// executor.setStreamHandler(streamHandler);
|
||||||
|
log.info("开始录制 {}", url);
|
||||||
|
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
AtomicBoolean record = new AtomicBoolean(true);
|
||||||
|
scheduledExecutorService.schedule(() -> {
|
||||||
|
log.info("到达结束时间, 结束录制 {}", url);
|
||||||
|
executor.getWatchdog().destroyProcess();
|
||||||
|
log.info("结束录制 {}", url);
|
||||||
|
// try {
|
||||||
|
// outputStream.close();
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
}, time, TimeUnit.SECONDS);
|
||||||
|
defaultExecuteResultHandler.waitFor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ public class WvpService {
|
|||||||
response.setContentType("video/mp4");
|
response.setContentType("video/mp4");
|
||||||
response.setHeader("Accept-Ranges", "none");
|
response.setHeader("Accept-Ranges", "none");
|
||||||
response.setHeader("Connection", "close");
|
response.setHeader("Connection", "close");
|
||||||
response.setHeader("Content-Disposition","attachment; filename=\"record.mp4\"");
|
// response.setHeader("Content-Disposition","attachment; filename=\"record.mp4\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@ -79,13 +80,13 @@ public class WvpService {
|
|||||||
String deviceId = wvpProxyDevice.getGbDeviceId();
|
String deviceId = wvpProxyDevice.getGbDeviceId();
|
||||||
String channelId = wvpProxyDevice.getGbDeviceChannelId();
|
String channelId = wvpProxyDevice.getGbDeviceChannelId();
|
||||||
log.info("设备编码 (deviceCode=>{}) 查询到的设备信息 国标id(gbDeviceId => {}), 通道(channelId => {})", deviceCode, deviceId, channelId);
|
log.info("设备编码 (deviceCode=>{}) 查询到的设备信息 国标id(gbDeviceId => {}), 通道(channelId => {})", deviceCode, deviceId, channelId);
|
||||||
|
request.startAsync();
|
||||||
Retryer<JsonResponse<?>> genericRetryer = RetryUtil.getDefaultGenericRetryer("调用 wvp api 查询设备历史");
|
AsyncContext asyncContext = request.getAsyncContext();
|
||||||
AsyncContext asyncContext = request.startAsync();
|
|
||||||
asyncContext.setTimeout(0);
|
asyncContext.setTimeout(0);
|
||||||
asyncContext.start(() -> {
|
asyncContext.start(() -> {
|
||||||
HttpServletResponse asyncResponse = (HttpServletResponse) asyncContext.getResponse();
|
HttpServletResponse asyncResponse = (HttpServletResponse) asyncContext.getResponse();
|
||||||
try {
|
try {
|
||||||
|
Retryer<JsonResponse<?>> genericRetryer = RetryUtil.getDefaultGenericRetryer("调用 wvp api 查询设备历史");
|
||||||
genericRetryer.call(() -> video(asyncResponse, deviceCode, deviceId, channelId, startTime, endTime));
|
genericRetryer.call(() -> video(asyncResponse, deviceCode, deviceId, channelId, startTime, endTime));
|
||||||
} catch (RetryException e) {
|
} catch (RetryException e) {
|
||||||
Attempt<?> failedAttempt = e.getLastFailedAttempt();
|
Attempt<?> failedAttempt = e.getLastFailedAttempt();
|
||||||
@ -101,6 +102,7 @@ public class WvpService {
|
|||||||
String reason = MessageFormat.format("调用 wvp api 查询设备({0})历史失败, 异常: {1}", deviceCode, e.getMessage());
|
String reason = MessageFormat.format("调用 wvp api 查询设备({0})历史失败, 异常: {1}", deviceCode, e.getMessage());
|
||||||
writeErrorToResponse(asyncResponse, JsonResponse.error(reason));
|
writeErrorToResponse(asyncResponse, JsonResponse.error(reason));
|
||||||
} finally {
|
} finally {
|
||||||
|
log.info("asyncContext 结束");
|
||||||
asyncContext.complete();
|
asyncContext.complete();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -202,7 +204,11 @@ public class WvpService {
|
|||||||
Retryer<JsonResponse<StreamContent>> playBackRetryer = RetryUtil
|
Retryer<JsonResponse<StreamContent>> playBackRetryer = RetryUtil
|
||||||
.<StreamContent>getDefaultRetryerBuilder("通过回放获取实时视频流下载", 100, TimeUnit.MILLISECONDS, 5)
|
.<StreamContent>getDefaultRetryerBuilder("通过回放获取实时视频流下载", 100, TimeUnit.MILLISECONDS, 5)
|
||||||
.build();
|
.build();
|
||||||
JsonResponse<StreamContent> videoStreamResponse = playBackRetryer.call(() -> wvpProxyClient.playbackStart(token, deviceId, channelId, new GeneralTimeReq(startTime, endTime)));
|
JsonResponse<StreamContent> videoStreamResponse = playBackRetryer.call(() -> {
|
||||||
|
JsonResponse<StreamContent> streamContentJsonResponse = wvpProxyClient.playbackStart(token, deviceId, channelId, new GeneralTimeReq(startTime, endTime));
|
||||||
|
log.info("实时视频流下载 响应:{} ", streamContentJsonResponse);
|
||||||
|
return streamContentJsonResponse;
|
||||||
|
});
|
||||||
StreamContent streamContent = videoStreamResponse.getData();
|
StreamContent streamContent = videoStreamResponse.getData();
|
||||||
String stream = streamContent.getStream();
|
String stream = streamContent.getStream();
|
||||||
String streamUrl = streamContent.getFlv();
|
String streamUrl = streamContent.getFlv();
|
||||||
|
@ -6,6 +6,11 @@ ENV HOME_PATH /opt/gb28181-docking-platform-wvp-proxy/
|
|||||||
RUN mkdir -p $HOME_PATH
|
RUN mkdir -p $HOME_PATH
|
||||||
WORKDIR $HOME_PATH
|
WORKDIR $HOME_PATH
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/bin/ffmpeg
|
||||||
|
ADD ./ffmpeg/ffmpeg /usr/bin/ffmpeg/ffmpeg
|
||||||
|
ADD ./ffmpeg/ffprobe /usr/bin/ffmpeg/ffprobe
|
||||||
|
ADD ./ffmpeg/model /usr/bin/ffmpeg/model
|
||||||
|
|
||||||
ADD target/gb28181-wvp-proxy-starter.jar /opt/gb28181-docking-platform-wvp-proxy/starter.jar
|
ADD target/gb28181-wvp-proxy-starter.jar /opt/gb28181-docking-platform-wvp-proxy/starter.jar
|
||||||
|
|
||||||
EXPOSE 18183
|
EXPOSE 18183
|
||||||
|
@ -43,6 +43,22 @@ media:
|
|||||||
|
|
||||||
proxy:
|
proxy:
|
||||||
wvp:
|
wvp:
|
||||||
url: http://10.10.10.20:18978
|
url: http://127.0.0.1:18978
|
||||||
user: admin
|
user: admin
|
||||||
passwd: admin
|
passwd: admi
|
||||||
|
use-ffmpeg: false
|
||||||
|
enable: true
|
||||||
|
|
||||||
|
ffmpeg-support:
|
||||||
|
task:
|
||||||
|
max: 4
|
||||||
|
ffmpeg: D:\Soft\Captura\ffmpeg\ffmpeg.exe
|
||||||
|
ffprobe: D:\Soft\Captura\ffmpeg\ffprobe.exe
|
||||||
|
rtp:
|
||||||
|
input: -r -i http://10.10.10.200:5080/live/test.live.flv
|
||||||
|
# input: -re -i
|
||||||
|
output: -vcodec copy -acodec copy -movflags empty_moov+frag_keyframe+default_base_moof -f mp4 # -rtsp_transport tcp
|
||||||
|
debug:
|
||||||
|
download: false
|
||||||
|
input: true
|
||||||
|
output: false
|
||||||
|
@ -24,8 +24,8 @@ spring:
|
|||||||
username: root
|
username: root
|
||||||
password: 123456a
|
password: 123456a
|
||||||
url: jdbc:mysql://192.168.1.241:3306/gb28181_docking_platform?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
url: jdbc:mysql://192.168.1.241:3306/gb28181_docking_platform?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||||
# profiles:
|
profiles:
|
||||||
# active: local
|
active: local
|
||||||
cloud:
|
cloud:
|
||||||
openfeign:
|
openfeign:
|
||||||
httpclient:
|
httpclient:
|
||||||
@ -50,3 +50,18 @@ proxy:
|
|||||||
user: admin
|
user: admin
|
||||||
passwd: admin
|
passwd: admin
|
||||||
use-wvp-assist: false
|
use-wvp-assist: false
|
||||||
|
enable: true
|
||||||
|
use-ffmpeg: false
|
||||||
|
|
||||||
|
ffmpeg-support:
|
||||||
|
task:
|
||||||
|
max: 4
|
||||||
|
ffmpeg: /usr/bin/ffmpeg/ffmpeg
|
||||||
|
ffprobe: /usr/bin/ffmpeg/ffprobe
|
||||||
|
rtp:
|
||||||
|
input: -i
|
||||||
|
output: -vcodec h264 -acodec aac -movflags empty_moov+frag_keyframe+default_base_moof -f mp4 # -rtsp_transport tcp
|
||||||
|
debug:
|
||||||
|
download: false
|
||||||
|
input: true
|
||||||
|
output: false
|
||||||
|
54
gb28181-wvp-proxy-starter/src/main/resources/logback.xml
Normal file
54
gb28181-wvp-proxy-starter/src/main/resources/logback.xml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||||
|
|
||||||
|
<contextName>logback</contextName>
|
||||||
|
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
|
||||||
|
<!--<property name="log.path" value="./log/business_Log" />-->
|
||||||
|
|
||||||
|
<!--输出到控制台-->
|
||||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
|
||||||
|
<!-- <level>INFO</level>-->
|
||||||
|
<!-- </filter>-->
|
||||||
|
<!-- <withJansi>true</withJansi>-->
|
||||||
|
<encoder>
|
||||||
|
<!--<pattern>%d %p (%file:%line\)- %m%n</pattern>-->
|
||||||
|
<!--格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符-->
|
||||||
|
<pattern>%red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %yellow(at %class.%method) (%file:%line\) - %cyan(%msg%n)</pattern>
|
||||||
|
<!--<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %magenta(%-5level) %green([%-50.50class]) >>> %cyan(%msg) %n</pattern>-->
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--<!–输出到文件–>-->
|
||||||
|
<!--<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
|
||||||
|
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
|
||||||
|
<!-- <level>INFO</level>-->
|
||||||
|
<!-- </filter>-->
|
||||||
|
<!-- <file>${log.path}/logback.log</file>-->
|
||||||
|
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||||
|
<!-- <fileNamePattern>${log.path}/logback-%d{yyyy-MM-dd-HH-mm}.log</fileNamePattern>-->
|
||||||
|
<!-- <maxHistory>365</maxHistory>-->
|
||||||
|
<!-- <!– <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">–>-->
|
||||||
|
<!-- <!– <maxFileSize>100kB</maxFileSize>–>-->
|
||||||
|
<!-- <!– </timeBasedFileNamingAndTriggeringPolicy>–>-->
|
||||||
|
<!-- </rollingPolicy>-->
|
||||||
|
<!-- <encoder>-->
|
||||||
|
<!-- <!–格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符–>-->
|
||||||
|
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
|
||||||
|
<!-- <charset>UTF-8</charset>-->
|
||||||
|
<!-- </encoder>-->
|
||||||
|
<!--</appender>-->
|
||||||
|
|
||||||
|
<!-- 如果appender里没有限定日志级别,那么root可以统一设置,如果没有配置那么控制台和文件不会输出任何日志,这里root的level不做限制-->
|
||||||
|
<root level="INFO">
|
||||||
|
<!-- 允许控制台输出-->
|
||||||
|
<appender-ref ref="console" />
|
||||||
|
<!--<!– 允许文件输出–>-->
|
||||||
|
<!--<appender-ref ref="file" />-->
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="cn.skcks.docking.gb28181.core.sip.logger" level="INFO" />
|
||||||
|
<logger name="cn.skcks.docking.gb28181" level="DEBUG" />
|
||||||
|
</configuration>
|
@ -2,6 +2,19 @@
|
|||||||
# 用于缓存打包过程下载的依赖
|
# 用于缓存打包过程下载的依赖
|
||||||
mkdir repository
|
mkdir repository
|
||||||
curDir=`pwd`
|
curDir=`pwd`
|
||||||
|
repository=${curDir}/repository
|
||||||
|
|
||||||
|
if ! test -e ${curDir}/gb28181-wvp-proxy-starter/ffmpeg;then
|
||||||
|
xz -d ${curDir}/ffmpeg/ffmpeg-git-amd64-static.tar.xz
|
||||||
|
tar -xvf ${curDir}/ffmpeg/ffmpeg-git-amd64-static.tar -C ${curDir}/ffmpeg/
|
||||||
|
mv ${curDir}/ffmpeg/ffmpeg-git*-static/* ${curDir}/ffmpeg
|
||||||
|
rm -rf ${curDir}/ffmpeg/ffmpeg-git*-static
|
||||||
|
mkdir -p ${curDir}/gb28181-wvp-proxy-starter/ffmpeg
|
||||||
|
cp ${curDir}/ffmpeg/ffmpeg ${curDir}/gb28181-wvp-proxy-starter/ffmpeg
|
||||||
|
cp ${curDir}/ffmpeg/ffprobe ${curDir}/gb28181-wvp-proxy-starter/ffmpeg
|
||||||
|
cp -r ${curDir}/ffmpeg/model ${curDir}/gb28181-wvp-proxy-starter/ffmpeg
|
||||||
|
fi
|
||||||
|
|
||||||
docker run --name maven --rm \
|
docker run --name maven --rm \
|
||||||
-v ${curDir}:/usr/src/mymaven \
|
-v ${curDir}:/usr/src/mymaven \
|
||||||
-v ${curDir}/repository:/root/.m2/repository \
|
-v ${curDir}/repository:/root/.m2/repository \
|
||||||
|
Loading…
Reference in New Issue
Block a user