上篇文章简单介绍了websocket的使用,有了这个基础我们就可以继续今天的内容了,原本想跳过websocket的介绍,但因为自己以前在项目中也没有使用过,就顺道说一说。
不废话,上才艺!
因为在上一篇文章中有了导包与配置本文就跳过该内容!直接上方案demo代码。
@Slf4j
@ServerEndpoint(value = "/webSocket", encoders = {ImageEncoder.class})
@Component
public class WebSocketReceiveMessage {
//用来存放每个客户端对应的WebSocketReceiveMessage对象,适用于同时与多个客户端通信
public static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>();
//与某个客户端的连接会话,通过它实现定向推送
private Session session;
/**
* 建立连接成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
// 添加到set中
webSocketSet.add(this);
log.info("用户连接成功!");
}
/**
* 关闭连接调用的方法
*/
@OnClose
public void onClose(Session closeSession){
webSocketSet.remove(this);
log.info("用户退出!");
}
/**
* 收到客户端消息调用的方法
*/
@OnMessage
public void onMessage(String message,Session mysession) throws Exception{
log.info("--------on message---{}----",message);
for (WebSocketReceiveMessage item: webSocketSet) {
item.sendAllMessage(message);
}
}
public static void sendAllByObject(Object message) {
if (!webSocketSet.isEmpty()) {
for (WebSocketReceiveMessage next : webSocketSet) {
next.sendMessageByObject(message);
}
}
}
public void sendMessageByObject(Object message) {
if (message != null) {
try {
this.session.getBasicRemote().sendObject(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void sendAllMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
}
/**
* 获取rtsp流,抓取每帧,通过websocket传递给前台显示
*/
@Slf4j
@Component
@EnableAsync
public class RTSPToImage {
@Value("${rtsp.url:rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=1}")
private String rtspUrl;
@Value("${rtsp.transport.type:udp}")
private String rtspTransportType;
/**
* 异步开启获取rtsp流,通过websocket传输数据
*/
@Async
public void live() {
log.info("开始创建grabber");
FFmpegFrameGrabber grabber = null;
try {
grabber = new FFmpegFrameGrabber(rtspUrl);
grabber.setOption("rtsp_transport", rtspTransportType);
//设置帧率
grabber.setFrameRate(25);
//设置获取的视频宽度
grabber.setImageWidth(996);
//设置获取的视频高度
grabber.setImageHeight(996);
//设置视频bit率
grabber.setVideoBitrate(2000000);
//设置日志等级
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
grabber.start();
log.info("创建并启动grabber成功");
}catch (Exception e){
e.printStackTrace();
}
//推送图片
Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();
while (true) {
try {
if (grabber != null) {
Frame frame = grabber.grabImage();
if (null == frame) {
continue;
}
BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", out);
//使用websocket发送视频帧数据
WebSocketReceiveMessage.sendAllByObject(new Image(out.toByteArray()));
}
} catch (Exception e) {
e.printStackTrace();
if (grabber != null) {
try {
grabber.stop();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
grabber = null;
}
}
}
}
}
}
/**
* 图片转码器
*/
public class ImageEncoder implements Encoder.Text {
@Override
public String encode(Image image) throws EncodeException {
if(image != null && !ArrayUtils.isEmpty(image.getImageByte())){
String base64Image= Base64.encode(image.getImageByte());
return JSON.toJSONString(new AjaxResult(AjaxResult.Type.SUCCESS,"获取帧成功",base64Image));
}
return JSON.toJSONString(new AjaxResult(AjaxResult.Type.ERROR,"获取帧失败",null));
}
@Override
public void init(EndpointConfig endpointConfig) {
}
@Override
public void destroy() {
}
}
/**
* 图片实体
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Image {
private byte[] imageByte;
}
/**
* 返回信息
*/
public class AjaxResult extends HashMap {
private static final long serialVersionUID = 1L;
//状态码
public static final String CODE = "code";
//返回信息
public static final String MSG = "msg";
//数据
public static final String DATA = "data";
/**
* 状态类型
*/
public enum Type {
SUCCESS(200),
ERROR(500);
private final int value;
Type(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
public AjaxResult(Type type, String msg, Object data) {
super.put(CODE, type.value);
super.put(MSG, msg);
if (ObjectUtils.isNotEmpty(data)) {
super.put(DATA, data);
}
}
@Slf4j
@Controller
public class IndexController {
@Autowired
RTSPToImage RTSPToImage;
@GetMapping("/test")
public void test() {
RTSPToImage.live();
return;
}
}
我们在websocket中连接后即可获取到返给前端显示的图字节数组。
最后等前端哥们儿把前端代码实现了看能不能搞到前端代码;写个完整的demo