海康web调试demo静态样式,看起来便于调试省个事

68 阅读6分钟

image.png 调试样式好于默认示范的,用这个调试查看也行 默认支持ip账号密码频道替换后预览,rtsp方式未验证

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>海康RTSP视频流播放器</title>
    <script src="./jquery-3.3.1.min.js"></script>
    <script src="./webVideoCtrl.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: white;
            min-height: 100vh;
            padding: 20px;
            overflow-x: hidden;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        header {
            text-align: center;
            padding: 20px 0;
            margin-bottom: 30px;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 15px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }
        
        .subtitle {
            font-size: 1.2rem;
            opacity: 0.9;
            margin-bottom: 10px;
        }
        
        .main-content {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
        }
        
        .video-section {
            flex: 1;
            min-width: 300px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 15px;
            padding: 20px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .control-section {
            width: 300px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 15px;
            padding: 20px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .video-container {
            width: 100%;
            height: 400px;
            background: rgba(0, 0, 0, 0.6);
            border-radius: 10px;
            margin-bottom: 20px;
            overflow: hidden;
            position: relative;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        #divPlugin {
            width: 100%;
            height: 100%;
        }
        
        .loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 1.2rem;
            text-align: center;
            width: 100%;
        }
        
        .status {
            background: rgba(0, 0, 0, 0.5);
            padding: 15px;
            border-radius: 10px;
            margin-bottom: 20px;
            font-size: 0.9rem;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .status h3 {
            margin-bottom: 10px;
            color: #4dabf7;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
            padding-bottom: 5px;
        }
        
        .status-item {
            display: flex;
            margin-bottom: 8px;
        }
        
        .status-label {
            width: 120px;
            font-weight: bold;
        }
        
        .status-value {
            flex: 1;
            word-break: break-all;
        }
        
        .success {
            color: #69db7c;
        }
        
        .error {
            color: #ff6b6b;
        }
        
        .warning {
            color: #ffd43b;
        }
        
        .control-panel {
            margin-top: 20px;
        }
        
        .input-group {
            margin-bottom: 15px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
        }
        
        input {
            width: 100%;
            padding: 12px;
            border-radius: 8px;
            border: none;
            background: rgba(255, 255, 255, 0.1);
            color: white;
            font-size: 1rem;
        }
        
        input:focus {
            outline: none;
            background: rgba(255, 255, 255, 0.15);
        }
        
        .btn-group {
            display: flex;
            gap: 10px;
            margin-top: 20px;
        }
        
        button {
            flex: 1;
            padding: 12px;
            border: none;
            border-radius: 8px;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 1rem;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 5px;
        }
        
        .btn-play {
            background: #40c057;
            color: white;
        }
        
        .btn-stop {
            background: #fa5252;
            color: white;
        }
        
        .btn-login {
            background: #4dabf7;
            color: white;
        }
        
        .btn-play:hover {
            background: #2f9e44;
        }
        
        .btn-stop:hover {
            background: #e03131;
        }
        
        .btn-login:hover {
            background: #339af0;
        }
        
        .info-box {
            margin-top: 20px;
            background: rgba(0, 0, 0, 0.5);
            padding: 15px;
            border-radius: 10px;
            font-size: 0.9rem;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .info-box h3 {
            margin-bottom: 10px;
            color: #4dabf7;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
            padding-bottom: 5px;
        }
        
        .info-box p {
            line-height: 1.6;
            margin-bottom: 10px;
            padding-left: 10px;
            position: relative;
        }
        
        .info-box p:before {
            content: "•";
            position: absolute;
            left: 0;
            color: #4dabf7;
        }
        
        .tabs {
            display: flex;
            margin-bottom: 20px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .tab {
            padding: 10px 20px;
            cursor: pointer;
            border-bottom: 2px solid transparent;
            transition: all 0.3s;
        }
        
        .tab.active {
            border-bottom: 2px solid #4dabf7;
            color: #4dabf7;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        @media (max-width: 768px) {
            .main-content {
                flex-direction: column;
            }
            
            .control-section {
                width: 100%;
            }
            
            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>海康视频监控系统</h1>
            <div class="subtitle">支持设备登录预览与RTSP流直接播放</div>
            <div class="subtitle">基于海康WebVideoCtrl插件</div>
        </header>
        
        <div class="main-content">
            <div class="video-section">
                <div class="tabs">
                    <div class="tab active" data-tab="device">设备预览</div>
                    <div class="tab" data-tab="rtsp">RTSP流播放</div>
                </div>
                
                <div class="video-container">
                    <div id="divPlugin"></div>
                    <div class="loading" id="loadingMessage">初始化海康插件中...</div>
                </div>
                
                <div class="status">
                    <h3>系统状态</h3>
                    <div class="status-item">
                        <div class="status-label">插件状态:</div>
                        <div class="status-value" id="pluginStatus">初始化中...</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">设备状态:</div>
                        <div class="status-value" id="deviceStatus">未登录</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">播放状态:</div>
                        <div class="status-value" id="playStatus">未播放</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">RTSP地址:</div>
                        <div class="status-value" id="rtspUrl">未设置</div>
                    </div>
                </div>
            </div>
            
            <div class="control-section">
                <h2>控制面板</h2>
                
                <div id="deviceTab" class="tab-content active">
                    <div class="input-group">
                        <label for="ip">设备IP:</label>
                        <input type="text" id="ip" value="192.168.2.253">
                    </div>
                    
                    <div class="input-group">
                        <label for="port">端口:</label>
                        <input type="text" id="port" value="80">
                    </div>
                    
                    <div class="input-group">
                        <label for="user">用户名:</label>
                        <input type="text" id="user" value="admin">
                    </div>
                    
                    <div class="input-group">
                        <label for="pwd">密码:</label>
                        <input type="password" id="pwd" value="xx2">
                    </div>
                    
                    <div class="btn-group">
                        <button class="btn-login" id="btnLogin">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                                <path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zm3.5 7.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H11.5z"/>
                            </svg>
                            登录设备
                        </button>
                    </div>
                    
                    <div class="btn-group">
                        <button class="btn-play" id="btnPreview">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                                <path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/>
                            </svg>
                            开始预览
                        </button>
                        <button class="btn-stop" id="btnStopPreview">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                                <path d="M5.5 5.5A.5.5 0 0 1 6 6v4a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm4 0a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5z"/>
                            </svg>
                            停止预览
                        </button>
                    </div>
                </div>
                
                <div id="rtspTab" class="tab-content">
                    <div class="input-group">
                        <label for="rtspInput">RTSP地址:</label>
                        <input type="text" id="rtspInput" placeholder="输入RTSP地址...">
                    </div>
                    
                    <div class="btn-group">
                        <button class="btn-play" id="btnPlay">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                                <path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/>
                            </svg>
                            播放RTSP
                        </button>
                        <button class="btn-stop" id="btnStop">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
                                <path d="M5.5 5.5A.5.5 0 0 1 6 6v4a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm4 0a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5z"/>
                            </svg>
                            停止播放
                        </button>
                    </div>
                </div>
                
                <div class="info-box">
                    <h3>使用说明</h3>
                    <p>设备预览模式需要登录海康设备</p>
                    <p>RTSP模式可直接播放RTSP流</p>
                    <p>切换模式前请先停止当前播放</p>
                    <p>示例RTSP地址: rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov</p>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 应用状态
        const state = {
            pluginReady: false,
            deviceLoggedIn: false,
            previewPlaying: false,
            rtspPlaying: false,
            deviceId: "",
            initInProgress: false,
            channels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            split: 2,
            controller: null
        };
        
        // 获取DOM元素
        const elements = {
            pluginStatus: document.getElementById('pluginStatus'),
            deviceStatus: document.getElementById('deviceStatus'),
            playStatus: document.getElementById('playStatus'),
            rtspUrl: document.getElementById('rtspUrl'),
            loadingMessage: document.getElementById('loadingMessage'),
            btnLogin: document.getElementById('btnLogin'),
            btnPreview: document.getElementById('btnPreview'),
            btnStopPreview: document.getElementById('btnStopPreview'),
            btnPlay: document.getElementById('btnPlay'),
            btnStop: document.getElementById('btnStop'),
            rtspInput: document.getElementById('rtspInput'),
            ip: document.getElementById('ip'),
            port: document.getElementById('port'),
            user: document.getElementById('user'),
            pwd: document.getElementById('pwd')
        };
        
        // 更新状态显示
        function updateStatus() {
            elements.pluginStatus.textContent = state.pluginReady ? "已就绪" : "未就绪";
            elements.pluginStatus.className = state.pluginReady ? "status-value success" : "status-value error";
            
            elements.deviceStatus.textContent = state.deviceLoggedIn ? "已登录" : "未登录";
            elements.deviceStatus.className = state.deviceLoggedIn ? "status-value success" : "status-value";
            
            if (state.previewPlaying) {
                elements.playStatus.textContent = "设备预览中";
                elements.playStatus.className = "status-value success";
            } else if (state.rtspPlaying) {
                elements.playStatus.textContent = "RTSP播放中";
                elements.playStatus.className = "status-value success";
            } else {
                elements.playStatus.textContent = "未播放";
                elements.playStatus.className = "status-value";
            }
        }
        
        // 初始化插件
        function initPlugin() {
            if (state.initInProgress) return;
            state.initInProgress = true;
            
            if (!window.WebVideoCtrl) {
                console.error("WebVideoCtrl 插件未加载");
                elements.pluginStatus.textContent = "插件未加载";
                elements.loadingMessage.textContent = "海康插件加载失败,请检查webVideoCtrl.js文件";
                return;
            }
            
            // 初始化插件
            WebVideoCtrl.I_InitPlugin({
                bWndFull: true,
                cbInitPluginComplete: function () {
                    console.log("插件初始化完成");
                    
                    // 插入插件到容器中
                    WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin")
                        .then(function () {
                            console.log("插件插入成功");
                            state.pluginReady = true;
                            elements.loadingMessage.style.display = 'none';
                            updateStatus();
                            
                            // 尝试自动登录设备
                            setTimeout(() => {
                                loginDevice();
                            }, 500);
                        })
                        .catch(function (err) {
                            console.error("插件插入失败:", err);
                            elements.pluginStatus.textContent = "插件插入失败";
                            elements.loadingMessage.textContent = "插件插入失败: " + err;
                        });
                }
            });
        }
        
        // 登录设备
        function loginDevice() {
            if (!state.pluginReady) {
                alert("插件未准备好,请稍后再试");
                return;
            }
            
            const ip = elements.ip.value;
            const port = parseInt(elements.port.value) || 80;
            const user = elements.user.value;
            const pwd = elements.pwd.value;
            
            if (!ip || !user || !pwd) {
                alert("请输入完整的设备登录信息");
                return;
            }
            
            state.deviceId = `${ip}_${port}`;
            elements.deviceStatus.textContent = "登录中...";
            
            WebVideoCtrl.I_Login(
                ip,
                1, // 协议
                port,
                user,
                pwd,
                {
                    success: function (xmlDoc) {
                        if ($(xmlDoc).find("statusString").text() === "OK") {
                            state.deviceLoggedIn = true;
                            updateStatus();
                            alert("设备登录成功");
                        } else {
                            console.error("登录状态异常");
                            elements.deviceStatus.textContent = "登录失败";
                        }
                    },
                    error: function (err) {
                        console.error("登录失败:", err);
                        elements.deviceStatus.textContent = "登录失败";
                        alert("设备登录失败: " + err);
                    }
                }
            );
        }
        
        // 开始预览所有通道
        function startPreviewAllChannels() {
            if (!state.pluginReady || !state.deviceLoggedIn) {
                alert("请确保插件已就绪且设备已登录");
                return;
            }
            
            if (state.previewPlaying) return;
            
            try {
                // 停止所有播放
                if (window.WebVideoCtrl && WebVideoCtrl.I_StopAllPlay) {
                    WebVideoCtrl.I_StopAllPlay();
                }
                
                // 设置画面分割
                WebVideoCtrl.I_ChangeWndNum(state.split);
                
                // 开始预览所有通道
                state.channels.forEach(function (channel, index) {
                    playChannel(channel, index);
                });
                
                state.previewPlaying = true;
                state.rtspPlaying = false;
                updateStatus();
            } catch (error) {
                console.error("预览启动失败:", error);
                alert("预览启动失败: " + error);
            }
        }
        
        // 播放通道
        function playChannel(iChannelID, wndIndex) {
            if (!window.WebVideoCtrl || !WebVideoCtrl.I_StartRealPlay) {
                console.error("WebVideoCtrl.I_StartRealPlay 方法未定义");
                return;
            }

            WebVideoCtrl.I_StartRealPlay(state.deviceId, {
                iWndIndex: wndIndex,
                iChannelID: parseInt(iChannelID),
                iStreamType: 2, // 主码流
                bZeroChannel: false,
                iPort: 554, // RTSP 端口
                success: function () {
                    console.log("通道 " + iChannelID + " 预览启动成功");
                },
                error: function (err) {
                    console.error("通道 " + iChannelID + " 预览启动失败:", err);
                }
            });
        }
        
        // 停止预览
        function stopPreview() {
            if (window.WebVideoCtrl && WebVideoCtrl.I_StopAllPlay) {
                WebVideoCtrl.I_StopAllPlay();
                state.previewPlaying = false;
                updateStatus();
            }
        }
        
        // 播放RTSP流
        function playRTSP() {
            if (!state.pluginReady) {
                alert("插件未准备好,请稍后再试");
                return;
            }
            
            // 获取输入的RTSP地址
            const rtsp = elements.rtspInput.value;
            if (!rtsp || !rtsp.startsWith('rtsp://')) {
                alert("请输入有效的RTSP地址");
                return;
            }
            
            // 停止当前播放
            if (window.WebVideoCtrl && WebVideoCtrl.I_StopAllPlay) {
                WebVideoCtrl.I_StopAllPlay();
            }
            
            // 更新状态
            elements.rtspUrl.textContent = rtsp;
            state.previewPlaying = false;
            state.rtspPlaying = true;
            updateStatus();
            
            try {
                // 设置单窗口模式
                WebVideoCtrl.I_ChangeWndNum(1);
                
                // 使用RTSP流播放
                WebVideoCtrl.I_StartRealPlayEx({
                    iWndIndex: 0,
                    url: rtsp,
                    success: function() {
                        console.log("RTSP播放成功");
                    },
                    error: function(err) {
                        console.error("RTSP播放失败:", err);
                        state.rtspPlaying = false;
                        elements.playStatus.textContent = "播放失败: " + err;
                        elements.playStatus.className = "status-value error";
                        alert("RTSP播放失败: " + err);
                    }
                });
            } catch (e) {
                console.error("播放异常:", e);
                state.rtspPlaying = false;
                updateStatus();
                alert("播放异常: " + e);
            }
        }
        
        // 停止RTSP播放
        function stopRTSP() {
            if (window.WebVideoCtrl && WebVideoCtrl.I_StopAllPlay) {
                WebVideoCtrl.I_StopAllPlay();
                state.rtspPlaying = false;
                updateStatus();
            }
        }
        
        // 清理资源
        function cleanup() {
            if (window.WebVideoCtrl) {
                try {
                    WebVideoCtrl.I_StopAllPlay();
                    WebVideoCtrl.I_DestroyPlugin();
                } catch (e) {
                    console.error("清理资源时出错:", e);
                }
            }
        }
        
        // 页面加载完成后初始化
        document.addEventListener("DOMContentLoaded", function() {
            // 初始化插件
            initPlugin();
            
            // 绑定按钮事件
            elements.btnLogin.addEventListener('click', loginDevice);
            elements.btnPreview.addEventListener('click', startPreviewAllChannels);
            elements.btnStopPreview.addEventListener('click', stopPreview);
            elements.btnPlay.addEventListener('click', playRTSP);
            elements.btnStop.addEventListener('click', stopRTSP);
            
            // 绑定标签切换事件
            document.querySelectorAll('.tab').forEach(tab => {
                tab.addEventListener('click', function() {
                    // 移除所有active类
                    document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                    document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
                    
                    // 添加active类到当前标签
                    this.classList.add('active');
                    const tabId = this.getAttribute('data-tab') + 'Tab';
                    document.getElementById(tabId).classList.add('active');
                });
            });
            
            // 页面关闭前清理资源
            window.addEventListener('beforeunload', cleanup);
            
            // 初始状态更新
            updateStatus();
        });
    </script>
</body>
</html>