websocket播放rtsp方案之websocket按帧播放rtsp

1 回顾

        上篇文章简单介绍了websocket的使用,有了这个基础我们就可以继续今天的内容了,原本想跳过websocket的介绍,但因为自己以前在项目中也没有使用过,就顺道说一说。  

        不废话,上才艺!

2 代码实现

因为在上一篇文章中有了导包与配置本文就跳过该内容!直接上方案demo代码。

2.1 websocket

@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);
	}
}

2.2 rtsp流转换为图片通过websocket发送给前端展示

/**
 *  获取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;
                    }
                }
            }
        }
    }

}

2.3 几个使用到的类

/**
 * 图片转码器
 */
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);
        }
    }

3 测试验证

@Slf4j
@Controller
public class IndexController {
    @Autowired
    RTSPToImage RTSPToImage;

    @GetMapping("/test")
    public void test() {
        RTSPToImage.live();
        return;
    }
}

我们在websocket中连接后即可获取到返给前端显示的图字节数组。

websocket播放rtsp方案之websocket按帧播放rtsp_第1张图片

最后等前端哥们儿把前端代码实现了看能不能搞到前端代码;写个完整的demo

你可能感兴趣的:(rtsp)