Compare commits

...

2 Commits

Author SHA1 Message Date
16d5bb3ba7 完善 2023-09-06 13:13:20 +08:00
4eb9b9cdd7 视频流 录制到临时文件 后 再写入响应 2023-09-06 10:59:10 +08:00
2 changed files with 36 additions and 90 deletions

View File

@ -15,7 +15,7 @@ mirror.id maven-default-http-blocker 部分改为
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
</mirror>
```
### 项目打包
#### 打包 为 jar

View File

@ -5,7 +5,6 @@ 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;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
@ -13,18 +12,15 @@ 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.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Path;
@ -47,99 +43,49 @@ public class VideoController {
@Operation(summary = "获取视频")
@GetMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<File> video(HttpServletResponse response) throws IOException {
public void video(HttpServletResponse response) throws IOException {
response.reset();
// response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setContentType("video/mp4");
// File f = new File("E:\\#Camera\\DCIM\\100MEDIA\\20230818\\NORM0003.MP4");
// try (
// BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(f));
// BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
// 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")) {
// FFmpegLogCallback.set();
// live.body()
// FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(live.body().asInputStream());
Path tmp = Path.of(System.getProperty("java.io.tmpdir"), IdUtil.getSnowflakeNextIdStr()).toAbsolutePath();
File file = new File(tmp + ".mp4");
log.info("创建文件 {}, {}", file, file.createNewFile());
String url = StringUtils.joinWith("/",config.getUrl(), "live","test.live.mp4");
log.info("url {}",url);
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(url);
String url = StringUtils.joinWith("/", config.getUrl(), "live", "test.live.mp4");
log.info("url {}", url);
try (
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(url);
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(file, 1920, 1080, 0)
) {
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);
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 {
Frame frame;
while ((frame = grabber.grab()) != null) {
if (frame.streamIndex == AVMEDIA_TYPE_VIDEO) {
recorder.record(frame);
}
grabber.stop();
grabber.release();
recorder.stop();
} catch (FFmpegFrameRecorder.Exception | FrameGrabber.Exception e) {
throw new RuntimeException(e);
}
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();
log.info("录像结束");
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
IoUtil.copy(inputStream, outputStream);
log.info("临时文件 {} 写入 响应 完成", file);
log.info("删除临时文件 {} {}", file, file.delete());
}
}