海康威视监控web实时预览解决方案

海康威视摄像头都试rtsp流,web页面无法加载播放,所以就得转换成web页面可以播放的hls、rtmp等数据流来播放。

一:萤石云

使用萤石云平台,把rtsp转化成ezopen协议,然后使用组件UIKit

最佳实践 · 萤石开放平台API文档

UIKit Javascript · 萤石开放平台API文档

文档概述 · 萤石开放平台API文档

二:

使用海康威视官网插件,或无插件版

海康开放平台

三:使用安防平台预览url接口

根据不同的数据流返回不同的直播流,这里我主要用的hls的流来播放。hls取流有一个坑的就是摄像头编码得设置264.音频选择acc。

海康接口调用封装的是用php写的。

复制代码
<?php
namespace AppModel;
header('Content-type:text/html; Charset=utf-8');
date_default_timezone_set('PRC');
class Haikang
{
    public $pre_url = "https://host:443"; //安防平台故武器地址
    protected $app_key = "appkey"; // key
    protected $app_secret = "secret";
    public $time ;//时间戳
    public $content_type="application/json";//类型
    public $accept="*/*" ;//accept
    
    public $person_list_url = "/artemis/api/resource/v1/encodeDevice/get";//人员列表url
    public $equipment_view_url = "/artemis/api/video/v1/cameras/previewURLs";//获取监控点预览取流URL
    public function __construct($app_key='', $app_secret='')
    {
        if($app_key!='') $this->app_key = $app_key;
        if($app_secret!='') $this->app_secret = $app_secret;
        $this->charset = 'utf-8';
        list($msec, $sec) = explode(' ', microtime());
        $this->time = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    }
    function getViewUrl($cameraIndexCode){
        //请求参数
        $postData['cameraIndexCode'] = $cameraIndexCode;
        $postData['streamType'] =0;
        $postData['protocol'] = 'hls';
        $postData['transmode'] = 1;
	$postData['videotype'] = 'h264';
        $sign = $this->get_sign($postData,$this->equipment_view_url);
        $options = array(
                CURLOPT_HTTPHEADER => array(
                    "Accept:".$this->accept,
                    "Content-Type:".$this->content_type,
                    "X-Ca-Key:".$this->app_key,
                    "X-Ca-Signature:".$sign,
                    "Date:".$this->time,
                    "X-Ca-Signature-Headers:"."x-ca-key",
                    )
            );
            
        $result = $this->curlPost($this->pre_url.$this->equipment_view_url,json_encode($postData),$options);
        return json_decode($result,true);
    }
    /**
     * 获取人员列表
     */
    function get_person_list($response){
        //请求参数
        $postData['pageNo'] = isset($response['pageNo']) ? intval($response['pageNo']):"1";
        $postData['pageSize'] = isset($response['pageSize']) ? intval($response['pageSize']):"1000";
        $sign = $this->get_sign($postData,$this->person_list_url);
        $options = array(
                CURLOPT_HTTPHEADER => array(
                    "Accept:".$this->accept,
                    "Content-Type:".$this->content_type,
                    "X-Ca-Key:".$this->app_key,
                    "X-Ca-Signature:".$sign,
                    "Date:".$this->time,
                    "X-Ca-Signature-Headers:"."x-ca-key",
                    )
            );
            
        $result = $this->curlPost($this->pre_url.$this->person_list_url,json_encode($postData),$options);
    
        return json_decode($result,true);
    }
    /**
     * 以appSecret为密钥,使用HmacSHA256算法对签名字符串生成消息摘要,对消息摘要使用BASE64算法生成签名(签名过程中的编码方式全为UTF-8)
     */
    function get_sign($postData,$url){
        $sign_str = $this->get_sign_str($postData,$url); //签名字符串
        
        $priKey=$this->app_secret;
        $sign = hash_hmac('sha256', $sign_str, $priKey,true); //生成消息摘要
        $result = base64_encode($sign);
        return $result;
    }
    function get_sign_str($postData,$url){
        
        $next = "
";
        $str = "POST".$next.$this->accept.$next.$this->content_type.$next.$this->time.$next;
        $str .= "x-ca-key:".$this->app_key.$next;
        $str .= $url;
        return $str;
    }
    public function getSignContent($params) {
        ksort($params);
        $stringToBeSigned = "";
        $i = 0;$len = count($params);
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
                // 转换成目标字符集
                $v = $this->characet($v, $this->charset);
                if ($i == 0) {
                    $stringToBeSigned .= "?$k" . "=" . "$v";
                }else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        unset ($k, $v);
        return $stringToBeSigned;
    }
    function get_message($postData){
        $str = str_replace(array('{','}','"'),'',json_encode($postData));
        return base64_encode(md5($str));
    }
    /**
     * 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected function checkEmpty($value) {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }
    
    /**
     * 转换字符集编码
     * @param $data
     * @param $targetCharset
     * @return string
     */
    function characet($data, $targetCharset) {
        if (!empty($data)) {
            $fileType = $this->charset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset, $fileType);
            }
        }
        return $data;
    }
    public function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
}

前端video-js插件就可以播放hls的视频流

四:ffpemg

下载并安装FFMPEG

随便找的一个安装教程:https://blog.csdn.net/weixin_44704985/article/details/109532224

安装后需配置到环境变量

下载并安装mediamtx

https://github.com/bluenviron/mediamtx/releases

要是打不开自己想办法

开启mediamtx

如果不进行配置文件修改,使用默认配置,双击mediamtx.exe打开执行文件

使用FFMPEG进行视频推流

打开cmd 运行以下命令

ffmpeg -re -i 你的视频.mp4 -vcodec libvpx -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream/h1

这句的含义是:输入流为你指定的视频,可以是本地的文件,也可以是海康的rtsp视频流,如

ffmpeg -re -i rtsp://admin:hik12345@10.16.4.25:554/Streaming/Channels/101 -vcodec libvpx -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream/h1

输出流是 rtsp://127.0.0.1:8554/stream

将原视频格式重新编码为libvpx(p8)格式

使用http方式播放视频

在网页中运行以下url

http://127.0.0.1:8889/stream/h1

如果不出意外现在能够进行视频播放

mediamtx部分

我们可以看见,开启软件后会对RTSP、RTMP、HLS、WebRTC、SRT这几种协议类型输入流进行监听

可以通过ffmpeg将视频推送到对应协议的端口

使用FFMPEG进行视频推流(重点)

ffmpeg -re -i 你的视频.mp4 -vcodec libvpx -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream/h1

编码时可以设置参数,vcodec:视频编码格式,acodec:音频编码格式

格式有很多,可以使用以下方式查看具体编码格式

ffmpeg -encoders

这里我把输入视频转换为libvpx格式是因为我想直接使用http方式播放视频,而WebRTC只能支持几种格式视频播放

如果你想同时推送多个相机或视频源,可以修改输出路径,如:

rtsp://127.0.0.1:8554/stream/h1

rtsp://127.0.0.1:8554/stream/h2

rtsp://127.0.0.1:8554/stream/h3

。。。

如果是需要推送其他协议视频,请参考ffmpeg的命令行说明

相关推荐
G_G#8 小时前
纯前端js插件实现同一浏览器控制只允许打开一个标签,处理session变更问题
前端·javascript·浏览器标签页通信·只允许一个标签页
@大迁世界8 小时前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
GIS之路8 小时前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug8 小时前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu121388 小时前
React面向组件编程
开发语言·前端·javascript
持续升级打怪中9 小时前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路9 小时前
GDAL 实现矢量合并
前端
hxjhnct9 小时前
React useContext的缺陷
前端·react.js·前端框架
前端 贾公子9 小时前
从入门到实践:前端 Monorepo 工程化实战(4)
前端
菩提小狗9 小时前
Sqlmap双击运行脚本,双击直接打开。
前端·笔记·安全·web安全