今天小編和大家分享有關(guān)于:“在前端怎么使用webcoekt播放JPEG圖片流? ”這個(gè)問(wèn)題的相關(guān)內(nèi)容分享!希望小編的分享對(duì)大家的學(xué)習(xí)有所幫助!
一、簡(jiǎn)介
既然webcoekt是基于tcp連接的,理論上講所有的瀏覽器是可以私有協(xié)議處理二進(jìn)制的,如果我們需要播放視頻,我們可以將視頻數(shù)據(jù)在后端解碼后直接將圖片推送到webcoekt前端,然后前端通過(guò)websocket接收?qǐng)D片然后將圖片顯示到img或canvas中即可,當(dāng)然這個(gè)是我自己設(shè)想的,也是應(yīng)該可以做的到了,做到如下需要以下技術(shù)支持:
- 后端直接ffmpeg轉(zhuǎn)碼為jpeg圖片流
- 后端定制播放協(xié)議包括基本指令如play、stop、pause、faster、slower
- 后端需要提供websocket支持發(fā)送圖片流到前端
- 前端需要接受圖片流并顯示出來(lái)
后端ffmpeg解碼這里就不說(shuō)明了,我有很多庫(kù),需要的單獨(dú)聯(lián)系我購(gòu)買(mǎi),前端的顯示jpg流,這里要借助前端顯示圖片放的做法,使用圖片base64數(shù)據(jù)!前端HTML顯示二進(jìn)制jpeg圖片:圖片流=>二進(jìn)制轉(zhuǎn)image的base64編碼=>設(shè)置到img的src中,如前端代碼:
<body>
<img id="player" style="width:704px;height:576px"/>
</body>
二進(jìn)制通過(guò)arraybuffer轉(zhuǎn)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;
當(dāng)然,還有其他的方式:
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);
}
};
關(guān)于c++的websocket開(kāi)源工程:websocketpp、QWebSocketServer
二、websocket播放圖片流
多說(shuō)無(wú)益,還不如痛痛快快的來(lái)一把,為了減低復(fù)雜度,我用java的websocket來(lái)實(shí)現(xiàn)圖片流的發(fā)送(當(dāng)然c++的庫(kù)我也一個(gè)實(shí)戰(zhàn)項(xiàng)目中用過(guò)的名為WebSocket的封裝的dll工程項(xiàng)目,需要的自行私下購(gòu)買(mǎi)源碼),前端使用一個(gè)img標(biāo)簽展示圖片,這里說(shuō)明一下,后臺(tái)模擬發(fā)送圖片(這里僅僅是圖片,不是流,如果是流直接連續(xù)不斷發(fā)送即可需要ffmpeg轉(zhuǎn)碼)
首先前端的代碼如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket顯示二進(jìn)制圖片流</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("請(qǐng)求成功!");
}
});
});
});
</script>
<body>
<h1>WebSocket播放圖片</h1>
<img id="player" style="width:500px;height:400px"/><br/>
<button id="send">請(qǐng)求圖片</button>
</body>
<script type="application/javascript">
var websocket = {
send: function (str) {
}
};
window.onload = function () {
if (!'WebSocket' in window) return;
webSocketInit();
};
function webSocketInit() {
// 連接到服務(wù)端端點(diǎn)
websocket = new WebSocket("ws://127.0.0.1:8080/image/show");
// 成功建立連接
websocket.onopen = function () {
console.log("成功連接到服務(wù)器");
websocket.send("成功連接到服務(wù)器");
};
// 接收到消息
websocket.onmessage = function (event) {
// 文本數(shù)據(jù)包
if(typeof(event.data)=="string"){
// JSON.parse(evt.data)
console.log("收到服務(wù)端發(fā)送的消息:" + event.data);
// 圖片數(shù)據(jù)包Blob
}else{
var reader = new FileReader();
reader.onload = function(evt){
if(evt.target.readyState == FileReader.DONE){
// base64數(shù)據(jù)
var url = evt.target.result;
document.getElementById("player").src = url;
}
}
reader.readAsDataURL(event.data);
}
};
// 連接發(fā)生錯(cuò)誤
websocket.onerror = function () {
console.log("WebSocket連接發(fā)生錯(cuò)誤");
};
// 連接關(guān)閉
websocket.onclose = function () {
console.log("WebSocket連接關(guān)閉");
};
// 監(jiān)聽(tīng)窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)關(guān)閉websocket連接
window.onbeforeunload = function () {
websocket.close()
};
}
</script>
</html>
每次點(diǎn)擊發(fā)送的時(shí)候就向后臺(tái)請(qǐng)求一張圖,后臺(tái)將改圖發(fā)送出去(我簡(jiǎn)單的使用websocket群發(fā),可以使用websocket的可變參數(shù)將websocket和http關(guān)聯(lián)起來(lái),這個(gè)應(yīng)該很容易我這里不再贅述,不了解的進(jìn)群討論):
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;
/**
* @文件名稱(chēng): TestController.java
* @功能描述: 圖片流請(qǐng)求請(qǐng)求發(fā)送接口(websocket發(fā)送圖片到web端)
* @版權(quán)信息: www.easystudy.com
* @技術(shù)交流: 961179337(QQ群)
* @編寫(xiě)作者: lixx2048@163.com
* @聯(lián)系方式: 941415509(QQ)
* @開(kāi)發(fā)日期: 2020年9月21日
* @歷史版本: V1.0
* @備注信息:
*/
@RestController
@RequestMapping("/test")
public class TestController {
/**
* @功能描述: 發(fā)送請(qǐng)求接口
* @版權(quán)信息: www.easystudy.com
* @編寫(xiě)作者: lixx2048@163.com
* @開(kāi)發(fā)日期: 2020年9月21日
* @備注信息:
*/
@SuppressWarnings("unused")
@GetMapping("/send")
public String reponseMsgToClient(@RequestParam(name="content", required = true)String content) throws Exception{
System.out.println("開(kāi)始發(fā)送圖片數(shù)據(jù)");
// 隨機(jī)選擇一張圖片發(fā)送
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 "未找到圖片!";
}
// 創(chuàng)建輸入圖片流
InputStream in = new FileInputStream(file);
if (null == in) {
return "打開(kāi)文件失敗!";
}
// 讀取圖片數(shù)據(jù)
int size = (int)file.length();
byte[] buffer = new byte[ size];
int count = in.read(buffer, 0, size);
System.out.println("文件長(zhǎng)度:" + size + ", 讀取長(zhǎng)度:" + count);
// 發(fā)送圖片數(shù)據(jù)(理論上講應(yīng)該只發(fā)對(duì)端連接的)
ImgEndPoint.fanoutMessage(buffer);
// 關(guān)閉文件流
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 接口響應(yīng)
return "消息【" +content+ "】發(fā)送成功!";
}
}
我這里多一句嘴,如果是音視頻應(yīng)用的錄像播放,這里可以使用websocket傳輸圖片流,然后通過(guò)計(jì)算發(fā)送定點(diǎn)的圖片流數(shù)據(jù)到前端來(lái)實(shí)現(xiàn)自定義的播放器功能(??滴炇剖褂玫木褪莣ebsocket播放錄像流的,做法類(lèi)似)
播放效果如下:
那么以上就是有關(guān)于:“在前端怎么使用webcoekt播放JPEG圖片流?”這個(gè)問(wèn)題的相關(guān)內(nèi)容,那么相信大家在閱讀完之后對(duì)于Html5中的webcoekt使用也有了不少的了解,更多關(guān)于Html5這方面的相關(guān)內(nèi)容我們可以在W3Cschool中進(jìn)行學(xué)習(xí)!