日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring boot集成javacv + websocket实现实时视频推流回放(延时1-2秒)

發布時間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot集成javacv + websocket实现实时视频推流回放(延时1-2秒) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近項目需要實時直播和回放,集成海康威視攝像頭:(適合少量用戶,或者內部系統使用)

<!-- 視頻處理庫 --><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.1</version></dependency>

這里是利用javacv抓取rtsp地址的視頻流,通過轉換成圖片使用websocket實時推送

首先了解rtsp地址,這里舉例就用海康威視的規則

通道號下面詳細介紹 # 單播rtsp://{用戶名}:{密碼}@{IP地址}:{端口號}/Streaming/Channels/{通道號}?transportmode=unicast # 多播rtsp://{用戶名}:{密碼}@{IP地址}:{端口號}/Streaming/Channels/{通道號}?transportmode=multicast # 分時獲取rtsp://{用戶名}:{密碼}@{IP地址}:{端口號}/Streaming/tracks/{通道號}?starttime=20191008t063812z&endtime=20191008t064816z上面地址獲取不到時可以試試下面的其他版本地址:rtsp://{用戶名}:{密碼}@{IP地址}:{端口號}/Streaming/Unicast/channels/{通道號}rtsp://{用戶名}:{密碼}@{IP地址}:{端口號}/h264/{通道號}/main/av_stream

這里通道號分類是IP通道號和模擬通道號,如果是12年以前的老機器,地址建議使用最后一個獲取實時視頻

可以使用官方提供的java demo 來查看,測試是否能獲取視頻

這里有打包好的jar包和環境可以直接運行jar包使用,解壓后將里面內容放置在System32下,cmd執行jar

地址?百度網盤 請輸入提取碼? 密碼?67v1

下圖就是IP通道號 若只是Camera20 則為模擬通道號

通道號可以參考這里最新海康攝像機、NVR、流媒體服務器、回放取流RTSP地址規則說明 - github.com/starRTC - 博客園

接下來就是java代碼:

首先yml配置動態RTSP地址

myconfig:rtsp: rtsp://%s:%s@%s:%s/Streaming/Channels/%s01replay-rtsp: rtsp://%s:%s@%s:%s/Streaming/tracks/%s01?starttime=%s&endtime=%s

媒體工具類:

@Slf4j @Component public class MediaUtils {/*** 直播攝像機id集合,避免重復拉流*/private static Set<Long> liveSet = new ConcurrentSet<>();/*** 用于構造回放rtsp地址*/@Value("${myconfig.replay-rtsp}")private String rtspReplayPattern;/*** 視頻幀率*/public static int frameRate = 15;/*** 視頻寬度*/public static int frameWidth = 480;/*** 視頻高度*/public static int frameHeight = 270;/*** 攝像機直播* @param rtsp 攝像機直播地址* @param cameraName 攝像機名稱* @param cameraId 攝像機id* @throws Exception e*/@Asyncpublic void live(String rtsp, String cameraName, Long cameraId) throws Exception {if (liveSet.contains(cameraId)) {return;}liveSet.add(cameraId);FFmpegFrameGrabber grabber = createGrabber(rtsp);startCameraPush(grabber, cameraName, cameraId);}/*** 構造視頻抓取器* @param rtsp 拉流地址* @return*/public FFmpegFrameGrabber createGrabber(String rtsp) {// 獲取視頻源FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtsp);grabber.setOption("rtsp_transport","tcp");//設置幀率grabber.setFrameRate(frameRate);//設置獲取的視頻寬度grabber.setImageWidth(frameWidth);//設置獲取的視頻高度grabber.setImageHeight(frameHeight);//設置視頻bit率grabber.setVideoBitrate(2000000);return grabber;}/*** 推送圖片(攝像機直播)* @param grabber* @throws Exception*/@Asyncpublic void startCameraPush(FFmpegFrameGrabber grabber, String cameraName, Long cameraId) throws Exception {Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();try {grabber.start();int i = 1;while (liveSet.contains(cameraId)) {Frame frame = grabber.grabImage();if (null == frame) {continue;}BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame);byte[] bytes = imageToBytes(bufferedImage, "jpg");//使用websocket發送圖片數據LiveWebsocket.sendImage(ByteBuffer.wrap(bytes), cameraId);}} finally {if (grabber != null) {grabber.stop();}}}/*** 圖片轉字節數組* @param bImage 圖片數據* @param format 格式* @return 圖片字節碼*/private byte[] imageToBytes(BufferedImage bImage, String format) {ByteArrayOutputStream out = new ByteArrayOutputStream();try {ImageIO.write(bImage, format, out);} catch (IOException e) {e.printStackTrace();}return out.toByteArray();}/*** 回放視頻播放超期檢查* @param userId 用戶id* @return*/private boolean replayOverTime(Integer userId) {if (replayMap.containsKey(userId)) {Long updateTime = replayMap.get(userId);if (updateTime != null) {if (System.currentTimeMillis() - updateTime < 10000) {return false;}}}return true;}/*** 構造監控回放查詢字段* @param date 時間* @param start* @return*/private String formatPullTime(Date date, boolean start) {Calendar calendar = Calendar.getInstance();if (date != null) {calendar.setTime(date);}if (start) {calendar.add(Calendar.SECOND, -10);} else {calendar.add(Calendar.SECOND, 10);}//海康威視取回放的時間格式SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd#HHmmss$");String ret = sdf.format(calendar.getTime());ret = ret.replace("#", "t");ret = ret.replace("$", "z");return ret;}/*** 回放視頻播放超期檢查* @param userId 用戶id* @return*/private boolean replayOverTime(Integer userId) {if (replayMap.containsKey(userId)) {Long updateTime = replayMap.get(userId);if (updateTime != null) {if (System.currentTimeMillis() - updateTime < 10000) {return false;}}}return true;}/*** 監控回放* @param userId 用戶id websocket 用戶編號,作為心跳標識檢測心跳* @param startDate 起始時間* @param endDate 結束時間* @param channel 通道號* @param username 用戶名* @param password 密碼* @param ip* @param port* @throws Exception e*/@Asyncpublic void replayVideo(Integer userId, Date startDate, Date endDate,Integer channel, String username, String password, String ip, Integer port) throws Exception {Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();FFmpegFrameGrabber grabber = null;try {if (grabber != null) {grabber.stop();}if (channel != null) {String st = formatPullTime(startDate, true);String et = formatPullTime(endDate, false);//構造rtsp回放流地址 username password ip portString rtsp = String.format(rtspReplayPattern,username,password,ip,port,channel,st,et);if (grabber != null) {grabber.stop();}grabber = createGrabber(rtsp);grabber.setTimeout(10000);grabber.start();//心跳消失停止推流while (!replayOverTime(userId)) {Frame frame = grabber.grabImage();if (null == frame) {continue;}BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame);byte[] bytes = imageToBytes(bufferedImage, "jpg");ByteBuffer buffer = ByteBuffer.wrap(bytes);//使用websocket發送圖片數據ReplayWebsocke.sendImage(buffer, userId);}}} catch (Exception e){e.printStackTrace();} finally {if (grabber != null) {grabber.stop();}}} }

視頻水印添加:

@Component public class ImgMarker {/*** 視頻水印圖片*/BufferedImage logoImg;private Font font;private Font font2;private FontDesignMetrics metrics;private FontDesignMetrics metrics2;@PostConstructprivate void init() {// 加水印圖片try {ImageIO.read(new File("圖片地址"));} catch (IOException e) {e.printStackTrace();}font = new Font("黑體", Font.BOLD, 16);font2 = new Font("黑體", Font.BOLD, 24);metrics = FontDesignMetrics.getMetrics(font);metrics2 = FontDesignMetrics.getMetrics(font2);}/*** 加水印* @param bufImg 視頻幀*/public void mark(BufferedImage bufImg) {if (bufImg == null || logoImg == null) {return;}int width = bufImg.getWidth();int height = bufImg.getHeight();Graphics2D graphics = bufImg.createGraphics();graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));//設置圖片背景graphics.drawImage(bufImg, 0, 0, width, height, null);//添加右上角水印graphics.drawImage(logoImg, width - 130, 8, 121, 64, null);}/**** @param bufImg 視頻幀*/public void markTag(BufferedImage bufImg, String msg, int videoWidth) {int width = bufImg.getWidth();int height = bufImg.getHeight();Graphics2D graphics = bufImg.createGraphics();graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));//設置圖片背景graphics.drawImage(bufImg, 0, 0, width, height, null);//設置由上方標簽號graphics.setColor(Color.orange);if (videoWidth <= 400) {graphics.setFont(font2);graphics.drawString(msg, width - metrics2.stringWidth(tagId) - 24, metrics2.getAscent());} else {graphics.setFont(font);graphics.drawString(msg, width - metrics.stringWidth(msg) - 12, metrics.getAscent());}graphics.dispose();}}

至此可以調用了(還有其他方式是直接調用SDK和推送視頻流媒體服務器,后續文章更新)

websocket 涉及到高并發阻塞情況 后續更新,建議使用netty

總結

以上是生活随笔為你收集整理的spring boot集成javacv + websocket实现实时视频推流回放(延时1-2秒)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美一区二区网站 | 一级艳片新婚之夜 | 毛片毛片 | 成人女同在线观看 | 国产com| 视频国产在线 | 欧洲精品视频在线 | 动漫美女放屁 | 亚洲精品大片www | 成人无高清96免费 | 黑人一区二区三区四区五区 | 国产精品美女一区 | 国产精品一级黄色片 | 最新激情网 | 黄色日批 | 女人张开腿让男人插 | 91精品国产综合久久福利软件 | 欧美人与性动交a欧美精品 日韩免费高清视频 | 中文字幕免费在线播放 | 爱综合网 | 国产成人精品在线播放 | 国产呦小j女精品视频 | 亚洲欧美日韩中文在线 | av乱码 | 日韩女优一区 | 黄色第一网站 | 欧美性猛交久久久久 | 亚洲精品网站在线观看 | 日韩成人av一区二区 | 伊人日本 | 色欲久久久天天天综合网精品 | 97青青草| 香蕉一区二区三区四区 | 激情国产一区 | www.超碰在线.com | 韩国19主播内部福利vip | 秋霞国产一区 | 亚洲永久无码7777kkk | 东京干手机福利视频 | 美女扒开粉嫩的尿囗给男生桶 | 亚洲一区二区三区电影在线观看 | 天堂99| 国产又黄又粗又猛又爽视频 | 亚洲国产91 | 欧美1| 伊人狼人影院 | 国产免费视屏 | 欧美最猛性xxxx | 成人做爰免费视频免费看 | 国产大学生av | 手机在线看永久av片免费 | 国产精品hd | www.天天操| 欧美精品不卡 | 亚洲精品亚洲人成人网 | 可以免费看的黄色 | 少妇在军营h文高辣 | 岛国精品一区二区三区 | 一本色道久久hezyo加勒比 | 2020av在线 | 理想之城连续剧40集免费播放 | 在线免费黄色 | 成人性爱视频在线观看 | 日本一本久久 | 精品无码一区二区三区爱欲 | 久久影院午夜理论片无码 | 欧美三级韩国三级日本三斤 | 黄色小视频入口 | 不卡日韩| 久久久国产精品免费 | 韩国成人理伦片免费播放 | 一区二区伊人 | 色天天色 | 99久久伊人| 国产人妖ts | 国产乱妇无码大片在线观看 | 日本黄色片视频 | 成年人黄色免费视频 | 少妇床戏av| a天堂中文字幕 | 欧美日韩成人在线视频 | 巨乳女教师的诱惑 | 公侵犯一区二区三区 | 色中文字幕在线观看 | 一本色道久久综合亚洲精品按摩 | 环太平洋3:泰坦崛起 | 久久金品| 极品美女被c | 成人爱爱视频 | 在线观看免费国产视频 | 伊人最新网址 | 在线观看日韩av | 精品自拍一区 | 污视频在线观看网址 | 亚洲aⅴ在线 | 91网址在线播放 | 久久久久久久久久久97 | 天天躁日日躁狠狠躁伊人 | 成人一级视频 |