海康威视摄像头都试rtsp流,web页面无法加载播放,所以就得转换成web页面可以播放的hls、rtmp等数据流来播放。
一:萤石云
使用萤石云平台,把rtsp转化成ezopen协议,然后使用组件UIKit
最佳实践 · 萤石开放平台API文档
UIKit Javascript · 萤石开放平台API文档
文档概述 · 萤石开放平台API文档
二:
使用海康威视官网插件,或无插件版
海康开放平台
三:使用安防平台预览url接口
根据不同的数据流返回不同的直播流,这里我主要用的hls的流来播放。hls取流有一个坑的就是摄像头编码得设置264.音频选择acc。
海康接口调用封装的是用php写的。
<?phpnamespace App\Model;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 = "\n"; $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的命令行说明