Я запускаю PHP-FPM 5.6 и Nginx 1.7.6.
Я обслуживаю фильмы Matroska / Mp4, используя файл PHP. Код: этот:
<?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 не отправляет заголовки, которые у меня есть в файле ,
Однако, если i DISABLE HTTP SEEK и включите posix_kill, как описано, пользователь сможет смотреть фильмы, но он не сможет найти . Это происходит потому, что, когда у нас есть заголовок Accept-Ranges, игроки делают несколько запросов к фильму, прежде чем открывать его.
Так, например, игрок будет делать 2-3 запроса к этому файлу PHP, чтобы понять и идентифицировать поиск. Posix_kill, однако, быстро убьет эти pids, и игрок не сможет принять правильные заголовки.
Таким образом, нам нужно решение, которое сделает PID соединения на сервере мгновенно удаляться, когда пользователь закроет соединение, но останется поддержкой поиска.
PS. Вышеприведенный код с включенным posix_kill работает ОТЛИЧНО в режиме потокового вещания, поскольку мы не стремимся, чтобы игрок сделал только один запрос.
Надеюсь, ты меня понял
Если у вас нет проблемы с безопасностью. Тогда используйте mp4-модуль nginx. Он работает как псевдо-потоковая передача для mp4. После этого вам не нужен php, чтобы искать фильм на любой части. Сам Nginx.
Я решил проблему с fastcgi_finish_request ();
Из руководства PHP:
Эта функция удаляет все данные ответа клиенту и завершает запрос. Это позволяет выполнять трудоемкие задачи, не оставляя открытое соединение с клиентом.
Моя функция останова:
function shutdown() { fastcgi_finish_request(); posix_kill( getmypid(), 9 ); }