我正在运行PHP-FPM 5.6和Nginx 1.7.6。
我正在使用PHP文件提供Matroska / Mp4电影。代码是:这一个:
<?php
register_shutdown_function( 'shutdown' );
$request = 'movie.mp4';
header( 'X-Accel-Buffering: no' ); //avoid nginx buffering.
header( 'Content-type: video/mp4' );
if ( file_exists( $request ) )
{
$fp = @fopen( $request, 'rb' );
$size = filesize( $request ); // File size
$length = $size; // Content length
$start = 0; // Start byte
$end = $size - 1; // End byte
header( "Accept-Ranges: 0-$length" );
if ( isset( $_SERVER['HTTP_RANGE'] ) )
{
$c_start = $start;
$c_end = $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 $start-$end/$size" );
exit;
}
if ( $range == '-' )
{
$c_start = $size - substr( $range, 1 );
}
else
{
$range = explode( '-', $range );
$c_start = $range[0];
$c_end = ( isset( $range[1] ) && is_numeric( $range[1] ) ) ? $range[1] : $size;
}
$c_end = ( $c_end > $end ) ? $end : $c_end;
if ( $c_start > $c_end || $c_start > $size - 1 || $c_end >= $size )
{
header( 'HTTP/1.1 416 Requested Range Not Satisfiable' );
header( "Content-Range: bytes $start-$end/$size" );
exit;
}
$start = $c_start;
$end = $c_end;
$length = $end - $start + 1;
fseek( $fp, $start );
header( 'HTTP/1.1 206 Partial Content' );
}
header( "Content-Range: bytes $start-$end/$size" );
header( "Content-Length: " . $length );
ob_end_flush();
$buffer = 1024 * 8;
while ( ! feof( $fp ) && ClientConnected() && ( $p = ftell( $fp ) ) <= $end )
{
$response = stream_get_line( $fp, $buffer );
echo $response;
}
fclose( $fp );
}
function ClientConnected()
{
if ( connection_status() != CONNECTION_NORMAL || connection_aborted() )
{
return false;
}
return true;
}
function shutdown()
{
//main cause of problems is that line
//posix_kill( getmypid(), 9 );
}
您会注意到上面的脚本支持Accept范围,因此用户可以查看电影! 该功能与电影本身完美配合。我可以通过访问该文件从我的播放器中看到电影而没有任何问题。
问题在于关机功能。您可能会问我为什么要使用posix_kill并杀死php pid。
用户可以选择从我的应用程序中查看多部电影。用户对可以打开到我的服务器的连接具有LIMIT。这意味着如果用户有1个可用的插槽连接到服务器,他将只能同时打开一部电影。
出于这个原因,让我们说用户正在观看电影并且他想将当前电影ZAP(改变)到另一个电影。
他无法做到这一点,因为旧的连接不会快速结束,并且pid将保持打开几秒钟。
如果我们取消注释上述代码的// posix_kill ,则用户根本无法看到任何电影,因为posix_kill函数会以某种方式覆盖以上所有标题和nginx / php都没有发送我在文件中的标题。
但是,如果我禁用HTTP SEEK并按照说明启用posix_kill,用户将能够观看电影,但他无法寻找。发生这种情况是因为当我们有Accept-Ranges标题时,玩家会在打开电影之前对电影做多个请求。
因此,例如,玩家将对该PHP文件执行2-3次请求以理解和识别搜索。然而,Posix_kill会快速杀死那些pid,并且玩家将无法选择正确的标题。
因此,我们需要一种解决方案,当用户关闭连接但仍然是搜索支持时,将立即删除服务器中连接的PID。
PS。启用了posix_kill的上述代码可以在直播中完美地工作,因为我们没有寻求,所以玩家只会发出一个请求。
希望你了解我 谢谢答案 0 :(得分:1)
如果您没有任何安全问题。比使用nginx的mp4模块。它将你作为mp4的伪流媒体工作。在此之后,你不需要PHP在任何部分寻找电影。 Nginx handel本身。
答案 1 :(得分:0)
来自PHP手册:
此函数将所有响应数据刷新到客户端并完成 请求。这允许在没有执行的情况下执行耗时的任务 将连接保持打开状态。
我的关机功能变成了这样:
function shutdown()
{
fastcgi_finish_request();
posix_kill( getmypid(), 9 );
}