HTML5视频寻求在CakePHP [英] HTML5 video seeking in CakePHP
问题描述
我有视频流工作在CakePHP很好。由于视频是每个用户的私有,我有一个CakePHP控制器提供的文件,如果用户的身份验证。我也注意到,发送到服务器的所有请求都在他们的请求中有 Cookie:CAKEPHP =< stuff>
标头。
I have video streaming working just fine in CakePHP. Since the videos are private to each user, I have a CakePHP controller serve up the files if the users are authenticated. I also notice that all requests sent to the server have a Cookie: CAKEPHP=<stuff>
header in their request.
问题是,当用户暂停,然后播放视频时,或者当用户沿着视频进行搜索时,Chrome会向我的服务器发送一个具有特定字节范围的Range请求。该请求会立即被取消。请注意,此请求没有 Cookie:CAKEPHP =< stuff>
头。
The problem is that when a user pauses, then plays the video or when the user seeks along the video, Chrome sends a Range request with a certain byte range for my server to deliver. The request gets cancelled immediately. It should be noted that this request has no Cookie: CAKEPHP=<stuff>
header.
我相信请求被拒绝,因为没有会话cookie。如何强制Chrome(以及其他浏览器)发送会话Cookie?
I believe the request is denied because there is no session cookie. How can I force chrome (and possibly other browsers) to send a session cookie?
我的CakePHP版本为2.4.1
My CakePHP Version is 2.4.1
编辑:
view_media.ctp
view_media.ctp
<?php echo $this->Html->script(array('//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js', 'mediaelement-and-player'), array('inline' => false));
echo $this->Html->css(array('mediaelementplayer.min'), array('inline' => false));
?>
<video width="320" height="240" controls preload="none">
<?php
if(isset($_SERVER['HTTP_USER_AGENT'])){
$agent = $_SERVER['HTTP_USER_AGENT'];
if (strpos($agent,'Chrome') !== false) {
echo '<source src="/pages/get_media/264/webm" type="video/webm">';
}
if (strpos($agent,'Mozilla') !== false) {
echo '<source src="/pages/get_media/264/mp4" type="video/mp4">';
}
}
?>
Your browser does not support HTML5.
</video>
(控制器中的view_media函数为空)
(The view_media function in the Controller is blank)
PagesController的相关部分
Relevant section of PagesController
public function get_media($id, $type){
$dbh = new PDO('mysql:host='.$dbhost;dbname=$dbname, $username, $password);
//get media info
$sth = $dbh->prepare("SELECT `owner`, `type` FROM media WHERE id=:id");
$sth->bindParam(':id', $id);
$sth->execute();
$row = $sth->fetch();
if($row['owner'] == $this->Auth->user('id')){
if($row['type'] == 'png'){
header("Content-type: image/png");
echo file_get_contents("/srv/Ads/Ad_".$id.".png");
}else if($row['type'] == 'mp4'){
if($type == "mp4"){
header("Content-type: video/mp4");
$filename = "/srv/Ads/Ad_".$id.".mp4";
}else if($type == "webm"){
header("Content-type: video/webm");
$filename = "/srv/Ads/Ad_".$id.".webm";
}else{
die;
}
$this->send_video($filename);
}
die;
}
}
//thanks to http://stackoverflow.com/questions/16732419/mp4-from-php-not-playing-in-html5-video-tag
private function send_video($path){
if (file_exists($path)){
$size=filesize($path);
$fm=@fopen($path,'rb');
if(!$fm) {
// You can also redirect here
header ("HTTP/1.0 404 Not Found");
die;
}
$begin=0;
$end=$size;
if(isset($_SERVER['HTTP_RANGE'])) {
if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i',
$_SERVER['HTTP_RANGE'],$matches)){
$begin=intval($matches[0]);
if(!empty($matches[1])) {
$end=intval($matches[1]);
}
}
}
if($begin>0||$end<$size)
header('HTTP/1.0 206 Partial Content');
else
header('HTTP/1.0 200 OK');
header('Accept-Ranges: bytes');
header('Content-Length:'.($end-$begin));
header("Content-Disposition: inline;");
header("Content-Range: bytes $begin-$end/$size");
header("Content-Transfer-Encoding: binary\n");
header('Connection: close');
$cur=$begin;
fseek($fm,$begin,0);
while(!feof($fm)&&$cur<$end&&(connection_status()==0)){
echo fread($fm,min(1024*16,$end-$cur));
$cur+=1024*16;
usleep(1000);
}
die;
}
}
(get_media没有视图)
(get_media has no view)
这些都是请求。 manage_media.js目前为空,我将使用它来加载这个视频内容正在工作的所有媒体文件。
These are the requests. manage_media.js is blank for now, I will use it to load all media files one this video thing is working.
推荐答案
正确地,它只是控制台无法正确显示它的服务器响应是不正确的。请尝试使用 Charles 等调试代理来检查请求。
I think the request is actually made correctly, it's just the console not displaying it properly as the servers response is not correct. Try using a debug proxy like Charles to check the request.
响应始终以字节 0
它使用第一个字节位置作为最后一个字节位置,因为在正则表达式匹配中使用了错误的索引。索引 0
包含整个匹配的主题,即完整的 bytes = xyz
字符串,索引 1
The response always serves starting from byte 0
and it uses the first byte position as the last byte position, both because the wrong indices are used on the regex matches. Index 0
contains the whole matched subject, ie the complete bytes=xyz
string, and index 1
contains the first capture, ie the first byte position.
您正在查找的实际捕获值位于索引 1
和 2
。
The actual captured values you are looking for are located at index 1
and 2
.
$begin=intval($matches[1]);
if(!empty($matches[2])) {
$end=intval($matches[2]);
}
无效的内容范围
另外, Content-Range
头错误,最后一个字节位置必须是 end - 1
0
。
Invalid content range
Also the Content-Range
header is wrong, the last byte position must be end - 1
as the first byte starts at 0
.
$last = $end - 1;
header("Content-Range: bytes $begin-$last/$size");
另请参阅 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
See also http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
一个byte-content-range-spec,带有一个byte-range-resp- spec,其最后一个字节的pos值小于第一个字节的pos值,或者其实例长度值小于或等于其最后一个字节的pos值,无效。
A byte-content-range-spec with a byte-range-resp-spec whose last- byte-pos value is less than its first-byte-pos value, or whose instance-length value is less than or equal to its last-byte-pos value, is invalid. The recipient of an invalid byte-content-range- spec MUST ignore it and any content transferred along with it.
[...]
假设实体总共包含1234个字节,byte-content-range-spec值的示例:
Examples of byte-content-range-spec values, assuming that the entity contains a total of 1234 bytes:
。前500个字节:
字节0-499 / 1234
。第二个500字节:
字节500-999 / 1234
。除了前500个字节:
字节500-1233 / 1234
。最后500个字节:
字节734-1233 / 1234
使用CakePHP代替
btw,有没有理由不使用CakePHP功能来查询数据库和服务文件?
Use CakePHP instead
btw, is there a reason why you aren't using the CakePHP functionality for querying the database and serving files? You would save yourself a lot of trouble that way.
请参阅 http://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse
See http://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse
一些(未测试的)示例代码:
Some (untested) example code:
public function get_media($id, $type)
{
$media = $this->Media->findById($id, array('Media.owner', 'Media.type'));
if($media['Media']['owner'] !== $this->Auth->user('id'))
{
throw new ForbiddenException();
}
$file = null;
if($media['Media']['type'] == 'png')
{
$file = "/srv/Ads/Ad_".$id.".png";
}
else if($media['Media']['type'] == 'mp4')
{
if($type == "mp4")
{
$file = "/srv/Ads/Ad_".$id.".mp4";
}
else if($type == "webm")
{
$file = "/srv/Ads/Ad_".$id.".webm";
}
}
$this->response->file($file, array('download' => true));
return $this->response;
}
这篇关于HTML5视频寻求在CakePHP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!