2010-06-27 14 views
16

पर PHP के माध्यम से पढ़ते समय नहीं, मैं उनकी सेवा करने से पहले वीडियो अनुरोधों को सत्यापित करने के लिए एक PHP स्क्रिप्ट का उपयोग करता हूं। यह स्क्रिप्ट सफारी और क्रोम के साथ डेस्कटॉप पर अपेक्षित काम करता है। लेकिन आईओएस पर, मुझे टूटा हुआ प्ले बटन मिलता है।एमपी 4 चलाता है जब सीधे पहुंचाया जाता है, लेकिन आईओएस

मुझे यकीन है कि वीडियो आईफोन/आईपैड के लिए ठीक से एन्कोड किया गया है, क्योंकि जब मैं इसे सीधे एक्सेस करता हूं, तो यह अपेक्षा के अनुसार काम करता है।

प्रासंगिक PHP कोड:

$file_name = 'test-video.mp4'; 
$file_size = (string)(filesize($file_name)); 
header('Content-Type: video/mp4'); 
header('Content-Length: '.$file_size); 
readfile_chunked($file_name); 
exit; 

(readfile_chunked()readfile() के लिए, लेकिन बहुत बड़ी फ़ाइलों, पीएचपी मैनुअल पृष्ठ पर मौजूद टिप्पणियों में पाया के लिए इसी तरह की है:। http://php.net/manual/en/function.readfile.php किसी भी घटना में, test-video.mp4 केवल ~ 5 MB है ।, जो स्मृति सीमा से कम है - और इस मामले में मैं वास्तव में सामान्य readfile() में स्थानापन्न और ठीक उसी व्यवहार उत्पादन कर सकते हैं)

हेडर जब मैं test-video.mp4 का उपयोग मैं सीधे हैं:

+०१२३५१६४१०
Accept-Ranges:bytes 
Connection:Keep-Alive 
Content-Length:5558749 
Content-Type:video/mp4 
Date:Sun, 27 Jun 2010 21:02:09 GMT 
Etag:"1c04757-54d1dd-489944c5a6400" 
Keep-Alive:timeout=10, max=30 
Last-Modified:Tue, 22 Jun 2010 01:25:36 GMT 
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635 

PHP स्क्रिप्ट से हेडर हैं:

Connection:Keep-Alive 
Content-Disposition:inline; filename="test-video.mp4" 
Content-Length:5558749 
Content-Type:video/mp4 
Date:Sun, 27 Jun 2010 21:03:32 GMT 
Keep-Alive:timeout=10, max=15 
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635 
X-Powered-By:PHP/5.2.13 

मैं कोई लाभ नहीं हुआ हेडर के कई अलग अलग क्रमपरिवर्तन की कोशिश की है, यहां तक ​​कि उन्हें वास्तव में एक सीधा अनुरोध से उन लोगों के लिए मिलान,।

क्या किसी ने आईओएस पर PHP के माध्यम से एचटीएमएल 5 वीडियो की सफलता हासिल की है?

[ध्यान दें:। मैं एक्स Sendfile का उपयोग कर की कोशिश करेंगे, लेकिन साइट बहुत ही सीमित उपयोग के साथ एक साझा मेजबान पर है]

संपादित करें: मैं पढ़ रहा था कि आईओएस तो फ़ाइल एक्सटेंशन के बारे में संवेदनशील हो सकता है, मैंने एक रिवाइटरूल सेट अप करने का प्रयास किया जो MP4 अनुरोधों को मेरी मूल PHP स्क्रिप्ट पर वापस लिखता है, लेकिन इससे कोई मदद नहीं मिली।

उत्तर

8

यदि आप इसे अपने आप संभालने में सक्षम हैं, तो आपको बाइट-रेंज अनुरोधों को स्वयं भी संभालना होगा।

+4

बिल्कुल सही - मैं तो बस कॉपी करने समाप्त हो गया 'rangeDownload()' परिशिष्ट A से समारोह निम्न आलेख की: http://mobiforge.com/developing/story/content-delivery-mobile-devices (क्या अच्छा है इस फ़ंक्शन के बारे में यह उपयोगकर्ता को टाइमलाइन पर क्लिक करके वीडियो में किसी भी बिंदु से प्लेबैक शुरू करने की इजाजत देता है।) मुझे लगता है कि मैं यहां समस्या से विशेष रूप से उलझन में था क्योंकि यह डेस्कटॉप पर पूरी तरह से काम करता था, जबकि आईओएस में यह बाइट है -रेंज आवश्यकता। – JKS

15

प्रयास करें:

$arquivo_caminho = 'path\file' 

    if (is_file($arquivo_caminho)){ 
     header("Content-type: video/mp4"); // change mimetype 

     if (isset($_SERVER['HTTP_RANGE'])){ // do it for any device that supports byte-ranges not only iPhone 
      rangeDownload($arquivo_caminho); 
     } else { 
      header("Content-length: " . filesize($arquivo_caminho)); 
      readfile($arquivo_caminho); 
     } // fim do if 
    } // fim do if 

    function rangeDownload($file){ 
     $fp = @fopen($file, 'rb'); 

     $size = filesize($file); // File size 
     $length = $size;   // Content length 
     $start = 0;    // Start byte 
     $end = $size - 1;  // End byte 
     // Now that we've gotten so far without errors we send the accept range header 
     /* At the moment we only support single ranges. 
     * Multiple ranges requires some more work to ensure it works correctly 
     * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 
     * 
     * Multirange support annouces itself with: 
     * header('Accept-Ranges: bytes'); 
     * 
     * Multirange content must be sent with multipart/byteranges mediatype, 
     * (mediatype = mimetype) 
     * as well as a boundry header to indicate the various chunks of data. 
     */ 
     header("Accept-Ranges: 0-$length"); 
     // header('Accept-Ranges: bytes'); 
     // multipart/byteranges 
     // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 
     if (isset($_SERVER['HTTP_RANGE'])){ 
      $c_start = $start; 
      $c_end = $end; 

      // Extract the range string 
      list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); 
      // Make sure the client hasn't sent us a multibyte range 
      if (strpos($range, ',') !== false){ 
       // (?) Shoud this be issued here, or should the first 
       // range be used? Or should the header be ignored and 
       // we output the whole content? 
       header('HTTP/1.1 416 Requested Range Not Satisfiable'); 
       header("Content-Range: bytes $start-$end/$size"); 
       // (?) Echo some info to the client? 
       exit; 
      } // fim do if 
      // If the range starts with an '-' we start from the beginning 
      // If not, we forward the file pointer 
      // And make sure to get the end byte if spesified 
      if ($range{0} == '-'){ 
       // The n-number of the last bytes is requested 
       $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; 
      } // fim do if 
      /* Check the range and make sure it's treated according to the specs. 
      * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 
      */ 
      // End bytes can not be larger than $end. 
      $c_end = ($c_end > $end) ? $end : $c_end; 
      // Validate the requested range and return an error if it's not correct. 
      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"); 
       // (?) Echo some info to the client? 
       exit; 
      } // fim do if 

      $start = $c_start; 
      $end = $c_end; 
      $length = $end - $start + 1; // Calculate new content length 
      fseek($fp, $start); 
      header('HTTP/1.1 206 Partial Content'); 
     } // fim do if 

     // Notify the client the byte range we'll be outputting 
     header("Content-Range: bytes $start-$end/$size"); 
     header("Content-Length: $length"); 

     // Start buffered download 
     $buffer = 1024 * 8; 
     while(!feof($fp) && ($p = ftell($fp)) <= $end){ 
      if ($p + $buffer > $end){ 
       // In case we're only outputtin a chunk, make sure we don't 
       // read past the length 
       $buffer = $end - $p + 1; 
      } // fim do if 

      set_time_limit(0); // Reset time limit for big files 
      echo fread($fp, $buffer); 
      flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit. 
     } // fim do while 

     fclose($fp); 
    } // fim do function 
+0

वाह बहुत बहुत धन्यवाद! आईफोन 4 एस (आईओएस 6) पर यह निश्चित वीडियो मुद्दे, एंड्रॉइड 4.1.1 पर भी काम करता है और मैंने परीक्षण किए गए सभी डेस्कटॉप ब्राउज़र – teejay

+0

धन्यवाद! यह समस्या अब मुझे कई हफ्तों तक परेशान कर रही है। मैंने वास्तव में थोड़ी देर पहले आपके समाधान की कोशिश की लेकिन इसे गलत तरीके से लागू किया होगा ... आज फिर कोशिश की गई और एमपी 4 अब बिना किसी समस्या के आईओएस और डेस्कटॉप दोनों सफारी में PHP से गुजर रहा है। दूसरों के लिए, क्या हो रहा है (अधिक या कम) यह है कि सफारी बस एक एमपी 4 का अनुरोध नहीं करता है। इसके बजाय यह एक प्रारंभिक अनुरोध करता है जैसे आप उम्मीद करेंगे, लेकिन फिर रेंज हेडर का उपयोग करके कई बाद के खंड अनुरोध। – Synexis

+0

ठीक है, यह वास्तव में काम करता है। मुझे अभी भी समझ में नहीं आता क्यों .. – Geo

0

आप तो बजाय filsize http URL से फ़ाइल() पढ़ें आप प्राप्त फ़ाइल आकार के लिए नीचे दिए गए कोड उपयोगकर्ता ढंग से काम

function getFileSize($file) { 
     $ch = curl_init($file); 
     curl_setopt($ch, CURLOPT_NOBODY, true); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($ch, CURLOPT_HEADER, true); 
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
     $data = curl_exec($ch); 
     curl_close($ch); 
     $contentLength=0; 
     if (preg_match('/Content-Length: (\d+)/', $data, $matches)) { 

      // Contains file size in bytes 
      $contentLength = (int)$matches[1]; 

     } 
     return $contentLength; 
} 
0

कृपया ध्यान दें कि इस कोड है (https://mobiforge.com/design-development/content-delivery-mobile-devices) एक lifesaver है। या - हालांकि लाइन

"{अगर ('' $ रेंज {0} ==)" बचाव का ध्यान रखें "अगर ($ range0 == '-') {"

यह

होना चाहिए

अगर ($ रेंज [0] == '-') {

इस टाइपो पता लगाना क्यों यह काम नहीं किया एक बहुत लंबे समय में हुई।

0

मुझे उस कोड के साथ समस्या थी।

फिक्स:

set_time_limit(0); // Reset time limit for big files 

ob_clean(); //added 

echo fread($fp, $buffer); 
flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit. 
0

जैसा कि ऊपर स्ट्रीम करने के लिए या PHP का उपयोग प्लेबैक MP4 वीडियो, तुम बाइट पर्वतमाला अगर आप सफारी और iOS पर उचित प्लेबैक चाहते संभाल करने की आवश्यकता होगी कहा गया था।

rangeDownload() पिछले उत्तरों में उल्लिखित कार्य नौकरी बहुत अच्छी तरह से करता है।

मैं इस पहेली का एक और टुकड़ा उल्लेख करना चाहता हूं - सुनिश्चित करें कि वीडियो में स्रोत .mp4<video source="url/yourfile.php/referenceForFile.mp4"> के साथ समाप्त होता है। यह ब्राउज़र की बात करता है कि यह एक वीडियो फ़ाइल है, और यह इसे एक के रूप में इलाज शुरू कर देता है।

yourfile.php के अंदर, आप $_SERVER['PATH_INFO'] या REQUEST_URI के उपयोग से अपनी फ़ाइल के आने वाले संदर्भ को पकड़ सकते हैं। इसे ?id=someId.mp4 के रूप में पास करने की आवश्यकता नहीं है, प्रत्यक्ष स्लैश दृष्टिकोण वास्तविक फ़ाइल की तरह दिखता है।

सारांश में, पीएचपी से एक वीडियो फ़ाइल की सेवा करने के अपने अनुभव से सही ढंग से आप की आवश्यकता होगी:

  • बाइट रेंज समर्थन करते हैं। ब्राउज़र सर्वर को बताता है कि फ़ाइल के किस हिस्से की आवश्यकता है, और सर्वर को उस बाइट रेंज सामग्री के साथ प्रतिक्रिया देने की आवश्यकता है।
  • अपने moov atom फ़ाइल की शुरुआत में (आप इस्तेमाल कर सकते हैं ffmpeg के -movflags +faststart या MP4Box) वीडियो टैग की
  • <video source="...file.mp4"> स्रोत विशेषता एक .mp4 फ़ाइल की तरह लग रहे करने की जरूरत है। इसके बिना मेरे वीडियो केवल क्रोम में खेल रहे थे, न कि सफारी/आईओएस में।
  • प्रत्यक्ष एचटीएमएल 5 खिलाड़ी, या आप की तरह videojs

एक पुस्तकालय का उपयोग कर सकते मैं अपने संगीत वीडियो वेबसाइट पर वीडियो के हजारों की सेवा के साथ अपने अनुभव के आधार पर यह लिखा था। हालांकि यह सभी के लिए मामला नहीं हो सकता है, लेकिन मुझे यह क्रॉस-ब्राउज़र और क्रॉस-डिवाइस सेटअप काम अपेक्षित के रूप में मिला।