Html5之webcoekt播放JPEG圖片流

一、簡(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)于Html5之webcoekt播放JPEG圖片流的文章就介紹到這了,更多相關(guān)Html5播放JPEG圖片流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
- 這篇文章主要介紹了HTML5播放實(shí)現(xiàn)rtmp流直播,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-16
html5用video標(biāo)簽流式加載的實(shí)現(xiàn)
這篇文章主要介紹了html5用video標(biāo)簽流式加載的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)2020-05-20基于 HTML5 WebGL 實(shí)現(xiàn)的醫(yī)療物流系統(tǒng)
物聯(lián)網(wǎng)( IoT ),簡(jiǎn)單的理解就是物體之間通過(guò)互聯(lián)網(wǎng)進(jìn)行鏈接。這篇文章給大家介紹基于 HTML5 WebGL 實(shí)現(xiàn)的醫(yī)療物流系統(tǒng),感興趣的朋友跟隨小編一起看看吧2019-10-08Html5 實(shí)現(xiàn)微信分享及自定義內(nèi)容的流程
這篇文章主要介紹了Html5 實(shí)現(xiàn)微信分享及自定義內(nèi)容的流程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-20- 這篇文章主要介紹了HTML5 canvas 瀑布流文字效果的示例代碼的相關(guān)資料,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-31
HTML5移動(dòng)端手機(jī)網(wǎng)站開(kāi)發(fā)流程
這篇文章主要為大家介紹了HTML5移動(dòng)端手機(jī)網(wǎng)站開(kāi)發(fā)流程,想要進(jìn)行移動(dòng)端手機(jī)網(wǎng)站開(kāi)發(fā)的朋友可以參考一下2016-04-25HTML5實(shí)現(xiàn)的圖片無(wú)限加載的瀑布流效果另帶邊框圓角陰影
一款網(wǎng)頁(yè)瀑布流效果,可以實(shí)現(xiàn)圖片的無(wú)限制加載?;跁r(shí)下流行的HTML5技術(shù)編寫(xiě)而成,除了實(shí)現(xiàn)瀑布流,還加入了CSS5的圖片修飾效果,比如圖片的圓角邊框、圖片陰影立體效果2014-03-07HTML5夢(mèng)幻之旅——炫麗的流星雨效果實(shí)現(xiàn)過(guò)程
流星出現(xiàn)的時(shí)候,人們都喜歡對(duì)著它們?cè)S愿,因?yàn)閭髡f(shuō)對(duì)著流星許下愿望后,愿望就能實(shí)現(xiàn),最近出于興趣,制作一個(gè)拖尾效果,后來(lái)想到可以通過(guò)拖尾效果來(lái)實(shí)現(xiàn)一下流星雨的效果2013-08-06HTML5 離線應(yīng)用之打造零請(qǐng)求、無(wú)流量網(wǎng)站的解決方法
今天Web應(yīng)用程序已經(jīng)很復(fù)雜了,以現(xiàn)在的發(fā)展,會(huì)將越來(lái)越復(fù)雜,但他有一個(gè)致命缺點(diǎn),不能脫離internet鏈接,因此在HTML中新增了一API,它使用一個(gè)本地存儲(chǔ)機(jī)制很好地解決了2013-04-25