ffmpeg 转换视频流 试水, 未完
This commit is contained in:
parent
af0229ac55
commit
6266f0c7d1
@ -1,6 +1,8 @@
|
||||
package cn.skcks.docking.gb28181.wvp.api;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.skcks.docking.gb28181.media.config.ZlmMediaConfig;
|
||||
import cn.skcks.docking.gb28181.wvp.config.SwaggerConfig;
|
||||
import cn.skcks.docking.gb28181.wvp.proxy.ZlmProxyClient;
|
||||
import feign.Response;
|
||||
@ -8,24 +10,34 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bytedeco.ffmpeg.global.avcodec;
|
||||
import org.bytedeco.ffmpeg.global.avutil;
|
||||
import org.bytedeco.javacv.*;
|
||||
import org.springdoc.core.models.GroupedOpenApi;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.bytedeco.ffmpeg.global.avutil.AVMEDIA_TYPE_VIDEO;
|
||||
|
||||
@Slf4j
|
||||
@Tag(name = "视频api")
|
||||
@Controller
|
||||
@RequestMapping("/video")
|
||||
@RequiredArgsConstructor
|
||||
public class VideoController {
|
||||
private final ZlmProxyClient zlmProxyClient;
|
||||
private final ZlmMediaConfig config;
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi videoApi() {
|
||||
@ -35,9 +47,9 @@ public class VideoController {
|
||||
@Operation(summary = "获取视频")
|
||||
@GetMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
@ResponseBody
|
||||
public void video(HttpServletResponse response) {
|
||||
public ResponseEntity<File> video(HttpServletResponse response) throws IOException {
|
||||
response.reset();
|
||||
// response.setHeader("Content-Type","video/mp4");
|
||||
response.setContentType("video/mp4");
|
||||
// File f = new File("E:\\#Camera\\DCIM\\100MEDIA\\20230818\\NORM0003.MP4");
|
||||
// try (
|
||||
// BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(f));
|
||||
@ -45,12 +57,89 @@ public class VideoController {
|
||||
// IoUtil.copy(inputStream, outputStream);
|
||||
// }
|
||||
|
||||
// try{
|
||||
Path tmp = Path.of(System.getProperty("java.io.tmpdir"),IdUtil.getSnowflakeNextIdStr()).toAbsolutePath();
|
||||
File file = new File(tmp +".mp4");
|
||||
log.info("创建文件 {}, {}",file, file.createNewFile());
|
||||
try (Response live = zlmProxyClient.live("live", "test.live.mp4")) {
|
||||
InputStream inputStream = live.body().asInputStream();
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
IoUtil.copy(inputStream, outputStream);
|
||||
// FFmpegLogCallback.set();
|
||||
// live.body()
|
||||
// FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(live.body().asInputStream());
|
||||
|
||||
|
||||
String url = StringUtils.joinWith("/",config.getUrl(), "live","test.live.mp4");
|
||||
log.info("url {}",url);
|
||||
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(url);
|
||||
grabber.start();
|
||||
|
||||
|
||||
try(FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(file,1920,1080,0)){
|
||||
recorder.start();
|
||||
log.info("开始录像");
|
||||
log.info("{}",file);
|
||||
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
|
||||
// recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); //视频源数据yuv
|
||||
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); //设置音频压缩方式
|
||||
recorder.setFormat("mp4");
|
||||
recorder.setVideoOption("threads", String.valueOf(Runtime.getRuntime().availableProcessors())); //解码线程数
|
||||
try (Java2DFrameConverter converter = new Java2DFrameConverter()){
|
||||
|
||||
// 建议在线程中使用该方法
|
||||
Frame frame;
|
||||
|
||||
// 此处仅为本地预览
|
||||
// CanvasFrame cframe = new CanvasFrame("欢迎来到直播间", CanvasFrame.getDefaultGamma() /
|
||||
// grabber.getGamma());
|
||||
// cframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 窗口关闭,则程序关闭
|
||||
// cframe.setAlwaysOnTop(true);
|
||||
|
||||
while ((frame = grabber.grab()) != null) {
|
||||
if(frame.streamIndex == AVMEDIA_TYPE_VIDEO){
|
||||
// BufferedImage bufferedImage = converter.getBufferedImage(frame);
|
||||
// frame.image = converter.getFrame(bufferedImage).image;
|
||||
recorder.record(frame);
|
||||
}
|
||||
// cframe.showImage(frame);
|
||||
}
|
||||
grabber.stop();
|
||||
grabber.release();
|
||||
recorder.stop();
|
||||
} catch (FFmpegFrameRecorder.Exception | FrameGrabber.Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
log.info("录像结束");
|
||||
// response.getOutputStream().close();
|
||||
// } finally {
|
||||
// log.info("临时文件 {} 写入完成",file);
|
||||
// FileInputStream fileInputStream = new FileInputStream(file);
|
||||
// OutputStream outputStream = response.getOutputStream();
|
||||
// IoUtil.copy(fileInputStream, outputStream);
|
||||
// log.info("临时文件 {} 写入 响应 完成",file);
|
||||
// fileInputStream.close();
|
||||
|
||||
return ResponseEntity.ok().body(file);
|
||||
|
||||
// InputStream inputStream = live.body().asInputStream();
|
||||
// Path tmp = Path.of(System.getProperty("java.io.tmpdir"),IdUtil.getSnowflakeNextIdStr()).toAbsolutePath();
|
||||
// File file = File.createTempFile(tmp.toString(),".mp4");
|
||||
// log.info("临时文件 {}", file);
|
||||
// FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
// BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
|
||||
// IoUtil.copy(inputStream, bufferedOutputStream);
|
||||
// log.info("临时文件 {} 写入完成",file);
|
||||
// FileInputStream fileInputStream = new FileInputStream(file);
|
||||
// BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
|
||||
// OutputStream outputStream = response.getOutputStream();
|
||||
// IoUtil.copy(bufferedInputStream, outputStream);
|
||||
// log.info("临时文件 {} 写入 响应 完成",file);
|
||||
// fileInputStream.close();
|
||||
// file.delete();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
file.deleteOnExit();
|
||||
}
|
||||
// return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,27 @@
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.bytedeco</groupId>-->
|
||||
<!-- <artifactId>javacv-platform</artifactId>-->
|
||||
<!-- <version>1.5.6</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv -->
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>javacv</artifactId>
|
||||
<version>1.5.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.bytedeco/ffmpeg-platform -->
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>ffmpeg-platform</artifactId>
|
||||
<version>4.4-1.5.6</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -87,4 +108,4 @@
|
||||
</testResource>
|
||||
</testResources>
|
||||
</build>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@EnableFeignClients(basePackages = {
|
||||
"cn.skcks.docking.gb28181.media",
|
||||
@ -14,9 +15,11 @@ import org.springframework.context.annotation.ComponentScan;
|
||||
"cn.skcks.docking.gb28181.annotation",
|
||||
"cn.skcks.docking.gb28181.common",
|
||||
"cn.skcks.docking.gb28181.wvp",
|
||||
"cn.skcks.docking.gb28181.media",
|
||||
})
|
||||
@EnableAsync
|
||||
public class Gb28181WvpProxyStarter {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Gb28181WvpProxyStarter.class, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
server:
|
||||
port: 18186
|
||||
project:
|
||||
version: @project.version@
|
||||
|
||||
spring:
|
||||
data:
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
# host: 192.168.1.241
|
||||
host: 10.10.10.200
|
||||
# [必须修改] 端口号
|
||||
port: 16379
|
||||
# [可选] 数据库 DB
|
||||
database: 15
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password: 12341234
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
username: root
|
||||
password: 12341234
|
||||
url: jdbc:mysql://10.10.10.200:3306/gb28181_docking_platform?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||
config:
|
||||
activate:
|
||||
on-profile: local
|
||||
cloud:
|
||||
openfeign:
|
||||
httpclient:
|
||||
connection-timeout: 0
|
||||
ok-http:
|
||||
read-timeout: 0
|
||||
media:
|
||||
ip: 10.10.10.200
|
||||
url: 'http://10.10.10.200:5080'
|
||||
# url: 'http://10.10.10.200:12580/anything/'
|
||||
id: amrWMKmbKqoBjRQ9
|
||||
# secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||
secret: 4155cca6-2f9f-11ee-85e6-8de4ce2e7333
|
||||
|
||||
proxy:
|
||||
wvp:
|
||||
url: http://192.168.3.13:18978
|
||||
user: admin
|
||||
passwd: admin
|
@ -4,6 +4,7 @@ server:
|
||||
project:
|
||||
version: @project.version@
|
||||
|
||||
|
||||
spring:
|
||||
data:
|
||||
redis:
|
||||
@ -24,6 +25,14 @@ spring:
|
||||
username: root
|
||||
password: 123456a
|
||||
url: jdbc:mysql://192.168.1.241:3306/gb28181_docking_platform?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||
profiles:
|
||||
active: local
|
||||
cloud:
|
||||
openfeign:
|
||||
httpclient:
|
||||
connection-timeout: 0
|
||||
ok-http:
|
||||
read-timeout: 0
|
||||
|
||||
media:
|
||||
ip: 192.168.1.241
|
||||
@ -37,4 +46,4 @@ proxy:
|
||||
wvp:
|
||||
url: http://192.168.3.13:18978
|
||||
user: admin
|
||||
passwd: admin
|
||||
passwd: admin
|
||||
|
Loading…
Reference in New Issue
Block a user