php中使用视频流的方式播放视频。

tech2023-09-26  106

1.什么是视频流?

视频流是指视频数据的传输,例如,它能够被作为一个稳定的和连续的流通过网络处理。因为流动,客户机浏览器或插件能够在整个文件被传输完成前显示多媒体数据。视频流技术基于 2 密钥技术,视频译码技术和可升级的视频分发技术发展。(摘自百度)

2.为什么要用视频流播放视频

最近在做项目开发的时候遇到一个问题,进行视频播放的时候后端php通过接口返回视频的地址,前端进行页面播放的时候会出现2-300M大小的视频浏览器可以直接加载,但是超过500M左右的视频就会出现浏览器解析不了变成下载的情况,经过上网查询了解了一些前人的一些方法,这里做一下总结。

3.封装的class类方法

VideostreamClass.php

<?php namespace app\statistics\controller;//当前在Thinkphp5框架中使用,需要使用到命名空间。 class VideostreamClass { private $stream = ''; private $buffer = 102400; private $start = -1; private $end = -1; private $size = 0; function __construct($filePath) { $this->path = $filePath; } //打开文件流 private function open() { if (!($this->stream = fopen($this->path, 'rb'))) { return json(['code'=>-1,'msg'=>'无法解析视频流']); } } //设置header头 private function setHeader() { ob_get_clean(); header("Content-Type: video/mp4"); header("Cache-Control: max-age=2592000, public"); header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT'); header("Last-Modified: ".gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT' ); $this->start = 0; $this->size = filesize($this->path); $this->end = $this->size - 1; header("Accept-Ranges: 0-".$this->end); if (isset($_SERVER['HTTP_RANGE'])) { $c_end = $this->end; list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); if (strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } if ($range == '-') { $c_start = $this->size - substr($range, 1); } else { $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; } $c_end = ($c_end > $this->end) ? $this->end : $c_end; if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } $this->start = $c_start; $this->end = $c_end; $length = $this->end - $this->start + 1; fseek($this->stream,$this->start); header('HTTP/1.1 206 Partial Content'); header("Content-Length: ".$length); header("Content-Range: bytes $this->start-$this->end/".$this->size); } else { header("Content-Length: ".$this->size); } } //关闭文件流 private function end() { fclose($this->stream); exit; } //执行计算范围的流式处理 private function stream() { $i = $this->start; set_time_limit(0); while(!feof($this->stream) && $i <= $this->end) { $bytesToRead = $this->buffer; if(($i+$bytesToRead) > $this->end) { $bytesToRead = $this->end - $i + 1; } $data = fread($this->stream,$bytesToRead); echo $data; flush(); $i += $bytesToRead; } } //开始处理 public function start() { $this->open(); $this->setHeader(); $this->stream(); $this->end(); } }

4.使用方法

使用方法非常简单,正常use引用,然后new这个类。

public function previewVideo(Request $request) { //跨域发送请求 header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Methods:OPTIONS, GET, POST');//允许option,get,post请求 header('Access-Control-Allow-Headers:X-Requested-With,id,token');//允许x-requested-with请求头,需要添加header头里的参数可以继续添加 //文件名 $fileName = 'example.mp4'; //将路径全部转为中文,防止出现乱码 $fileName = iconv("utf-8", "gb2312//IGNORE", $fileName); //文件路径,这里需要使用绝对路径 $file_path = 'G:\BaiduNetdiskDownload\example.mp4'; //new自定义方法类 $stream = new VideostreamClass($file_path); $stream->start(); }

5.不足和缺陷

(1)经过测试这种方法可以直接通过接口进行调用,在谷歌浏览器中可以直接进行解析播放所要播放的视频。但是在 IE11 浏览器中则会自动调用 windows 10 自带的 windows media player 播放器进行播放。 (2)目前只进行了mp4格式的视频文件进行测试,其他格式的视频文件有待后续测试。

最新回复(0)