用于在Safari 8中播放.MOV文件的HTML - 改变了什么?

时间:2015-08-07 22:01:02

标签: javascript html safari quicktime .mov

我有一个相当大的 QuickTime .MOV 文件库,这些文件由以前工作得很好的页面提供服务; HTML没有多年改变,但有人注意到它不再适用于Safari,尽管所有其他浏览器似乎都没问题。

相反,现在在OS X 中的 Safari 8.0.7中,它会显示" 缺少插件"按钮,按下时会弹出一个警告:

  

此网页包含需要互联网插件的内容。

     

此页面包含无法显示的内容,因为其类型未指定。   此页面可能包含供您下载和安装的插件:

     

http://www.apple.com/quicktime/download/

     

想要打开此页吗?

按OK就会把我带到那里,但我得到的OS X就是" QuickTime内置于Mac OS X中。"没有插件。

虽然我最喜欢切换到.MP4格式并使用HTML5 VIDEO标记,但我试图保持向后兼容性。除了新的视频标签只能播放MP4,WebM和Ogg格式。 Apple无法在自己的浏览器中播放QuickTime文件似乎很荒谬。 [见下面的更新]

除此之外......它可以。 直接将网址加载到.MOV文件,这表明它不是格式,而是错误的HTML 。事实上,我在plug-in list中列出了QuickTime 7.7.3。

生成的内容是:

<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="320" height="256" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,3,0,0" align="middle">
  <param name="src" value="file.mov">
  <param name="kioskmode" value="true">
  <embed src="file.mov" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true">
</object>

我说&#39;生成&#39;因为我遵循了Apple的HTML Scripting指南,即使用this exampleac_quicktime.js脚本(v1.2)编写的 Apple ,为给定的浏览器生成正确的代码。

<script language="javacript" type="text/javascript">
  QT_WriteOBJECT('file.mov', 
    '320', '256', 
    '',
    'kioskmode', 'true',
    'pluginspage','http://www.apple.com/quicktime/download/',
    'align', 'middle'); 
</script>

使用Safari的Web Inspector检查DOM,显示上面的JavaScript确实生成了对象/嵌入块。

我甚至用wget验证了直接拉媒体文件时MIME类型是否正确:

Content-Type: video/quicktime

使用Ghostery和uBlock Origin的一些小实验表明没有任何东西被阻挡。控制网站,它确认没有跟踪器,并且因为它生成了上述内容,所以它不会阻止JavaScript。

更多实验表明,我的iPhone和iPad上也会出现此问题。否#34;缺少插件&#34;按钮,只是画布上应该是电影的空洞。

ffprobe报告有效的视频文件(H.264,320x240; AAC 48000 Hz,Mono,29.97 fps,19.8 MB,294.68 kbit / s):

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'file.mov':
  Metadata:
    major_brand     : qt  
    minor_version   : 537199360
    compatible_brands: qt  
    creation_time   : 2007-09-17 02:37:42
  Duration: 00:08:42.39, start: 0.000000, bitrate: 302 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 80 kb/s (default)
    Metadata:
      creation_time   : 2007-09-17 02:37:42
      handler_name    : Apple Alias Data Handler
    Stream #0:1(eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, smpte170m/smpte170m/bt709), 320x240, 173 kb/s, 29.97 fps, 29.97 tbr, 2997 tbn, 5994 tbc (default)
    Metadata:
      creation_time   : 2007-09-17 02:37:42
      handler_name    : Apple Alias Data Handler
      encoder         : H.264
    Stream #0:2(eng): Data: none (rtp  / 0x20707472), 32 kb/s
    Metadata:
      creation_time   : 2007-09-17 02:37:42
      handler_name    : Apple Alias Data Handler
    Stream #0:3(eng): Data: none (rtp  / 0x20707472), 9 kb/s
    Metadata:
      creation_time   : 2007-09-17 02:37:42
      handler_name    : Apple Alias Data Handler

对可能发生的事情的任何想法?

更新#1:

建议使用HTML5 VIDEO标记,如下所示:

<video width="320" height="240" controls>
  <source src="file.mov" type="video/quicktime">
  Your browser does not support the video tag.
</video>

令我惊讶的是,这实际上是#34;工作&#34;在Safari中。但是,在其他不支持HTML5的浏览器中以及那些认识到这不支持视频格式的浏览器中,它可怕地破坏了。

因此确认VIDEO标记不是解决方案,因为这会破坏向后兼容性要求。

新信息:

我有一个忏悔。上面显示的file.mov是为了简化读者的示例。 实际值是一个包含PHP脚本的URL,用于选择要显示的.MOV文件。

我刚刚发现,当我使用.mov而不是.php的文件时,页面工作得很好。 这曾经用作PHP ...多年。

更令人不安的是, 该插件 正在查看正确传递的Content-Type,但文件扩展名为 。这可能是苹果公司的一个错误,也可能是我的错误(我希望是这样的)。但目前,它阻止我提供动态内容。

Apple的JavaScript函数正在使用我的URL生成正确的对象/嵌入标记,静态快照显示如果我使用扩展名为.mov的文件,它可以工作,但不是脚本,甚至如果两者都提供相同的内容。

我正在进行进一步的实验来断言内容类型是正确的。 wget说,Safari的网络检查员似乎不这么说。

更新#2:

奇怪的事情肯定会发生。

如果我直接在浏览器中加载file.mov,则会播放。

如果我直接在浏览器中加载此file.php,它也会播放。

<?php
  $filename = "file.mov";
  $handle = fopen( $filename, "rb" );
  if ( $handle ) {
    header( "Content-type: video/quicktime" ); 
    header( "Accept-Ranges: bytes" );
    header( "Content-Length: " . filesize( $filename ) );
    fpassthru( $handle );
    flush();
    exit;
  } // if handle
?>

如果我在浏览器中加载此file.html,则会发生有趣的事情。第一个条目显示Missing Plug-In,其他条目播放。

<HTML>
<BODY>

<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="320" height="256" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" align="middle">
    <param name="src" value="file.php">
    <param name="kioskmode" value="true">
    <embed src="file.php" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true">
</object>

<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="320" height="256" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" align="middle">
    <param name="src" value="file.mov">
    <param name="kioskmode" value="true">
    <embed src="file.mov" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true">
</object>

<video width="320" height="240" controls>
  <source src="file.php" type="video/quicktime">
  Your browser does not support the video tag.
</video>

<video width="320" height="240" controls>
  <source src="file.mov" type="video/quicktime">
  Your browser does not support the video tag.
</video>

</BODY>
</HTML>

至少对我来说,这表明Apple 有一个错误,因为它不会加载动态内容。

同意?不同意?想法?

真的好奇&#34;对&#34;这样做的方法是。

另一项实验,我将video/quicktime更改为video/mp4,它适用于Safari版本。

我担心我可能必须检测浏览器是否为Safari,如果它处理VIDEO标记,如果是,则使用.php选择代码而不是Apple的object / embed标记发出该hack

更新3:

发现Safari正在发出此错误消息:

Failed to load resource: Plug-in handled load

发现这篇有趣的帖子someone else confirms that videos from PHP don't work, but directly served they do

这表明视频不应再通过blob servers发送。

解决:

这就是问题所在。曾经有人能够发送整个文件,Safari和iOS不再那样了。

这就是为什么提供相同内容的行为方式不同。这是问题的传递机制,而不是内容。

查看有关使用PHP代码和信用的标记答案。

1 个答案:

答案 0 :(得分:1)

这篇StackOverflow文章让我找到了一个有效的解决方案:

Using php to output an mp4 video

问题是Safari和iOS不希望一次性传送整个.MOV文件,事实上,插件会抛出错误。相反,它想把它搞定。

这是解决问题的代码,几乎从上面的答案中获取并包含在函数中:

function RenderVideo( $file ) {

  $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");
  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);
      flush();
  }

  fclose($fp);
  exit();

}