前言
Universal Media Player算是視頻流播放功能常用的插件了,用到現(xiàn)在已經不知道躺了多少坑了,這個插件雖然是白嫖的,不過被甲方和領導吐槽的就是播放視頻流的速度特別慢,可能需要幾十秒來打開監(jiān)控畫面,等待的時間較久。還有當輸出WebGL的時候視頻無法播放,這個問題也一直沒法解決。而我們常用的螢石云監(jiān)控視頻流在小程序端或者Web端打開卻快速了很多,這也就啟發(fā)了在Unity3d中也使用這種嫁接的方式來實現(xiàn)。就是通過打開網頁,在網頁中播放視頻流的方式來解決該問題。實驗結果就是能比Universal Media Player打開快2-3倍。本文是Unity3d 2020.3.28f1c1 Personal版本以螢石云的ezopen協(xié)議為例,實現(xiàn)該功能。
如果你的視頻流協(xié)議是其它的(如rtmp、rtsp等),則需要將攝像頭的協(xié)議轉成能夠在瀏覽器中播放的協(xié)議,具體方式需要做網頁的相關人員進行。這個是我在網上搜到的方法,本人并未進行實操測試,僅供參考:
1、Nginx的RTMP模塊配置方法,通過Ffmpeg將RTSP轉成RTMP協(xié)議,然后Nginx中配置RTMP到HLS協(xié)議的映射,最后按照指定的規(guī)則路徑請求即可。
2、Ffmpeg將RTSP協(xié)議直接轉成HLS協(xié)議,寫入到Nginx的指定目錄下,然后Nginx將該目錄代理成HTTP訪問的方式,瀏覽器直接請求即可,這種方法會生成很多ts文件,需要做清理處理,嘗試過可行,但是不建議使用。
效果
Windows效果一:
Windows效果二:
WebGL平臺:
如果設備有問題會直接提示在播放界面上:
以上動態(tài)圖沒有展示成功的畫面,因為設備非個人持有,所以播放成功的畫面未進行直接展示。
工作準備
筆者所用的插件:
LitJson 用于生成/解析網絡請求的json。
DOTweenPro 用于制作簡單的窗口彈出、關閉動畫;
3D WebView for Windows and macOS (Web Browser) 用于打開網頁(使用說明(https://blog.csdn.net/qq_33789001/article/details/126180804))的插件(看需求使用Embedded Browser也可以),需要WebGL 平臺的還需要2D WebView for WebGL (Web Browser IFrame)插件。
參考文章:
之前筆者寫過關于螢石云監(jiān)控相關的操作可以進行一些參考復用。
獲取accessToken:https://blog.csdn.net/qq_33789001/article/details/117251545
獲取視頻流地址:https://blog.csdn.net/qq_33789001/article/details/128223680
Unity WebGl發(fā)布問題:
https://blog.csdn.net/qq_33789001/article/details/128900799
功能實現(xiàn)
獲取accessToken
管理員賬號根據(jù)appKey和secret獲取accessToken接口.
請求地:https://open.ys7.com/api/lapp/token/get 請求方式:POST
① AccessToken,即訪問令牌。接口調用必備的公共參數(shù)之一,用于校驗接口訪問/調用是否有權限,有效期為7天,有效期內不需要重復申請,可以重復使用;
② 有效期7天無法變更,請在業(yè)務端使用AccessToken的場景中,校驗老Token的有效性和失效時重新獲取Token的機制;
③ 新獲取Token不會使老Token失效,每個Token獨立擁有7天生命周期 接口列表如下:
返回字段
字段名 類型 描述
accessToken String 獲取的accessToken
expireTime long 具體過期時間,精確到毫秒
這里的實現(xiàn)代碼如下:
//令牌相關
[Header("設置螢石云的appKey")]
public string appKey = "";
[Header("設置螢石云的appSecret")]
public string appSecret = "";
string GetATUrl = "https://open.ys7.com/api/lapp/token/get";
[HideInInspector]
public string AT = "";
DateTime AtEdTime; //令牌失效時間
//請求螢石云的令牌
void GetAccessToken()
{
isGetATing = true;
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("appKey", appKey));
formData.Add(new MultipartFormDataSection("appSecret", appSecret));
Global.DoReqWebApiPost(GetATUrl, formData, (bytes) =>
{
try
{
if (string.IsNullOrEmpty(bytes)) return;
JsonData datas = JsonMapper.ToObject(bytes);
if (!datas.ContainsKey("data")) return;
if (!datas["data"].ContainsKey("accessToken") || !datas["data"].ContainsKey("expireTime")) return;
AT = datas["data"]["accessToken"].ToString();
AtEdTime = ConvertToDateTime(datas["data"]["expireTime"].ToString());
}
catch (Exception e)
{
Debug.LogWarning("獲取螢石云AccessToken異常:" + e);
}
finally {
isGetATing = false;
}
});
}
要注意的是,如果程序長期運行,需要判斷accessToken的過期時間,即使獲取并更新,不然會導致功能異常。
獲取監(jiān)控視頻流
獲取單個的視頻流地址,需要使用accessToken為參數(shù),并且protocol的協(xié)議必須是ezopen,同時過期時間需要盡量長一些。
[Header("是否同步流地址")]
public bool isSyncUrl = true;
[Header("選擇視頻流類型")]
public Streaming_Type streamingType = Streaming_Type.ezopen;
[Header("監(jiān)控設備編號")]
public string deviceSerial;
[Header("監(jiān)控頻道號")]
public string channelNo;
//獲取視頻地址
void GetSteamingUrl()
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("accessToken", YsAccessTokenMgr.instance.AT));
formData.Add(new MultipartFormDataSection("deviceSerial", deviceSerial));
formData.Add(new MultipartFormDataSection("channelNo", channelNo));
formData.Add(new MultipartFormDataSection("expireTime", "2592000"));
formData.Add(new MultipartFormDataSection("protocol", ((int)streamingType).ToString()));
formData.Add(new MultipartFormDataSection("quality", "1"));
Global.DoReqWebApiPost(StreamUrl, formData, (bytes) =>
{
try
{
if (string.IsNullOrEmpty(bytes))
return;
JsonData datas = JsonMapper.ToObject(bytes);
if (!datas.ContainsKey("data")|| !datas["data"].ContainsKey("url"))
return;
videourl = datas["data"]["url"].ToString();
}
catch (Exception e)
{
Debug.LogWarning("獲取螢石云視頻流地址異常:" + e);
}
});
}
這里也可以不獲取視頻流地址,只有視頻嵌入式需要ezopen的地址,isSyncUrl 為false時,就不會獲取。
打開網頁播放視頻
我們在點擊了監(jiān)控視頻的標簽后,就根據(jù)視頻標簽的信息打開監(jiān)控視頻的網頁。
這里有兩種方式進行播放視頻流:視頻嵌入式和跳轉播放頁式,詳細說明請看:https://open.ys7.com/bbs/article/20
因為我們的視頻窗口是在UI上,所以使用CanvasWebViewPrefab進行網頁打開:
canvasWebView.WebView.LoadUrl(url);
視頻嵌入式
代碼如下:
string url = "https://open.ys7.com/ezopen/h5/iframe_se?url=" + path + "&autoplay=1&audio=0&accessToken=" + YsAccessTokenMgr.instance.AT;
canvasWebView.WebView.LoadUrl(url);
說明如下:
url:監(jiān)控地址,包含驗證碼、設備序列號、通道號、清晰度、播放類型
autoplay:1-開啟自動播放,未顯示字段-關閉自動播放
audio:1-開啟音頻,未顯示字段-關閉音頻
accessToken:訪問令牌,播放監(jiān)控地址的必要參數(shù)
筆者在測試該方式時發(fā)現(xiàn),在WebGL時,這種方式在一定情況下會出現(xiàn)網頁錯誤,視頻未播放的情況:
跳轉播放頁式
代碼如下:
string url = " https://open.ys7.com/ezopen/h5/live?autoplay=1&audio=0&accessToken=" + YsAccessTokenMgr.instance.AT + "&hd=1&deviceSerial=" + camlab.deviceSerial + "&channelNo=" + camlab.channelNo;
canvasWebView.WebView.LoadUrl(url);
說明如下:
live后綴:預覽
rec后綴:回放
autoplay:1-開啟自動播放,未顯示字段-關閉自動播放
audio:1-開啟音頻,未顯示字段-關閉音頻
accessToken:訪問令牌,播放監(jiān)控地址的必要參數(shù)
validCode:驗證碼,加密設備播放需要驗證碼
hd:1-高清(實際為主碼流),未顯示字段-流暢(實際為子碼流)
deviceSerial:設備序列號
channelNo:通道號
工程源碼
完整的工程源碼:https://download.csdn.net/download/qq_33789001/88135255
無法打開說明審核未通過。
現(xiàn)在工程后,打開項目中的Main.unity場景,選中FunNodes>YsAccessTokenMgr節(jié)點設置您自己的appKey和appSecret:
選中Icon_Camera修改視頻標簽的信息deviceSerial和channelNo:文章來源:http://www.zghlxwxcb.cn/news/detail-621627.html
確保的信息都是同一個賬號下面的,運行后點擊視頻圖標即可看到播放的效果了。文章來源地址http://www.zghlxwxcb.cn/news/detail-621627.html
到了這里,關于Unity3d C#快速打開螢石云監(jiān)控視頻流(ezopen)支持WebGL平臺,替代UMP播放視頻流的方案(含源碼)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!