2016-04-19 6 views
0

Ich habe Probleme mit dem Streaming .mp4 Videos von PHP zu einem HTML5 Video Tag. Das Video streamt gut und bewegt sich auch vorwärts und rückwärts. ABER: Wenn ich auf einen Link in meinem Menü klicke, ändert sich die Site nicht. Das Ladesymbol erscheint auf der Registerkarte und die Entwicklungstools zeigen an, dass eine Anfrage vorliegt. Aber die Anfrage "wartet" bis zum Ende des Video-Streams. Wenn das Video beendet wurde, wird die neue Seite geladen, aber nicht vorher.PHP Stream zu html5 Video, Seite Navigation funktioniert nicht

Irgendwelche Ideen dazu?

PS: session_write_close() hinzufügen; vor dem Streaming löst die Datei das Problem. Aber es sieht ein bisschen zu Hacky für mich ...

<video style="width:100%;" preload="metadata" controls=""> 
<source src="/uploads/getfile?image_path=5%2FOKzAAFlSub-VLsnFWvkPWXBLluwOV-Q5DIuqJkPpDubahlAosK.mp4&amp;type=20" type="video/mp4"> 
Your browser does not support the video tag. 
</video> 

PHP-Code:

$file = Yii::getAlias('@app') . '/../files/uploads/' .$image_path; 
$fp = @fopen($file, 'rb');  
$size = filesize($file); // File size 
$length = $size;   // Content length 
$start = 0;    // Start byte 
$end = $size - 1;  // End byte 
header('Content-type: video/mp4'); 
header("Accept-Ranges: 0-$length"); 
header("Accept-Ranges: bytes"); 
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); 
$buffer = 1024 * 8; 
while(!feof($fp) && ($p = ftell($fp)) <= $end) { 
    if ($p + $buffer > $end) {  
     $buffer = $end - $p + 1;   
    }    
    set_time_limit(0);    
    echo fread($fp, $buffer);  
    ob_flush();  
} 
fclose($fp);  
exit(); 

Antwort

2

Hinzufügen session_write_close(); vor dem Streaming löst die Datei das Problem. Aber es sieht ein bisschen zu hacky für mich aus ...

Es gibt nicht viel "hacky" darüber.

Ein langer Laufzeit-Skript, das eine Sitzung offen hält für alle anderen Skripte Zugriff auf derselben Sitzung blockieren, die später beginnen (wie mit dem Menü-Link klicken.)

Um das zu vermeiden, schließen Sie das Sobald Sie fertig sind, können Sie die Sitzung im Skript mit langer Laufzeit starten, sodass die Sperre für die Sitzungsdatendatei freigegeben werden kann.


Was ist recht „Hacky“ aber ist das Streaming von Videodaten über ein Skript in dem ersten Platz. Das ist, was Sie in erster Linie vermeiden sollten, wenn überhaupt möglich. Es ist keine gute Idee in Bezug auf Speichernutzung und Skriptlaufzeiten.

+0

Danke für die Informationen. Die Sache ist, dass wir Inhalte haben, die nur für einige Leute sichtbar sein sollten und nicht für alle. Die Dateien werden also nicht öffentlich gespeichert. Im Moment sollte unser System nur ein paar Leuten dienen - es ist kein System für Tausende;) – Lugaru

0

Es ist besser, bereits vorhandenes PHP-Paket zu verwenden, um partiellen Download zu unterstützen. Hier ist einer von ihnen aus Birne:

http://pear.php.net/manual/en/package.http.http-download.php

Es verschiedene Arten von Download unterstützen (teilweise, Strom, ..). Hier ist ein Beispielcode:

$dl = &new HTTP_Download(); 
$dl->setData($data); 
$dl->setLastModified($unix_timestamp); 
$dl->setContentType('application/x-gzip'); 
$dl->setContentDisposition(HTTP_DOWNLOAD_ATTACHMENT, 'latest.tgz'); 
$dl->send();