返回顶部
首页 > 资讯 > 后端开发 > JAVA >java 实现监控rtsp流转flv,实现前端播放(前后端代码都有)
  • 884
分享到

java 实现监控rtsp流转flv,实现前端播放(前后端代码都有)

音视频springbootjavaPoweredby金山文档 2023-09-01 21:09:28 884人浏览 薄情痞子
摘要

一.服务代码 目录结构 Maven配置文件引入坐标:         org.bytedeco javacv-platfORM

一.服务代码

  1. 目录结构

  1. Maven配置文件引入坐标:

                    org.bytedeco            javacv-platfORM            1.5.1                            javax.xml.bind            jaxb-api            2.3.0        
  1. 服务器代码

controller层:

import com.xr.WEB.rtspconverterflvSpringBootstarter.service.IFLVService;import io.swagger.annotations.Api;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.Http.httpservletRequest;import javax.servlet.http.HttpServletResponse;@Api(tags = "flv")@RequestMapping("/flv")@RestControllerpublic class FLVController {    @Autowired    private IFLVService service;    @GetMapping()    public void open4(HttpServletResponse response,                      HttpServletRequest request) {        String test = "rtsp://admin:sdxr@2022@192.168.0.205:554";        service.open(test, response, request);    }}

config层:

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.TaskScheduler;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@Configuration@EnableSchedulingpublic class SchedulerConfig {    @Bean    public TaskScheduler taskScheduler() {        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();        // 线程池大小        scheduler.setPoolSize(3);        // 线程名字前缀        scheduler.setThreadNamePrefix("task-thread-");        return scheduler;    }}

factories层:

public enum ConverterState {    INITIAL, OPEN, CLOSE, ERROR, RUN}
import javax.servlet.AsyncContext;import java.io.IOException;public interface Converter {        public String geTKEy();        public String getUrl();        public void addOutputStreamEntity(String key, AsyncContext entity) throws IOException;        public void exit();        public void start();}
import com.alibaba.fastJSON.util.IOUtils;import lombok.extern.slf4j.Slf4j;import org.bytedeco.FFmpeg.avcodec.AVPacket;import org.bytedeco.ffmpeg.global.avcodec;import org.bytedeco.javacv.FFmpegFrameGrabber;import org.bytedeco.javacv.FFmpegFrameRecorder;import javax.servlet.AsyncContext;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Iterator;import java.util.List;import java.util.Map;@Slf4jpublic class ConverterFactories extends Thread implements Converter {    public volatile boolean runing = true;        private FFmpegFrameGrabber grabber;        private FFmpegFrameRecorder recorder;        private byte[] headers;        private ByteArrayOutputStream stream;        private String url;        private List outEntitys;        private String key;        private Map factories;    public ConverterFactories(String url, String key, Map factories, List outEntitys) {        this.url = url;        this.key = key;        this.factories = factories;        this.outEntitys = outEntitys;    }    @Override    public void run() {        boolean isCloseGrabberAndResponse = true;        try {            grabber = new FFmpegFrameGrabber(url);            if ("rtsp".equals(url.substring(0, 4))) {                grabber.setOption("rtsp_transport", "tcp");                grabber.setOption("stimeout", "5000000");            }            grabber.start();            if (avcodec.AV_CODEC_ID_H264 == grabber.getVideoCodec()                    && (grabber.getAudioChannels() == 0 || avcodec.AV_CODEC_ID_AAC == grabber.getAudioCodec())) {                log.info("this url:{} converterFactories start", url);                // 来源视频H264格式,音频AAC格式                // 无须转码,更低的资源消耗,更低的延迟                stream = new ByteArrayOutputStream();                recorder = new FFmpegFrameRecorder(stream, grabber.getImageWidth(), grabber.getImageHeight(),                        grabber.getAudioChannels());                recorder.setInterleaved(true);                recorder.setVideoOption("preset", "ultrafast");                recorder.setVideoOption("tune", "zerolatency");                recorder.setVideoOption("crf", "25");                recorder.setFrameRate(grabber.getFrameRate());                recorder.setSampleRate(grabber.getSampleRate());                if (grabber.getAudioChannels() > 0) {                    recorder.setAudioChannels(grabber.getAudioChannels());                    recorder.setAudioBitrate(grabber.getAudioBitrate());                    recorder.setAudioCodec(grabber.getAudioCodec());                }                recorder.setFormat("flv");                recorder.setVideoBitrate(grabber.getVideoBitrate());                recorder.setVideoCodec(grabber.getVideoCodec());                recorder.start(grabber.getFormatContext());                if (headers == null) {                    headers = stream.toByteArray();                    stream.reset();                    writeResponse(headers);                }                int nullNumber = 0;                while (runing) {                    AVPacket k = grabber.grabPacket();                    if (k != null) {                        try {recorder.recordPacket(k);                        } catch (Exception e) {                        }                        if (stream.size() > 0) {byte[] b = stream.toByteArray();stream.reset();writeResponse(b);if (outEntitys.isEmpty()) {    log.info("没有输出退出");    break;}                        }                        avcodec.av_packet_unref(k);                    } else {                        nullNumber++;                        if (nullNumber > 200) {break;                        }                    }                    Thread.sleep(5);                }            } else {                isCloseGrabberAndResponse = false;                // 需要转码为视频H264格式,音频AAC格式                ConverterTranFactories c = new ConverterTranFactories(url, key, factories, outEntitys, grabber);                factories.put(key, c);                c.start();            }        } catch (Exception e) {            log.error(e.getMessage(), e);        } finally {            closeConverter(isCloseGrabberAndResponse);            completeResponse(isCloseGrabberAndResponse);            log.info("this url:{} converterFactories exit", url);        }    }        public void writeResponse(byte[] b) {        Iterator it = outEntitys.iterator();        while (it.hasNext()) {            AsyncContext o = it.next();            try {                o.getResponse().getOutputStream().write(b);            } catch (Exception e) {                log.info("移除一个输出");                it.remove();            }        }    }        public void closeConverter(boolean isCloseGrabberAndResponse) {        if (isCloseGrabberAndResponse) {            IOUtils.close(grabber);            factories.remove(this.key);        }        IOUtils.close(recorder);        IOUtils.close(stream);    }        public void completeResponse(boolean isCloseGrabberAndResponse) {        if (isCloseGrabberAndResponse) {            Iterator it = outEntitys.iterator();            while (it.hasNext()) {                AsyncContext o = it.next();                o.complete();            }        }    }    @Override    public String getKey() {        return this.key;    }    @Override    public String getUrl() {        return this.url;    }    @Override    public void addOutputStreamEntity(String key, AsyncContext entity) throws IOException {        if (headers == null) {            outEntitys.add(entity);        } else {            entity.getResponse().getOutputStream().write(headers);            entity.getResponse().getOutputStream().flush();            outEntitys.add(entity);        }    }    @Override    public void exit() {        this.runing = false;        try {            this.join();        } catch (Exception e) {            log.error(e.getMessage(), e);        }    }}
import com.alibaba.fastjson.util.IOUtils;import lombok.extern.slf4j.Slf4j;import org.bytedeco.ffmpeg.global.avcodec;import org.bytedeco.javacv.FFmpegFrameGrabber;import org.bytedeco.javacv.FFmpegFrameRecorder;import org.bytedeco.javacv.Frame;import javax.servlet.AsyncContext;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Iterator;import java.util.List;import java.util.Map;@Slf4jpublic class ConverterTranFactories extends Thread implements Converter {    public volatile boolean runing = true;        private FFmpegFrameGrabber grabber;        private FFmpegFrameRecorder recorder;        private byte[] headers;        private ByteArrayOutputStream stream;        private String url;        private List outEntitys;        private String key;        private Map factories;    public ConverterTranFactories(String url, String key, Map factories,            List outEntitys, FFmpegFrameGrabber grabber) {        this.url = url;        this.key = key;        this.factories = factories;        this.outEntitys = outEntitys;        this.grabber = grabber;    }    @Override    public void run() {        try {            log.info("this url:{} converterTranFactories start", url);            grabber.setFrameRate(25);            if (grabber.getImageWidth() > 1920) {                grabber.setImageWidth(1920);            }            if (grabber.getImageHeight() > 1080) {                grabber.setImageHeight(1080);            }            stream = new ByteArrayOutputStream();            recorder = new FFmpegFrameRecorder(stream, grabber.getImageWidth(), grabber.getImageHeight(),                    grabber.getAudioChannels());            recorder.setInterleaved(true);            recorder.setVideoOption("preset", "ultrafast");            recorder.setVideoOption("tune", "zerolatency");            recorder.setVideoOption("crf", "25");            recorder.setGopSize(50);            recorder.setFrameRate(25);            recorder.setSampleRate(grabber.getSampleRate());            if (grabber.getAudioChannels() > 0) {                recorder.setAudioChannels(grabber.getAudioChannels());                recorder.setAudioBitrate(grabber.getAudioBitrate());                recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);            }            recorder.setFormat("flv");            recorder.setVideoBitrate(grabber.getVideoBitrate());            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);            recorder.start();            if (headers == null) {                headers = stream.toByteArray();                stream.reset();                writeResponse(headers);            }            int nullNumber = 0;            while (runing) {                // 抓取一帧                Frame f = grabber.grab();                if (f != null) {                    try {                        // 转码                        recorder.record(f);                    } catch (Exception e) {                    }                    if (stream.size() > 0) {                        byte[] b = stream.toByteArray();                        stream.reset();                        writeResponse(b);                        if (outEntitys.isEmpty()) {log.info("没有输出退出");break;                        }                    }                } else {                    nullNumber++;                    if (nullNumber > 200) {                        break;                    }                }                Thread.sleep(5);            }        } catch (Exception e) {            log.error(e.getMessage(), e);        } finally {            closeConverter();            completeResponse();            log.info("this url:{} converterTranFactories exit", url);            factories.remove(this.key);        }    }        public void writeResponse(byte[] b) {        Iterator it = outEntitys.iterator();        while (it.hasNext()) {            AsyncContext o = it.next();            try {                o.getResponse().getOutputStream().write(b);            } catch (Exception e) {                log.info("移除一个输出");                it.remove();            }        }    }        public void closeConverter() {        IOUtils.close(grabber);        IOUtils.close(recorder);        IOUtils.close(stream);    }        public void completeResponse() {        Iterator it = outEntitys.iterator();        while (it.hasNext()) {            AsyncContext o = it.next();            o.complete();        }    }    @Override    public String getKey() {        return this.key;    }    @Override    public String getUrl() {        return this.url;    }    @Override    public void addOutputStreamEntity(String key, AsyncContext entity) throws IOException {        if (headers == null) {            outEntitys.add(entity);        } else {            entity.getResponse().getOutputStream().write(headers);            entity.getResponse().getOutputStream().flush();            outEntitys.add(entity);        }    }    @Override    public void exit() {        this.runing = false;        try {            this.join();        } catch (Exception e) {            log.error(e.getMessage(), e);        }    }}

result层:

import com.alibaba.fastjson.JSONObject;import java.io.Serializable;import java.util.HashMap;public class JsonResult extends HashMap implements Serializable {    private static final long serialVersionUID = 1L;    public static final int SUCCESS = 200;    public JsonResult() {    }        public static JsonResult ok() {        return ok("操作成功");    }        public static JsonResult okFallBack() {        return okFallBack("操作成功");    }        public JsonResult put(Object obj) {        return this.put("data", obj);    }        public static JsonResult ok(String message) {        return result(200, message);    }        public static JsonResult okFallBack(String message) {        return result(205, message);    }        public static JsonResult result(int code, String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", code);        jsonResult.put("message", message);        return jsonResult;    }        public static JsonResult error() {        return error("操作失败");    }        public static JsonResult error(String message) {        return error(500, message);    }        public static JsonResult error(int code, String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", code);        jsonResult.put("message", message);        return jsonResult;    }        public JsonResult setCode(int code) {        super.put("status", code);        return this;    }        public JsonResult setMessage(String message) {        super.put("message", message);        return this;    }        @Override    public JsonResult put(String key, Object object) {        super.put(key, object);        return this;    }        public static JsonResult forbidden(String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", 401);        jsonResult.put("message", message);        return jsonResult;    }    @Override    public String toString() {        return JSONObject.toJSONString(this);    }    public JSONObject toJSONObject() {        return JSONObject.parseObject(toString());    }}

service层:

import com.alibaba.fastjson.JSONObject;import java.io.Serializable;import java.util.HashMap;public class JsonResult extends HashMap implements Serializable {    private static final long serialVersionUID = 1L;    public static final int SUCCESS = 200;    public JsonResult() {    }        public static JsonResult ok() {        return ok("操作成功");    }        public static JsonResult okFallBack() {        return okFallBack("操作成功");    }        public JsonResult put(Object obj) {        return this.put("data", obj);    }        public static JsonResult ok(String message) {        return result(200, message);    }        public static JsonResult okFallBack(String message) {        return result(205, message);    }        public static JsonResult result(int code, String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", code);        jsonResult.put("message", message);        return jsonResult;    }        public static JsonResult error() {        return error("操作失败");    }        public static JsonResult error(String message) {        return error(500, message);    }        public static JsonResult error(int code, String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", code);        jsonResult.put("message", message);        return jsonResult;    }        public JsonResult setCode(int code) {        super.put("status", code);        return this;    }        public JsonResult setMessage(String message) {        super.put("message", message);        return this;    }        @Override    public JsonResult put(String key, Object object) {        super.put(key, object);        return this;    }        public static JsonResult forbidden(String message) {        JsonResult jsonResult = new JsonResult();        jsonResult.put("timestamp", System.currentTimeMillis());        jsonResult.put("status", 401);        jsonResult.put("message", message);        return jsonResult;    }    @Override    public String toString() {        return JSONObject.toJSONString(this);    }    public JSONObject toJSONObject() {        return JSONObject.parseObject(toString());    }}
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public interface IFLVService {        public void open(String url, HttpServletResponse response, HttpServletRequest request);}

二.客户端代码基于flv.js进行播放

                                    Document                                            

这里因为浏览器把自动播放给禁止了,加了个按钮点击事件

https://www.bootcdn.cn/

引入的flv.js文件在如下网站下载即可:

来源地址:https://blog.csdn.net/seeblood/article/details/128964479

--结束END--

本文标题: java 实现监控rtsp流转flv,实现前端播放(前后端代码都有)

本文链接: https://lsjlt.com/news/389699.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作