锦瑟弦音 2025-10-19 22:20 采纳率: 86.4%
浏览 18
已结题

海康摄像头二次开发调用sdk教程

我需要把摄像头采集的视频传到网页端,并接收服务器返回的结果,摄像头进行语音提示,想用海康摄像头二次开发,用没有会的啊

有没有技术交流群啊

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-19 22:30
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:相信自己,你远比想象中更有潜力。
    .

    海康摄像头二次开发调用SDK教程

    概述

    针对您将海康摄像头视频传输到网页端,并实现语音提示的需求,以下是完整的解决方案。

    开发环境准备

    1. 获取海康SDK

    # 从海康官网下载对应平台的SDK
    # 通常包含:头文件、库文件、文档和示例代码
    

    2. SDK文件结构

    HikSDK/
    ├── include/          # 头文件
    ├── lib/             # 库文件
    ├── demo/            # 示例代码
    └── document/        # 开发文档
    

    核心开发步骤

    1. 初始化SDK和环境

    #include "HCNetSDK.h"
    
    
    // SDK初始化
    BOOL initSDK() {
        // 设置SDK日志路径
        NET_DVR_SetLogToFile(TRUE, "./sdk_log/");
        
        // 初始化SDK
        if (!NET_DVR_Init()) {
            printf("SDK初始化失败! 错误码: %d\n", NET_DVR_GetLastError());
            return FALSE;
        }
        
        // 设置连接时间和重连时间
        NET_DVR_SetConnectTime(2000, 1);
        NET_DVR_SetReconnect(10000, TRUE);
        
        return TRUE;
    }
    

    2. 用户登录和设备连接

    // 设备登录信息
    typedef struct {
        LONG lUserID;
        NET_DVR_DEVICEINFO_V30 deviceInfo;
    } DeviceLogin;
    
    
    DeviceLogin loginToDevice(const char* ip, const char* username, const char* password) {
        DeviceLogin result = {0};
        
        NET_DVR_USER_LOGIN_INFO loginInfo = {0};
        NET_DVR_DEVICEINFO_V40 deviceInfo = {0};
        
        strcpy(loginInfo.sDeviceAddress, ip);
        strcpy(loginInfo.sUserName, username);
        strcpy(loginInfo.sPassword, password);
        loginInfo.wPort = 8000;
        loginInfo.bUseAsynLogin = FALSE;
        
        result.lUserID = NET_DVR_Login_V40(&loginInfo, &deviceInfo);
        if (result.lUserID < 0) {
            printf("登录失败! 错误码: %d\n", NET_DVR_GetLastError());
        } else {
            printf("登录成功! 用户ID: %d\n", result.lUserID);
        }
        
        return result;
    }
    

    3. 实时视频流获取

    // 实时预览回调函数
    void CALLBACK RealDataCallBack(LONG lRealHandle, DWORD dwDataType, 
                                  BYTE *pBuffer, DWORD dwBufSize, void* pUser) {
        // 处理视频数据
        switch (dwDataType) {
            case NET_DVR_SYSHEAD:
                // 系统头数据
                break;
            case NET_DVR_STREAMDATA:
                // 码流数据
                processVideoStream(pBuffer, dwBufSize);
                break;
            case NET_DVR_AUDIOSTREAMDATA:
                // 音频数据
                processAudioStream(pBuffer, dwBufSize);
                break;
        }
    }
    
    
    // 开始实时预览
    LONG startRealPlay(LONG lUserID, int channel) {
        NET_DVR_PREVIEWINFO struPlayInfo = {0};
        struPlayInfo.hPlayWnd = NULL;        // 窗口句柄,NULL表示不显示
        struPlayInfo.lChannel = channel;     // 通道号
        struPlayInfo.dwStreamType = 0;       // 0-主码流,1-子码流
        struPlayInfo.dwLinkMode = 0;         // 0-TCP,1-UDP
        struPlayInfo.bBlocked = 1;           // 0-非阻塞取流,1-阻塞取流
        
        LONG lRealHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, 
                                               RealDataCallBack, NULL);
        if (lRealHandle < 0) {
            printf("开始预览失败! 错误码: %d\n", NET_DVR_GetLastError());
        }
        
        return lRealHandle;
    }
    

    4. 视频流推送到网页端

    后端服务(Node.js + WebSocket)

    const WebSocket = require('ws');
    const http = require('http');
    const express = require('express');
    
    
    const app = express();
    const server = http.createServer(app);
    const wss = new WebSocket.Server({ server });
    
    
    // 存储视频流数据
    let videoStreams = new Map();
    
    
    wss.on('connection', (ws) => {
        console.log('客户端连接');
        
        ws.on('message', (message) => {
            const data = JSON.parse(message);
            
            if (data.type === 'subscribe') {
                // 客户端订阅视频流
                const streamId = data.streamId;
                if (!videoStreams.has(streamId)) {
                    videoStreams.set(streamId, new Set());
                }
                videoStreams.get(streamId).add(ws);
            }
        });
        
        ws.on('close', () => {
            // 清理连接
            videoStreams.forEach((clients, streamId) => {
                clients.delete(ws);
                if (clients.size === 0) {
                    videoStreams.delete(streamId);
                }
            });
        });
    });
    
    
    // 从海康SDK接收视频数据并广播
    function broadcastVideoData(streamId, videoData) {
        const clients = videoStreams.get(streamId);
        if (clients) {
            const message = JSON.stringify({
                type: 'video',
                data: videoData.toString('base64'),
                timestamp: Date.now()
            });
            
            clients.forEach(client => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(message);
                }
            });
        }
    }
    
    
    server.listen(8080, () => {
        console.log('WebSocket服务器运行在端口 8080');
    });
    

    网页端接收视频

    <!DOCTYPE html>
    <html>
    <head>
        <title>海康摄像头实时视频</title>
    </head>
    <body>
        <video id="videoPlayer" controls autoplay muted></video>
        
        <script>
            class VideoStreamPlayer {
                constructor() {
                    this.ws = null;
                    this.videoElement = document.getElementById('videoPlayer');
                    this.initWebSocket();
                }
                
                initWebSocket() {
                    this.ws = new WebSocket('ws://localhost:8080');
                    
                    this.ws.onopen = () => {
                        console.log('WebSocket连接已建立');
                        // 订阅视频流
                        this.ws.send(JSON.stringify({
                            type: 'subscribe',
                            streamId: 'camera_001'
                        }));
                    };
                    
                    this.ws.onmessage = (event) => {
                        const data = JSON.parse(event.data);
                        if (data.type === 'video') {
                            this.playVideo(data.data);
                        } else if (data.type === 'voice_command') {
                            this.playVoiceCommand(data.command);
                        }
                    };
                    
                    this.ws.onclose = () => {
                        console.log('WebSocket连接已关闭');
                    };
                }
                
                playVideo(base64Data) {
                    // 将base64数据转换为blob URL
                    const byteCharacters = atob(base64Data);
                    const byteNumbers = new Array(byteCharacters.length);
                    for (let i = 0; i < byteCharacters.length; i++) {
                        byteNumbers[i] = byteCharacters.charCodeAt(i);
                    }
                    const byteArray = new Uint8Array(byteNumbers);
                    const blob = new Blob([byteArray], { type: 'video/mp4' });
                    const videoUrl = URL.createObjectURL(blob);
                    
                    this.videoElement.src = videoUrl;
                }
                
                playVoiceCommand(command) {
                    // 使用Web Speech API播放语音提示
                    const speech = new SpeechSynthesisUtterance(command);
                    speech.lang = 'zh-CN';
                    window.speechSynthesis.speak(speech);
                }
                
                sendServerResponse(response) {
                    // 发送服务器响应到后端
                    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                        this.ws.send(JSON.stringify({
                            type: 'server_response',
                            data: response
                        }));
                    }
                }
            }
            
            // 初始化视频播放器
            const player = new VideoStreamPlayer();
        </script>
    </body>
    </html>
    

    5. 语音提示功能

    // 语音对讲和提示功能
    BOOL startVoiceBroadcast(LONG lUserID, int channel) {
        // 启动语音对讲
        LONG lVoiceHandle = NET_DVR_StartVoiceCom_V30(lUserID, channel, 
                                                     VoiceDataCallBack, NULL);
        if (lVoiceHandle < 0) {
            printf("启动语音对讲失败! 错误码: %d\n", NET_DVR_GetLastError());
            return FALSE;
        }
        
        return TRUE;
    }
    
    
    // 语音数据回调
    void CALLBACK VoiceDataCallBack(LONG lVoiceHandle, char *pRecvDataBuffer, 
                                   DWORD dwBufSize, BYTE byAudioFlag, void* pUser) {
        // 处理接收到的语音数据
    }
    
    
    // 发送语音提示
    BOOL sendVoicePrompt(LONG lUserID, const char* audioFile) {
        // 读取音频文件
        FILE* file = fopen(audioFile, "rb");
        if (!file) {
            printf("无法打开音频文件: %s\n", audioFile);
            return FALSE;
        }
        
        fseek(file, 0, SEEK_END);
        long fileSize = ftell(file);
        fseek(file, 0, SEEK_SET);
        
        BYTE* audioData = (BYTE*)malloc(fileSize);
        fread(audioData, 1, fileSize, file);
        fclose(file);
        
        // 发送语音数据
        BOOL result = NET_DVR_VoiceComSendData(lUserID, audioData, fileSize);
        free(audioData);
        
        return result;
    }
    

    6. 服务器通信和结果处理

    // 服务器端结果处理
    app.post('/api/process-video', express.json(), (req, res) => {
        const { videoData, cameraId } = req.body;
        
        // 处理视频数据(AI分析等)
        const analysisResult = processVideoAnalysis(videoData);
        
        // 根据分析结果决定是否发送语音提示
        if (analysisResult.requiresAlert) {
            // 发送语音提示命令到前端
            broadcastVoiceCommand(cameraId, analysisResult.alertMessage);
        }
        
        // 返回处理结果
        res.json({
            success: true,
            result: analysisResult,
            timestamp: Date.now()
        });
    });
    
    
    function broadcastVoiceCommand(cameraId, message) {
        const clients = videoStreams.get(cameraId);
        if (clients) {
            const voiceMessage = JSON.stringify({
                type: 'voice_command',
                command: message,
                timestamp: Date.now()
            });
            
            clients.forEach(client => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(voiceMessage);
                }
            });
        }
    }
    

    完整示例代码

    C++ 主程序

    #include <iostream>
    #include <thread>
    #include <chrono>
    #include "HCNetSDK.h"
    
    
    class HikCameraController {
    private:
        LONG lUserID;
        LONG lRealHandle;
        bool isConnected;
        
    public:
        HikCameraController() : lUserID(-1), lRealHandle(-1), isConnected(false) {}
        
        ~HikCameraController() {
            cleanup();
        }
        
        bool connect(const char* ip, const char* username, const char* password) {
            if (!initSDK()) {
                return false;
            }
            
            NET_DVR_USER_LOGIN_INFO loginInfo = {0};
            NET_DVR_DEVICEINFO_V40 deviceInfo = {0};
            
            strcpy(loginInfo.sDeviceAddress, ip);
            strcpy(loginInfo.sUserName, username);
            strcpy(loginInfo.sPassword, password);
            loginInfo.wPort = 8000;
            loginInfo.bUseAsynLogin = FALSE;
            
            lUserID = NET_DVR_Login_V40(&loginInfo, &deviceInfo);
            if (lUserID < 0) {
                std::cout << "登录失败! 错误码: " << NET_DVR_GetLastError() << std::endl;
                return false;
            }
            
            isConnected = true;
            std::cout << "摄像头连接成功!" << std::endl;
            return true;
        }
        
        bool startVideoStream(int channel = 1) {
            if (!isConnected) {
                std::cout << "未连接到摄像头!" << std::endl;
                return false;
            }
            
            NET_DVR_PREVIEWINFO struPlayInfo = {0};
            struPlayInfo.hPlayWnd = NULL;
            struPlayInfo.lChannel = channel;
            struPlayInfo.dwStreamType = 0;
            struPlayInfo.dwLinkMode = 0;
            struPlayInfo.bBlocked = 1;
            
            lRealHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, 
                                              RealDataCallBack, NULL);
            if (lRealHandle < 0) {
                std::cout << "开始视频流失败! 错误码: " << NET_DVR_GetLastError() << std::endl;
                return false;
            }
            
            std::cout << "视频流已启动!" << std::endl;
            return true;
        }
        
        void cleanup() {
            if (lRealHandle >= 0) {
                NET_DVR_StopRealPlay(lRealHandle);
                lRealHandle = -1;
            }
            
            if (lUserID >= 0) {
                NET_DVR_Logout(lUserID);
                lUserID = -1;
            }
            
            NET_DVR_Cleanup();
            isConnected = false;
        }
    };
    
    
    // 全局回调函数
    void CALLBACK RealDataCallBack(LONG lRealHandle, DWORD dwDataType, 
                                  BYTE *pBuffer, DWORD dwBufSize, void* pUser) {
        // 这里将视频数据发送到WebSocket服务器
        // 实际实现中需要将pBuffer数据编码并传输
    }
    
    
    int main() {
        HikCameraController camera;
        
        // 连接摄像头
        if (camera.connect("192.168.1.100", "admin", "password123")) {
            // 启动视频流
            if (camera.startVideoStream()) {
                std::cout << "系统运行中..." << std::endl;
                
                // 保持程序运行
                while (true) {
                    std::this_thread::sleep_for(std::chrono::seconds(1));
                }
            }
        }
        
        return 0;
    }
    

    部署和运行

    编译C++程序

    g++ -o camera_stream main.cpp -L./lib -lHCNetSDK -lpthread
    

    运行Node.js服务器

    npm install ws express
    node server.js
    

    注意事项

    1. SDK版本兼容性:确保使用的SDK版本与摄像头固件版本兼容
    2. 网络配置:摄像头和服务器需要在同一网络或可访问的网络中
    3. 性能优化:视频流传输需要考虑带宽和编码优化
    4. 错误处理:完善各种异常情况的处理机制
    5. 安全性:在生产环境中需要考虑身份验证和数据加密

    这个方案提供了从摄像头视频采集到网页展示,再到语音提示的完整流程。您可以根据具体需求调整各个模块的实现细节。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月4日
  • 已采纳回答 10月27日
  • 修改了问题 10月19日
  • 创建了问题 10月19日