1.maven依賴
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.1</version> <type>pom</type> </dependency>
2.線程類
1 package com.bs.thread; 2 3 import com.bs.controller.BsDataController; 4 import org.bytedeco.javacv.FFmpegFrameGrabber; 5 import org.bytedeco.javacv.Frame; 6 import org.bytedeco.javacv.FrameGrabber; 7 import org.bytedeco.javacv.Java2DFrameConverter; 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; 10 import org.springframework.scheduling.annotation.Async; 11 import javax.imageio.ImageIO; 12 import java.awt.image.BufferedImage; 13 import java.io.ByteArrayOutputStream; 14 import java.io.IOException; 15 16 public class RtspToJpgThread extends Thread { 17 18 public String FLAG="CLOSE"; 19 20 private String rtspUrl; 21 22 private String rtspTransportType="udp"; 23 24 private FFmpegFrameGrabber grabber; 25 26 private final Logger log = LoggerFactory.getLogger(this.getClass()); 27 28 private boolean isStart = false; 29 30 /** 31 * 視頻幀率 32 */ 33 private int frameRate = 30; 34 /** 35 * 視頻寬度 36 */ 37 private int frameWidth = 480; 38 /** 39 * 視頻高度 40 */ 41 private int frameHeight = 270; 42 43 public RtspToJpgThread(String rtspUrl){ 44 this.rtspUrl=rtspUrl; 45 } 46 47 @Override 48 public void run() { 49 live(); 50 } 51 52 53 54 /** 55 * 開啟獲取rtsp流,通過websocket傳輸數據 56 */ 57 @Async 58 public void live() { 59 log.info("連接rtsp:"+rtspUrl+",開始創建grabber"); 60 grabber = createGrabber(rtspUrl); 61 if (grabber != null) { 62 log.info("創建grabber成功"); 63 } else { 64 log.info("創建grabber失敗"); 65 } 66 startCameraPush(); 67 } 68 69 /** 70 * 構造視頻抓取器 71 * 72 * @param rtsp 拉流地址 73 * @return 74 */ 75 public FFmpegFrameGrabber createGrabber(String rtsp) { 76 // 獲取視頻源 77 try { 78 FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(rtsp); 79 grabber.setOption("rtsp_transport", rtspTransportType); 80 //設置幀率 81 grabber.setFrameRate(frameRate); 82 //設置獲取的視頻寬度 83 grabber.setImageWidth(frameWidth); 84 //設置獲取的視頻高度 85 grabber.setImageHeight(frameHeight); 86 //設置視頻bit率 87 grabber.setVideoBitrate(2000000); 88 return grabber; 89 } catch (FrameGrabber.Exception e) { 90 log.error("創建解析rtsp FFmpegFrameGrabber 失敗"); 91 log.error("create rtsp FFmpegFrameGrabber exception: ", e); 92 return null; 93 } 94 } 95 96 /** 97 * 推送圖片(攝像機直播) 98 */ 99 public void startCameraPush() { 100 Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter(); 101 while (true) { 102 if (grabber == null) { 103 log.info("重試連接rtsp:"+rtspUrl+",開始創建grabber"); 104 grabber = createGrabber(rtspUrl); 105 log.info("創建grabber成功"); 106 } 107 try { 108 if (grabber != null && !isStart) { 109 grabber.start(); 110 isStart = true; 111 log.info("啟動grabber成功"); 112 } 113 if (grabber != null) { 114 Frame frame = grabber.grabImage(); 115 if (null == frame) { 116 continue; 117 } 118 BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame); 119 byte[] bytes = imageToBytes(bufferedImage, "jpg"); 120 //使用websocket發送視頻幀數據 121 if("OPEN".equals(FLAG)){ 122 //log.info("============ 線程"+rtspUrl+"發出數據 ============"); 123 BsDataController.ws.sendAllByObject(bytes); 124 } 125 126 } 127 } catch (FrameGrabber.Exception | RuntimeException e) { 128 log.error("因為異常,grabber關閉,rtsp連接斷開,嘗試重新連接"); 129 log.error("exception : " , e); 130 if (grabber != null) { 131 try { 132 grabber.stop(); 133 } catch (FrameGrabber.Exception ex) { 134 log.error("grabber stop exception: ", ex); 135 } finally { 136 grabber = null; 137 isStart = false; 138 } 139 } 140 } 141 } 142 } 143 144 /** 145 * 圖片轉字節數組 146 * 147 * @param bImage 圖片數據 148 * @param format 格式 149 * @return 圖片字節碼 150 */ 151 private byte[] imageToBytes(BufferedImage bImage, String format) { 152 ByteArrayOutputStream out = new ByteArrayOutputStream(); 153 try { 154 ImageIO.write(bImage, format, out); 155 } catch (IOException e) { 156 log.error("bufferImage 轉 byte 數組異常"); 157 log.error("bufferImage transfer byte[] exception: ", e); 158 return null; 159 } 160 return out.toByteArray(); 161 } 162 }