H5之webcoekt播放JPEG图片流

2023-11-13

一、简介

既然webcoekt是基于tcp连接的,理论上讲所有的浏览器是可以私有协议处理二进制的,如果我们需要播放视频,我们可以将视频数据在后端解码后直接将图片推送到webcoekt前端,然后前端通过websocket接收图片然后将图片显示到img或canvas中即可,当然这个是我自己设想的,也是应该可以做的到了,做到如下需要以下技术支持:

  • 后端直接ffmpeg转码为jpeg图片流
  • 后端定制播放协议包括基本指令如play、stop、pause、faster、slower
  • 后端需要提供websocket支持发送图片流到前端
  • 前端需要接受图片流并显示出来

后端ffmpeg解码这里就不说明了,我有很多库,需要的单独联系我购买,前端的显示jpg流,这里要借助前端显示图片放的做法,使用图片base64数据!前端HTML显示二进制jpeg图片:图片流=>二进制转image的base64编码=>设置到img的src中,如前端代码

<body>
    <img id="player" style="width:704px;height:576px"/>
</body>

二进制通过arraybuffer转base64

function arrayBufferToBase64(buffer) {
        var binary = '';
        var bytes = new Uint8Array(buffer);
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    }

最后显示:

	  var player = document.getElementById('player');
      var url= arrayBufferToBase64(data);
      player.src='data:image/jpeg;base64,'+url;

当然,还有其他的方式:

var wsCtrl = new WebSocket("ws://127.0.0.1/ctrl/");
//Establish channel code
....
var wsVideo = new WebSocket("ws://127.0.0.1/video/channel1");
wsVideo.onmessage = function(evt)
{
   //Method 1
   document.getElementById("img1").src = URL.createObjectURL(evt.data);
   
   //Method 2
   var read = new FileReader();
   read.onload = function(e)
   {
      document.getElementById("img2").src = e.target.result;
   }
   read.readAsDataURL(evt.data);
}

ws.onmessage = function(evt) {
	if(typeof(evt.data)=="string"){
		//textHandler(JSON.parse(evt.data));
	}else{
	    var reader = new FileReader();
		reader.onload = function(evt){
			if(evt.target.readyState == FileReader.DONE){
				var url = evt.target.result;
				alert(url);
				var img = document.getElementById("imgDiv");
				img.innerHTML = "<img src = "+url+" />";
			}
		}
    	reader.readAsDataURL(evt.data);
	}
};  

关于c++的websocket开源工程:websocketpp、QWebSocketServer

二、websocket播放图片流

多说无益,还不如痛痛快快的来一把,为了减低复杂度,我用java的websocket来实现图片流的发送(当然c++的库我也一个实战项目中用过的名为WebSocket的封装的dll工程项目,需要的自行私下购买源码),前端使用一个img标签展示图片,这里说明一下,后台模拟发送图片(这里仅仅是图片,不是流,如果是流直接连续不断发送即可需要ffmpeg转码)

首先前端的代码如下所示:

<!DOCTYPE html>
<html lang="en">
	<head>
	    <meta charset="UTF-8">
	    <title>websocket显示二进制图片流</title>
	    <style type="text/css">
	    </style>
	</head>
	<script src="jquery.min.js"></script>
	<script>
	$(document).ready(function(){
		$("#send").click(function(){
		  //var content = $("#content").val();
		  $.ajax({
			  url: "/test/send",
			  data: {
				 //content: content
				 content: ""
			  },
			  success: function( result ) {
				  console.log("请求成功!");
			  }
			});
	  });
	});
	</script>
	<body>
		<h1>WebSocket播放图片</h1>
		<img id="player" style="width:500px;height:400px"/><br/>
		<button id="send">请求图片</button>
	</body>
	<script type="application/javascript">
	    var websocket = {
	        send: function (str) {
	        }
	    };
	    window.onload = function () {
	        if (!'WebSocket' in window) return;
	        webSocketInit();
	    };
	    function webSocketInit() {
	    	// 连接到服务端端点
	        websocket = new WebSocket("ws://127.0.0.1:8080/image/show");
	        // 成功建立连接
	        websocket.onopen = function () {
	        	console.log("成功连接到服务器");
	            websocket.send("成功连接到服务器");
	        };
	        // 接收到消息
	        websocket.onmessage = function (event) {
	        	// 文本数据包
	        	if(typeof(event.data)=="string"){
	        		// JSON.parse(evt.data)
	        		console.log("收到服务端发送的消息:" + event.data);
	        	// 图片数据包Blob
	        	}else{
	        	    var reader = new FileReader();
	        		reader.onload = function(evt){
	        			if(evt.target.readyState == FileReader.DONE){
	        				// base64数据
	        				var url = evt.target.result;
	        				document.getElementById("player").src = url;
	        			}
	        		}
	            	reader.readAsDataURL(event.data);
	        	}
	        };
	        // 连接发生错误
	        websocket.onerror = function () {
	            console.log("WebSocket连接发生错误");
	        };
	        // 连接关闭
	        websocket.onclose = function () {
	        	console.log("WebSocket连接关闭");
	        };
	        // 监听窗口关闭事件,当窗口关闭时,主动关闭websocket连接
	        window.onbeforeunload = function () {
	            websocket.close()
	        };
	    }
	</script>
</html>

每次点击发送的时候就向后台请求一张图,后台将改图发送出去(我简单的使用websocket群发,可以使用websocket的可变参数将websocket和http关联起来,这个应该很容易我这里不再赘述,不了解的进群讨论)

package com.easystudy.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Random;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.easystudy.websocket.ImgEndPoint;

/**
 * @文件名称: TestController.java
 * @功能描述: 图片流请求请求发送接口(websocket发送图片到web端)
 * @版权信息:  www.easystudy.com
 * @技术交流:  961179337(QQ群)
 * @编写作者:  lixx2048@163.com
 * @联系方式:  941415509(QQ)
 * @开发日期:  2020年9月21日
 * @历史版本: V1.0 
 * @备注信息:
 */
@RestController
@RequestMapping("/test")
public class TestController {
	
	/**
	 * @功能描述: 发送请求接口
	 * @版权信息:  www.easystudy.com
	 * @编写作者:  lixx2048@163.com
	 * @开发日期:  2020年9月21日
	 * @备注信息:
	 */
	@SuppressWarnings("unused")
	@GetMapping("/send")
	public String reponseMsgToClient(@RequestParam(name="content", required = true)String content) throws Exception{
		System.out.println("开始发送图片数据");
		
		// 随机选择一张图片发送
		int index = new Random().nextInt(4) + 1;
		String imgName = index + ".jpg";
		
		// 判断图片是否存在
		URL url = getClass().getClassLoader().getResource(imgName);
		File file = new File(url.getFile());
		if (!file.exists()) {
			return "未找到图片!";
		}
		
		// 创建输入图片流
		InputStream in = new FileInputStream(file);
		if (null == in) {
			return "打开文件失败!";
		}
		
		// 读取图片数据
		int size = (int)file.length();
		byte[] buffer = new byte[ size];
		int count = in.read(buffer, 0, size);	
		System.out.println("文件长度:" + size + ", 读取长度:" + count);
		
		// 发送图片数据(理论上讲应该只发对端连接的)
		ImgEndPoint.fanoutMessage(buffer);
		
		// 关闭文件流
		try {
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		// 接口响应
		return "消息【" +content+ "】发送成功!";
	}
}

我这里多一句嘴,如果是音视频应用的录像播放,这里可以使用websocket传输图片流,然后通过计算发送定点的图片流数据到前端来实现自定义的播放器功能(海康萤石云使用的就是websocket播放录像流的,做法类似)

播放效果如下: 在这里插入图片描述
在这里插入图片描述

源码获取、合作、技术交流请获取如下联系方式:
QQ交流群:961179337
在这里插入图片描述

微信账号:lixiang6153
公众号:IT技术快餐
电子邮箱:lixx2048@163.com

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

H5之webcoekt播放JPEG图片流 的相关文章

随机推荐

  • 关于iostat中await的理解

    关于iostat中await的理解 await 每个I O平均所需的时间 rd ticks wr ticks rd ios wr ios 不仅包括硬盘设备处理I O的时间 还包括了在kernel队列中等待的时间 rd ticks 读操作消耗
  • linux 6中4T磁盘识别并分区格式化挂接

    存储端划分4T的LUN后 主机端操作如下 1 主机识别 本例中hba卡的端口是host11和host12 root db1 echo gt sys class scsi host host11 scan root db1 echo gt s
  • Netlink 内核实现分析(一):创建

    http blog csdn net luckyapple1028 article details 50839395 Netlink 是一种IPC Inter Process Commumicate 机制 它是一种用于内核与用户空间通信的机
  • Resnet 18网络模型

    1 残差网络 Resnet 残差块 让我们聚焦于神经网络局部 如图左侧所示 假设我们的原始输入为x 而希望学出的理想映射为f x 作为上方激活函数的输入 左图虚线框中的部分需要直接拟合出该映射f x 而右图虚线框中的部分则需要拟合出残差映射
  • Canalys 2020Q2报告:百度智能云稳坐第一阵营 AI打造差异化竞争力

    在AI新基建领域的持续布局下 百度智能云站稳中国云市场第一阵营 9月9日消息 据英国调研机构Canalys发布的2020年第二季度中国基础云市场报告显示 中国云计算市场整体规模达43亿美金 同比增长70 突破新纪录 其中 头部四家厂商市场占
  • 手机热点总是正在连接服务器,电脑连接手机热点无法上网的三种解决方法

    电脑连接手机热点无法上网的三种解决方法 方法一 网络诊断 右键点击通知栏的网络图标 打开网络和共享中心 如图所示 在网络和共享中心 找到所连接的手机网络热点并点击它 如图所示 点击 诊断 功能 诊断网络无法连接的问题 如图所示 系统的网络诊
  • 网络分层模型

    OSI七层模型 物数网传会表应 物理层 主要定义物理设备标准 如网线的接口类型 光纤的接口类型 各种传输介质的传输速率等 它的主要作用是传输比特流 就是由1 0转化为电流强弱来进行传输 到达目的地后再转化为1 0 也就是我们常说的数模转换与
  • 性能综述方法论

    性能问题和Bug不同 后者的分析和解决思路更清晰 很多时候从应用日志 文中的应用指分布式服务下的单个节点 即可直接找到问题根源 而性能问题 其排查思路更为复杂一些 对应用进行性能优化 是一个系统性的工程 对工程师的技术广度和技术深度都有所要
  • fiery服务器不显示,fiery服务器打印设置

    fiery服务器打印设置 内容精选 换一换 在创建数据库连接之后 才能使用它来执行SQL语句操作数据 JDBC提供了三个方法 用于创建数据库连接 DriverManager getConnection String url DriverMa
  • 矩阵的秩与行列式的几何意义

    这里首先讨论一个长期以来困惑工科甚至物理系学生的一个数学问题 即 究竟什么是面积 以及面积的高维推广 体积等 1 关于面积 一种映射 大家会说 面积 不就是长乘以宽么 其实不然 我们首先明确 这里所讨论的面积 是欧几里得空间几何面积的基本单
  • spring boot jar部署 控制台 日志 乱码

    spring boot jar部署 控制台 日志 乱码 问题描述 spring boot jar包部署 通过java jar 命令运行 jar文件 代码中通过变量log输出到控制台的中文 乱码 但是仅仅是在运行jar时才乱码 而在用ecli
  • Mybatis源码分析:MapperMethod中内部静态类MethodSignature的作用

    MethodSignature分析 MethodSignature为MapperMethod类提供了三个作用 获取待执行方法中的参数和 Param注解标注的参数名 获取标注有 MapKey的参数 Mapkey作用在后续会讲到 方法的返回类型
  • SQLSERVER-CASE关键词的用法 .

    在Oralce中有个函数为Decode 感觉非常好用 但是此函数为Oracle所独有 在SQLSERVER和MYSQL中实现与之相类似的功能还无相关函数 但通过CASE关键词可实现类似功能 1 首先让我们看一下 CASE 的语法 在一般的
  • 僵尸进程及其处理

    进程 一个可并发执行的程序在一个数据集上的一次运行 即程序的一次运行过程 进程与程序的关系 程序是进程的一个组成部分 是进程的执行文本 进程是程序的执行过程 僵尸进程 进程主体结束 但是进程的PCB依旧存在 在多进程编程中 父进程未结束 但
  • 用U盘安卓esxi虚拟机出现 error loading /s.v00 错误解决办法

    前段时间用 一个 白色的 东芝U盘 给戴尔 R720服务器安装 esxi 6 0时 在加载到 s v00 找个文件时出现错误 大致为 error loading s v00 compressed MD5 xxxxxxx decompress
  • vue3快速入门-Teleport传送(瞬移组件)

    Vue 的组件架构使我们能够将用户界面构建为能够精美地组织业务逻辑和表示层的组件 Teleporting是Vue 3发布带来的一项新功能 它的灵感来自React Portals 相同的门户是 React 中的一个常见功能 在 Vue2 的
  • 2023最新100道渗透测试面试题(附答案)

    眨眼间2023年快过去一半了 不知道大家有没有找到心仪的工作呀 今天我给大家整理了100道渗透测试面试题给大家 需要答案的话可以在评论区给我留言哦 第一套渗透面试题 什么是渗透测试 它的目的是什么 渗透测试的五个阶段是什么 您如何选择正确的
  • SimPy

    目录 简介 安装命令 Environment Events Sleep until woken up Waiting for another process to terminate Interrupting another process
  • 【“码”力全开,“章”显实力】2022年第1季Task挑战赛贡献者榜单

    通过区块链技术及智能合约实现石头剪刀布的游戏玩法 解决双方遇到分歧的场景 让一方说服另一方 从0开始构建WeCross Go SDK 以方便社区开发者通过Go SDK实现UBI接口的快速调用 一系列FISCO BCOS WeBASE的实操教
  • H5之webcoekt播放JPEG图片流

    一 简介 既然webcoekt是基于tcp连接的 理论上讲所有的浏览器是可以私有协议处理二进制的 如果我们需要播放视频 我们可以将视频数据在后端解码后直接将图片推送到webcoekt前端 然后前端通过websocket接收图片然后将图片显示