WEB端播放華為海康大華視頻方案


WEB端播放華為海康大華視頻方案

類似標題:谷歌瀏覽器播放華為海康大華視頻方案

方案

以下方案相當於給需要播放視頻的WEB系統做了一個專用的瀏覽器,通過專用瀏覽器的CS客戶端組件播放視頻,當然,這個專用瀏覽器是需要安裝的
  1. 使用WPF編寫一個客戶端程序,嵌入CefSharp瀏覽器控件,除了瀏覽器之外無其它界面元素,客戶端窗體也沒有邊框和標題欄,如效果圖所示
  2. 瀏覽器加載WEB系統,WEB系統登錄后把Token傳給WPF客戶端,客戶端使用Token可以請求WEB系統的接口,獲取數據。
  3. WEB系統需要播放實時視頻或錄像回放時,使用nanoid.js為播放器生成一個唯一標識,計算播放器在瀏覽器中的位置、長寬,然后把播放器唯一標識、位置、長寬、攝像機設備ID集合通過JS調用C#方法傳給客戶端,客戶端根據位置、長寬顯示播放器組件。

說明

  1. WEB端為Vue開發的系統,WEB系統內有Tab頁,如果有子系統跳轉,或window.open,客戶端會打開新窗體加載跳轉頁

效果圖

效果圖

效果圖說明

  1. 頁面為BS頁面,視頻彈窗是用layui做的,也是BS的,視頻播放是CS控件,WPF通過WindowsFormsHost加載的Winform控件播放視頻
  2. 當BS彈窗最大化、還原、移動時,通過JS調用C#方法更新視頻播放CS控件的位置、長寬
  3. BS彈窗最小化時隱藏視頻播放CS控件,還原時顯示
  4. BS彈窗關閉時,釋放視頻播放CS控件占用的資源
  5. 視頻播放CS控件,全屏功能正常,單視頻全屏功能正常,單視頻僅在視頻播放CS控件中最大化顯示功能正常

現場截圖

WEB端測試頁面代碼

<!DOCTYPE html>
<html>

<head>
    <title>CefSharpDemo</title>

    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <script type="text/javascript" src="jquery-1.9.1.js"></script>
    <script type="text/javascript" src="nanoid.js"></script>
    <script src="layui/layui.js"></script>

    <style type="text/css">
        input {
            height: 21px;
            line-height: 21px;
            border: solid 1px #666;
            outline: none;
        }
    </style>

    <script type="text/javascript">
        //測試JS調用C#方法
        function testCallCSharp() {
            if (jsObjExists()) jsObj.TestCallCSharp("測試參數123");
        }

        //測試C#調用JS方法
        function testCallJs(data) {
            alert("測試C#調用JS方法:" + data);
        }

        //判斷jsObj是否存在
        function jsObjExists() {
            return typeof (jsObj) != typeof (undefined);
        }

        //獲取url參數
        getQueryString = function (name) {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
            var r = window.location.search.substring(1).match(reg);
            if (r != null) return decodeURIComponent(r[2]);
            return null;
        }
    </script>
</head>

<body style="background-color: #ffffff; border: solid 2px #ff0000; padding: 0; margin: 0;">
    <div style="margin-bottom: 10px; font-weight: bold;">
        <span id="title"></span>
    </div>
    <div style="height: 30px;">
        <span>測試輸入框:</span><input type="text" />
    </div>
    <div style="height: 30px; user-select: none;">
        <span id="msg" style="line-height: 30px;"></span>
    </div>
    <div style="height: 30px; user-select: none;">
        <span id="msg2" style="line-height: 30px;"></span>
    </div>

    <div style="user-select: none;">
        <input type="button" value="測試調用C#方法" title="測試調用C#方法" onclick="testCallCSharp()" />
        <input type="button" value="跳轉" title="跳轉" onclick="openNew()" />
        <input type="button" value="設置Token或登錄信息" title="設置Token或登錄信息" onclick="setToken()" />
    </div>
    <div style="user-select: none; margin-top: 20px;">
        <input type="button" value="播放單個視頻" title="播放單個視頻" onclick="playSingle()" />
        <input type="button" value="替換播放單個視頻" title="替換播放單個視頻" onclick="playSingleReplace()" />
        <input type="button" value="播放多路視頻" title="播放多路視頻" onclick="playMulti()" />
        <input type="button" value="追加播放" title="追加播放" onclick="appendToPlayMulti()" />
        <input type="button" value="播放單個錄像" title="播放單個錄像" onclick="playOneRecord()" />
        <input type="button" value="錄像回放" title="錄像回放" onclick="playRecord()" />
        <input type="button" value="追加錄像回放" title="追加錄像回放" onclick="appendToPlayRecord()" />
    </div>
    <div style="position: absolute; float: right; top:5px;right:5px;">
        <input type="button" value="最小化" title="最小化" onclick="minimizeApp()" style="margin-right: 10px;" />
        <input type="button" value="最大化" title="最大化" onclick="maximizeApp()" style="margin-right: 10px;" />
        <input type="button" value="還原" title="還原" onclick="normalizeApp()" style="margin-right: 10px;" />
        <input type="button" value="關閉" title="關閉" onclick="closeApp()" />
    </div>

    <!-- 一個BS組件 -->
    <div
        style="position: absolute; float: right; top: 200px; right: 100px; width: 300px; height: 300px; background-color:#FFEE33; padding: 10px; color: #333333;">
        <span>
            這是一個BS組件,視頻能把我擋住
        </span>
        <br />
        <span style="margin-top: 100px; display: block;">
            這是一個BS組件,視頻能把我擋住
        </span>
        <br />
        <span style="margin-top: 100px; display: block;">
            這是一個BS組件,視頻能把我擋住
        </span>
    </div>

    <script type="text/javascript">
        //JS調用C#方法的接口,jsObj.XXX(...)
        //下面所有方法,調用的C#方法是首字母大寫

        let title = getQueryString("title");
        $("#title").text(title);

        //頁面加載完成時調用C#方法(重要,頁面加載完成一定要調用)
        if (jsObjExists()) jsObj.WebPageLoaded(title);

        //跳轉
        function openNew() {
            window.open("http://localhost:8066/?title=跳轉頁");
        }

        //設置Token或登錄信息
        function setToken() {
            if (jsObjExists()) jsObj.SetToken("這是登錄信息或Token");
        }

        //窗口ID
        let windowIdForSingle;
        let windowIdForMulti;
        let windowIdForOneRecord;
        let windowIdForPlayRecord;
        let windowIdForPtz;

        //播放單個視頻
        function playSingle() {
            if (windowIdForSingle) {
                if (jsObjExists()) jsObj.ShowWindow(windowIdForSingle);
                alert("單個視頻播放窗口已存在");
                return;
            }

            let moveWindow = function () {
                if (!windowIdForSingle) return;
                let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
                let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
                let width = $("#layui-layer" + handle).width();
                let height = $("#layui-layer" + handle).height() - 51;
                jsObj.MoveWindow(windowIdForSingle, left, top, width, height);
            }

            let interval = setInterval(() => {
                moveWindow();
            }, 100);

            windowIdForSingle = nanoid(); //窗口ID
            let handle = layer.open({
                type: 1,
                title: '視頻',
                shadeClose: false,
                shade: false,
                maxmin: true, //開啟最大化最小化按鈕
                area: ['500px', '351px'],
                content: '<div>空白頁面</div>',
                cancel: function () {
                    if (jsObjExists()) {
                        clearInterval(interval);
                        jsObj.CloseWindow(windowIdForSingle);
                        windowIdForSingle = undefined;
                    }
                },
                min: function () {
                    if (jsObjExists()) {
                        jsObj.HideWindow(windowIdForSingle);
                        //jsObj.StopWindowPlay(windowIdForSingle); //可選操作,停止窗體所有正在播放的視頻
                    }
                },
                restore: function () {
                    if (jsObjExists()) {
                        jsObj.ShowWindow(windowIdForSingle);
                        moveWindow();
                    }
                },
                full: function () {
                    moveWindow();
                }
            });

            let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
            let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
            let width = 500;
            let height = 300;

            let cameraId = "BD4F35031E61B4BCE053070C0822BF04"; //攝像機設備ID

            if (jsObjExists()) jsObj.PlaySingle(left, top, width, height, windowIdForSingle, cameraId);
        }

        //替換播放單個視頻
        function playSingleReplace() {
            let cameraId = "BC77ACF9EFCE1A48E053070C0822157A"; //攝像機設備ID

            if (jsObjExists()) jsObj.PlaySingleReplace(windowIdForSingle, cameraId);
        }

        //播放多個視頻
        function playMulti() {
            if (windowIdForMulti) {
                if (jsObjExists()) jsObj.ShowWindow(windowIdForMulti);
                alert("多路視頻播放窗口已存在,您可以追加播放");
                return;
            }

            let moveWindow = function () {
                if (!windowIdForMulti) return;
                let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
                let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
                let width = $("#layui-layer" + handle).width();
                let height = $("#layui-layer" + handle).height() - 51;
                jsObj.MoveWindow(windowIdForMulti, left, top, width, height);
            }

            let interval = setInterval(() => {
                moveWindow();
            }, 100);

            windowIdForMulti = nanoid(); //窗口ID
            let handle = layer.open({
                type: 1,
                title: '視頻',
                shadeClose: false,
                shade: false,
                maxmin: true, //開啟最大化最小化按鈕
                area: ['1100px', '651px'],
                content: '<div>空白頁面</div>',
                cancel: function () {
                    if (jsObjExists()) {
                        clearInterval(interval);
                        jsObj.CloseWindow(windowIdForMulti);
                        windowIdForMulti = undefined;
                        hidePTZ();
                    }
                },
                min: function () {
                    if (jsObjExists()) {
                        jsObj.HideWindow(windowIdForMulti);
                        //jsObj.StopWindowPlay(windowIdForMulti); //可選操作,停止窗體所有正在播放的視頻
                    }
                },
                restore: function () {
                    if (jsObjExists()) {
                        jsObj.ShowWindow(windowIdForMulti);
                        moveWindow();
                    }
                },
                full: function () {
                    moveWindow();
                }
            });

            let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
            let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
            let width = 1000;
            let height = 600;
            let cameraIds = "BD4F31B4DBFEB3A1E053070C0822FD40,BC77ACF9F04D1A48E053070C0822157A"; //攝像機設備ID

            if (jsObjExists()) jsObj.PlayMulti(left, top, width, height, windowIdForMulti, 4, true, cameraIds);
        }

        //追加播放
        function appendToPlayMulti() {
            let cameraIds = "BC77ACF9EFCE1A48E053070C0822157A,BC77ACF9F0801A48E053070C0822157A,BC77ACF9F04D1A48E053070C0822157A,BD4F31B4DBFEB3A1E053070C0822FD40,BD4F31B4DC10B3A1E053070C0822FD40,BD4F35031E50B4BCE053070C0822BF04,BD4F35031E61B4BCE053070C0822BF04"; //攝像機設備ID

            if (jsObjExists()) jsObj.AppendToPlayMulti(windowIdForMulti, cameraIds);
        }

        //播放單個錄像
        function playOneRecord() {
            layer.msg("請稍等......", { icon: 1, offset: "t" });

            if (windowIdForOneRecord) {
                if (jsObjExists()) jsObj.ShowWindow(windowIdForOneRecord);
                alert("視頻回放彈框已存在,您可以追加回放");
                return;
            }

            let moveWindow = function () {
                if (!windowIdForOneRecord) return;
                let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
                let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
                let width = $("#layui-layer" + handle).width();
                let height = $("#layui-layer" + handle).height() - 51;
                jsObj.MoveWindow(windowIdForOneRecord, left, top, width, height);
            }

            let interval = setInterval(() => {
                moveWindow();
            }, 100);

            windowIdForOneRecord = nanoid(); //窗口ID
            let handle = layer.open({
                type: 1,
                title: '視頻',
                shadeClose: false,
                shade: false,
                maxmin: true, //開啟最大化最小化按鈕
                area: ['500px', '351px'],
                content: '<div style="padding: 20px;">請稍等......</div>',
                cancel: function () {
                    if (jsObjExists()) {
                        clearInterval(interval);
                        jsObj.CloseWindow(windowIdForOneRecord);
                        windowIdForOneRecord = undefined;
                    }
                },
                min: function () {
                    if (jsObjExists()) {
                        jsObj.HideWindow(windowIdForOneRecord);
                        //jsObj.StopWindowPlay(windowIdForOneRecord); //可選操作,停止窗體所有正在播放的視頻
                    }
                },
                restore: function () {
                    if (jsObjExists()) {
                        jsObj.ShowWindow(windowIdForOneRecord);
                        moveWindow();
                    }
                },
                full: function () {
                    moveWindow();
                }
            });

            let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
            let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
            let width = 500;
            let height = 300;

            let cameraId = "BD4F31B4DBFEB3A1E053070C0822FD40"; //攝像機設備ID
            let startTime = "2022-04-20 01:00:00";
            let endTime = "2022-04-20 02:00:00";

            if (jsObjExists()) jsObj.PlayOneRecord(left, top, width, height, windowIdForOneRecord, cameraId, startTime, endTime);
        }

        //錄像回放
        function playRecord() {
            layer.msg("請稍等......", { icon: 1, offset: "t" });

            if (windowIdForPlayRecord) {
                if (jsObjExists()) jsObj.ShowWindow(windowIdForPlayRecord);
                alert("視頻回放彈框已存在,您可以追加回放");
                return;
            }

            let moveWindow = function () {
                if (!windowIdForPlayRecord) return;
                let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
                let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
                let width = $("#layui-layer" + handle).width();
                let height = $("#layui-layer" + handle).height() - 51;
                jsObj.MoveWindow(windowIdForPlayRecord, left, top, width, height);
            }

            let interval = setInterval(() => {
                moveWindow();
            }, 100);

            windowIdForPlayRecord = nanoid(); //窗口ID
            let handle = layer.open({
                type: 1,
                title: '視頻',
                shadeClose: false,
                shade: false,
                maxmin: true, //開啟最大化最小化按鈕
                area: ['1100px', '651px'],
                content: '<div style="padding: 20px;">請稍等......</div>',
                cancel: function () {
                    if (jsObjExists()) {
                        clearInterval(interval);
                        jsObj.CloseWindow(windowIdForPlayRecord);
                        windowIdForPlayRecord = undefined;
                    }
                },
                min: function () {
                    if (jsObjExists()) {
                        jsObj.HideWindow(windowIdForPlayRecord);
                        //jsObj.StopWindowPlay(windowIdForPlayRecord); //可選操作,停止窗體所有正在播放的視頻
                    }
                },
                restore: function () {
                    if (jsObjExists()) {
                        jsObj.ShowWindow(windowIdForPlayRecord);
                        moveWindow();
                    }
                },
                full: function () {
                    moveWindow();
                }
            });

            let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));
            let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;
            let width = 1100;
            let height = 600;

            let cameraId = "BD4F31B4DBFEB3A1E053070C0822FD40"; //攝像機設備ID
            let startTime = "2022-04-20 01:00:00";
            let endTime = "2022-04-20 02:00:00";

            if (jsObjExists()) jsObj.PlayRecord(left, top, width, height, windowIdForPlayRecord, 4, cameraId, startTime, endTime);
        }

        //追加錄像回放
        function appendToPlayRecord() {
            layer.msg("請稍等......", { icon: 1, offset: "t" });

            let cameraIds = "BD4F31B4DBFEB3A1E053070C0822FD40"; //攝像機設備ID
            let startTime = "2022-04-20 01:00:00";
            let endTime = "2022-04-20 02:00:00";

            if (jsObjExists()) jsObj.AppendToPlayRecord(windowIdForPlayRecord, cameraIds, startTime, endTime);
        }

        //關閉App
        function closeApp() {
            if (jsObjExists()) jsObj.CloseApp();
        }

        //顯示攝像機的雲台控制
        function showPTZ(cameraId) {
            layer.msg("顯示攝像機的雲台控制,cameraId=" + cameraId, { icon: 1, offset: "t" });

            if (!windowIdForPtz) {
                windowIdForPtz = nanoid(); //窗口ID
                jsObj.ShowPTZ(1603, 650, windowIdForPtz, cameraId);
            }
        }

        //隱藏攝像機的雲台控制
        function hidePTZ(cameraId) {
            layer.msg("隱藏攝像機的雲台控制,cameraId=" + cameraId, { icon: 1, offset: "t" });

            if (windowIdForPtz) {
                jsObj.ClosePTZ(windowIdForPtz);
                windowIdForPtz = undefined;
            }
        }

        //最大化
        function maximizeApp() {
            if (jsObjExists()) jsObj.Maximize();
        }

        //最小化
        function minimizeApp() {
            if (jsObjExists()) jsObj.Minimize();
        }

        //還原
        function normalizeApp() {
            if (jsObjExists()) jsObj.Normalize();
        }

        //窗體最大化事件
        function onMaximize() {
            layer.msg("窗體最大化", { icon: 1, offset: "t" });
        }

        //窗體還原事件
        function onNormalize() {
            layer.msg("窗體還原", { icon: 1, offset: "t" });
        }

        //設置body高度
        function setBodyHeight() {
            let windowHeight = $(window).height();
            $("body").height(windowHeight - 4);
        }
        setBodyHeight();
        window.onresize = function () {
            setBodyHeight();
        }
    </script>
</body>

</html>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM