我已经尝试为这个问题寻找解决方案好几天了,我尝试了所有可以在 stackoverflow 和其他平台上找到的建议.仍然没有解决方案.
我正在通过 HTML5 视频标签嵌入视频:
我尝试通过 PHP 提供 MP4 视频文件,而不是直接链接它.直接链接mp4文件即可播放文件!
测试:
、.
在生产环境中,我总是使用 PHP 来检查引用者.正如我发现的,iPad 不会发送推荐人信息.这也会阻止流式传输,您还会看到无法播放符号(带删除线的播放图标).
我不知道为什么,但 iPad 只接受来自这个脚本的视频流http://ideone.com/NPSlw5
我希望这些信息能帮助其他人解决问题.
更新:三个月后,在生产环境中,我的一些用户仍然报告播放问题.Safari 似乎还有另一个问题.我建议他们使用 Chrome for iPad,这就解决了.
PS:几天的研究和麻烦只是为了播放一个视频文件,顺便说一下,它可以在所有其他设备上运行.这再次向我证明,Apple 的成功只是因为出色的营销,而不是因为出色的软件.
I am trying to find a solution for this problem for some days already, I tried all advices I could find here on stackoverflow and other platforms. And still, there is no solution.
I am embedding a video via HTML5 video tag:
<video poster="thumb.png" controls="controls" preload="none" width="640" height="480">
<source src="provider.php?secure=12345" type="video/mp4">
</video>
I try to deliver the MP4 video file by PHP instead of linking it directly. Linking the mp4 file directly works and plays the file!
Testing:
Notes:
My Setup:
The .htaccess
in the test folder sets the MIME type and Accept-Ranges:
AddType video/mp4 .mp4
<IfModule mod_headers.c>
Header set Accept-Ranges "bytes"
</IfModule>
Even though I created the same header (compare test URLs 1. and 2.), the iPad is not playing the file through the PHP request.
Instead I always get this strikedthrough play button:
The headers of 1. (direct mp4 call):
The headers of 2. The same headers as above, but set up by PHP (mp4 delivered by PHP):
--
I have also tried reading the entire video file and sending it to the browser using PHP's fread(), fpassthru() and file_get_contents() but the iPad is always showing the cannot-play-icon.
--
My hosted server does not supply Connection keep-alive, could this be a problem? Is the iPad interpreting .php different from .mp4?
Can somebody help me out of pain? I am totally stuck.
PS: What I tried to consider:
I finally got a MAC of a friend, connected the iPad, opened the Debug Console in Safari on the Mac, loaded the page on the iPad and checked the error messages appearing on the Mac (btw, how more complicated could apple force us to develop...). For all test scripts this error appears:
Failed to load resource: Plug-in handled load
Wow, that was tough!
It turned out to be no encoding problem but a problem with the mp4 container header set during the video conversion process - iPad has obviously a problem with MP4 videos that are prepared for progressive streaming.
First I discovered that in a conversation here. After converting a video I always used the tool MP4 Fast Start to prepare the video file for progressive stream. This was necessary to stream the video file to the Flash Player in pieces (progressively), so it did not load the entire file (and the user had to wait).
With Handbrake there is a similar setting, that is called Web Optimized
. It does the same:
Web Optimized
Also known as "Fast Start"
This places the container header at the start of the file, optimizing it for streaming across the web.
If you enable this and convert your video, the iPad will not play the video file! Instead you get the error "The operation could not be completed".
Check out and test it yourself: video test resources.
In production environment I always used PHP to check the referer. As I found out, the iPad does not send the referer information. This also prevents the streaming and you will also see the cannot-play-symbol (striked-through play icon).
I could not find out why, but the iPad only accepts the video streaming from this script http://ideone.com/NPSlw5
<?php
// disable zlib so that progress bar of player shows up correctly
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
$folder = '.';
$filename = 'video.mp4';
$path = $folder.'/'.$filename;
// from: http://licson.net/post/stream-videos-php/
if (file_exists($path)) {
// Clears the cache and prevent unwanted output
ob_clean();
$mime = "video/mp4"; // The MIME type of the file, this should be replaced with your own.
$size = filesize($path); // The size of the file
// Send the content type header
header('Content-type: ' . $mime);
// Check if it's a HTTP range request
if(isset($_SERVER['HTTP_RANGE'])){
// Parse the range header to get the byte offset
$ranges = array_map(
'intval', // Parse the parts into integer
explode(
'-', // The range separator
substr($_SERVER['HTTP_RANGE'], 6) // Skip the `bytes=` part of the header
)
);
// If the last range param is empty, it means the EOF (End of File)
if(!$ranges[1]){
$ranges[1] = $size - 1;
}
// Send the appropriate headers
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range
// Send the ranges we offered
header(
sprintf(
'Content-Range: bytes %d-%d/%d', // The header format
$ranges[0], // The start range
$ranges[1], // The end range
$size // Total size of the file
)
);
// It's time to output the file
$f = fopen($path, 'rb'); // Open the file in binary mode
$chunkSize = 8192; // The size of each chunk to output
// Seek to the requested start range
fseek($f, $ranges[0]);
// Start outputting the data
while(true){
// Check if we have outputted all the data requested
if(ftell($f) >= $ranges[1]){
break;
}
// Output the data
echo fread($f, $chunkSize);
// Flush the buffer immediately
@ob_flush();
flush();
}
}
else {
// It's not a range request, output the file anyway
header('Content-Length: ' . $size);
// Read the file
@readfile($path);
// and flush the buffer
@ob_flush();
flush();
}
}
die();
?>
I hope this information will help others to cope with the problem.
Update: Three months later in production environment, some of my users still reported playback issues. There seems to be another problem with Safari. I advised them to use Chrome for iPad, this fixed it.
PS: A couple of days of research and hassle only to play a video file that, by the way, runs on all other devices. This again proves to me that Apple got successful just because of great marketing, not because of great software.
这篇关于PHP:iPad 不能播放由 PHP 提供的 MP4 视频,但如果直接访问它可以的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!