添加预处理扩展接口

This commit is contained in:
xgc 2024-07-10 11:01:28 +08:00
parent f960667ff4
commit 7669895db7
6 changed files with 50 additions and 13 deletions

View File

@ -30,7 +30,7 @@ public class FLVController {
HttpServletRequest request) { HttpServletRequest request) {
String url = openFLVService.getUrl(channel); String url = openFLVService.getUrl(channel);
if(!StringUtils.isEmpty(url)){ if(!StringUtils.isEmpty(url)){
service.open(channel,url, response, request); service.open(channel,url, response, request,openFLVService);
} }
} }
@GetMapping(value = "/get/flv/hls/stream") @GetMapping(value = "/get/flv/hls/stream")
@ -38,7 +38,7 @@ public class FLVController {
HttpServletRequest request) throws UnsupportedEncodingException { HttpServletRequest request) throws UnsupportedEncodingException {
if(!StringUtils.isEmpty(url)){ if(!StringUtils.isEmpty(url)){
String decodedUrl = java.net.URLDecoder.decode(url, "UTF-8"); String decodedUrl = java.net.URLDecoder.decode(url, "UTF-8");
service.open(decodedUrl, response, request); service.open(decodedUrl, response, request,openFLVService);
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.gc.easy.flv.factories; package com.gc.easy.flv.factories;
import com.alibaba.fastjson.util.IOUtils; import com.alibaba.fastjson.util.IOUtils;
import com.gc.easy.flv.service.IOpenFLVService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.avcodec.AVPacket; import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.global.avcodec; import org.bytedeco.ffmpeg.global.avcodec;
@ -60,12 +61,15 @@ public class ConverterFactories extends Thread implements Converter {
*/ */
private Map<String, Converter> factories; private Map<String, Converter> factories;
private IOpenFLVService openFLVService;
public ConverterFactories(String url, String key, Map<String, Converter> factories, List<AsyncContext> outEntitys) {
public ConverterFactories(String url, String key, Map<String, Converter> factories, List<AsyncContext> outEntitys, IOpenFLVService openFLVService) {
this.url = url; this.url = url;
this.key = key; this.key = key;
this.factories = factories; this.factories = factories;
this.outEntitys = outEntitys; this.outEntitys = outEntitys;
this.openFLVService=openFLVService;
} }
@Override @Override
@ -79,7 +83,7 @@ public class ConverterFactories extends Thread implements Converter {
} }
grabber.start(); grabber.start();
if (avcodec.AV_CODEC_ID_H264 == grabber.getVideoCodec() if (avcodec.AV_CODEC_ID_H264 == grabber.getVideoCodec()
&& (grabber.getAudioChannels() == 0 || avcodec.AV_CODEC_ID_AAC == grabber.getAudioCodec())) { && (grabber.getAudioChannels() == 0 || avcodec.AV_CODEC_ID_AAC == grabber.getAudioCodec())&&(openFLVService==null||!openFLVService.openPreview())) {
log.info("this url:{} converterFactories start", url); log.info("this url:{} converterFactories start", url);
// 来源视频H264格式,音频AAC格式 // 来源视频H264格式,音频AAC格式
// 无须转码更低的资源消耗更低的延迟 // 无须转码更低的资源消耗更低的延迟
@ -135,7 +139,7 @@ public class ConverterFactories extends Thread implements Converter {
} else { } else {
isCloseGrabberAndResponse = false; isCloseGrabberAndResponse = false;
// 需要转码为视频H264格式,音频AAC格式 // 需要转码为视频H264格式,音频AAC格式
ConverterTranFactories c = new ConverterTranFactories(url, key, factories, outEntitys, grabber); ConverterTranFactories c = new ConverterTranFactories(url, key, factories, outEntitys, grabber,openFLVService);
factories.put(key, c); factories.put(key, c);
c.start(); c.start();
} }

View File

@ -1,11 +1,14 @@
package com.gc.easy.flv.factories; package com.gc.easy.flv.factories;
import com.alibaba.fastjson.util.IOUtils; import com.alibaba.fastjson.util.IOUtils;
import com.gc.easy.flv.service.IOpenFLVService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avcodec; import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder; import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.IplImage;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -59,13 +62,18 @@ public class ConverterTranFactories extends Thread implements Converter {
*/ */
private Map<String, Converter> factories; private Map<String, Converter> factories;
private OpenCVFrameConverter.ToIplImage converter;
private IOpenFLVService openFLVService;
public ConverterTranFactories(String url, String key, Map<String, Converter> factories, public ConverterTranFactories(String url, String key, Map<String, Converter> factories,
List<AsyncContext> outEntitys, FFmpegFrameGrabber grabber) { List<AsyncContext> outEntitys, FFmpegFrameGrabber grabber, IOpenFLVService openFLVService) {
this.url = url; this.url = url;
this.key = key; this.key = key;
this.factories = factories; this.factories = factories;
this.outEntitys = outEntitys; this.outEntitys = outEntitys;
this.grabber = grabber; this.grabber = grabber;
this.openFLVService=openFLVService;
} }
@Override @Override
@ -82,6 +90,8 @@ public class ConverterTranFactories extends Thread implements Converter {
stream = new ByteArrayOutputStream(); stream = new ByteArrayOutputStream();
recorder = new FFmpegFrameRecorder(stream, grabber.getImageWidth(), grabber.getImageHeight(), recorder = new FFmpegFrameRecorder(stream, grabber.getImageWidth(), grabber.getImageHeight(),
grabber.getAudioChannels()); grabber.getAudioChannels());
converter = new OpenCVFrameConverter.ToIplImage();
recorder.setInterleaved(true); recorder.setInterleaved(true);
recorder.setVideoOption("preset", "ultrafast"); recorder.setVideoOption("preset", "ultrafast");
recorder.setVideoOption("tune", "zerolatency"); recorder.setVideoOption("tune", "zerolatency");
@ -107,6 +117,14 @@ public class ConverterTranFactories extends Thread implements Converter {
while (runing) { while (runing) {
// 抓取一帧 // 抓取一帧
Frame f = grabber.grab(); Frame f = grabber.grab();
if(openFLVService!=null&&openFLVService.openPreview()){
//预处理
IplImage iplImage = converter.convert(f);//抓取一帧视频并将其转换为图像至于用这个图像用来做什么加水印人脸识别等等自行添加
if (iplImage != null) {
openFLVService.preview(iplImage);
f = converter.convert(iplImage);
}
}
if (f != null) { if (f != null) {
try { try {
// 转码 // 转码

View File

@ -11,7 +11,7 @@ public interface IFLVService {
* @param url * @param url
* @param response * @param response
*/ */
public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request); public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request,IOpenFLVService openFLVService);
public void open(String url, HttpServletResponse response, HttpServletRequest request); public void open(String url, HttpServletResponse response, HttpServletRequest request,IOpenFLVService openFLVService);
} }

View File

@ -1,5 +1,7 @@
package com.gc.easy.flv.service; package com.gc.easy.flv.service;
import org.bytedeco.opencv.opencv_core.IplImage;
public interface IOpenFLVService { public interface IOpenFLVService {
@ -8,5 +10,17 @@ public interface IOpenFLVService {
* @param channel * @param channel
* @return * @return
*/ */
public String getUrl(Integer channel); String getUrl(Integer channel);
/**
* 抓取一帧视频并将其转换为图像预处理
* @param iplImage
*/
void preview(IplImage iplImage);
/**
* 开启预处理
* @return
*/
boolean openPreview();
} }

View File

@ -4,6 +4,7 @@ package com.gc.easy.flv.service.impl;
import com.gc.easy.flv.factories.Converter; import com.gc.easy.flv.factories.Converter;
import com.gc.easy.flv.factories.ConverterFactories; import com.gc.easy.flv.factories.ConverterFactories;
import com.gc.easy.flv.service.IFLVService; import com.gc.easy.flv.service.IFLVService;
import com.gc.easy.flv.service.IOpenFLVService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -28,11 +29,11 @@ public class FLVService implements IFLVService {
private ConcurrentHashMap<String, Converter> converters = new ConcurrentHashMap<>(); private ConcurrentHashMap<String, Converter> converters = new ConcurrentHashMap<>();
@Override @Override
public void open(String url, HttpServletResponse response, HttpServletRequest request) { public void open(String url, HttpServletResponse response, HttpServletRequest request,IOpenFLVService openFLVService) {
open(null,url,response,request); open(null,url,response,request,openFLVService);
} }
@Override @Override
public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request) { public void open(Integer channel, String url, HttpServletResponse response, HttpServletRequest request, IOpenFLVService openFLVService) {
String key = md5(url); String key = md5(url);
AsyncContext async = request.startAsync(); AsyncContext async = request.startAsync();
async.setTimeout(0); async.setTimeout(0);
@ -47,7 +48,7 @@ public class FLVService implements IFLVService {
} else { } else {
List<AsyncContext> outs = new ArrayList<>(); List<AsyncContext> outs = new ArrayList<>();
outs.add(async); outs.add(async);
ConverterFactories c = new ConverterFactories(url, key, converters, outs); ConverterFactories c = new ConverterFactories(url, key, converters, outs,openFLVService);
c.start(); c.start();
converters.put(key, c); converters.put(key, c);
} }