海康威视监控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的命令行说明

相关推荐
王解1 小时前
企业级包管理器之搭建 npm 私有服务器 (6)
服务器·前端·npm
清风孤客4 小时前
Vue.js 如何塑造现代网络体验
前端·网络·vue.js
一棵开花的树,枝芽无限靠近你4 小时前
【PPTist】历史记录功能
前端·笔记·学习
licy__5 小时前
Vue 2 中 v-text 和 v-html 指令的使用详解
开发语言·前端·javascript
tester Jeffky5 小时前
深入探索 jQuery:解锁前端开发的高效工具
前端·javascript·jquery
海上彼尚7 小时前
前端自己也能开启HTTPS
前端·vue.js·https·vue
陪你去流浪_8 小时前
Vue iframe嵌套的页面实现路由缓存 实现keep-alive效果
前端·vue.js·缓存
Jing_jing_X8 小时前
心情追忆- SEO优化提升用户发现率
前端·后端·产品经理·个人开发·流量运营
ekskef_sef8 小时前
2024年前端真实面试题集合(Vue篇02)
前端·javascript·vue.js