HTML for playing .MOV files in Safari 8 — What Changed?

痞子三分冷 提交于 2021-01-21 10:51:06

问题


I have a fairly large library of QuickTime .MOV files that get served by a page that used to work great; the HTML hasn't changed in years, but someone noticed it no longer works in Safari, although all other browsers seem to be fine.

Instead, now in Safari 8.0.7 in OS X, it shows a "Missing Plug-In" button, which when pressed pops up an alert that says:

This web page has content that requires an Internet plug-in.

This page contains content that cannot be shown because its type is unspecified. This page may have the plug-in for you to download and install:

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

Want to open this page?

Pressing OK takes me there, but all I get with OS X is "QuickTime is built into Mac OS X." No plug-in.

While I'd like nothing better than to switch to .MP4 format and use the HTML5 VIDEO tag, I'm trying to maintain backwards compatibility. Besides the new video tag can only play MP4, WebM, and Ogg formats. It seems absurd that Apple can't play QuickTime files in its own browser. [see UPDATE below]

Except that... it can. Loading the direct URL to the .MOV file plays perfectly, suggesting it's not so much the format, but the HTML that's at fault. In fact, I see QuickTime 7.7.3 listed in the plug-in list.

What's being generated is:

<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>

I say 'generated' because I'm following Apple's HTML Scripting guidelines, which say to use this example's ac_quicktime.js script (v1.2), written by Apple, to generate the correct code for the given browser.

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

Inspecting the DOM with Safari's Web Inspector shows the JavaScript above does indeed generate the object/embed block.

I've even validated with wget that the MIME type is correct when pulling the media file directly:

Content-Type: video/quicktime

A little experimentation using Ghostery and uBlock Origin show nothing is being blocked. Being in control of the site, it confirms there are no trackers, and as it generates the above content, it isn't blocking JavaScript.

More experimentation shows this problem happens on my iPhone and iPad as well. No "Missing Plug-In" button, just a empty hole on the canvas where the movie should be.

ffprobe reports a valid video file (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

Any thoughts of what might be happening?


UPDATE #1:

It was suggested to use the HTML5 VIDEO tag, like so:

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

To my surprise, this actually "worked" in Safari. However, it broke horribly in other browsers that didn't support HTML5 as well as those that recognized this was not a supported video format.

It has therefore been confirmed the VIDEO tag is not the solution, as this breaks the backwards compatibility requirement.

NEW INFORMATION:

I have a confession. The file.mov shown above was done to simplify the example for readers. The actual value is a URL containing a PHP script that selects which .MOV file to display.

I just discovered that when I use a file with .mov, rather than .php, the page works just fine. This used to work as PHP ...for years.

More disturbing, it appears that the plug-in is not looking at the Content-Type that's correctly being passed, but the file extension. This is either a bug on Apple's part, or a mistake on mine (and I hope that's the case). But at the moment, it's preventing me from serving dynamic content.

Apple's JavaScript function is generating the correct object/embed tags with my URL, and a static snapshot shows that if I use a file with the .mov extension it works, but not the script, even if both deliver identical content.

I'm doing further experiments to assert the Content-Type is coming across correctly. wget says it is, Safari's web inspector seems to saying otherwise.


UPDATE #2:

Something strange is most certainly going on.

If I load file.mov in the browser directly, it plays.

If I load this file.php in the browser directly, it also plays.

<?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
?>

If I load this file.html in the browser, interesting things happen. The first entry shows a Missing Plug-In, the others play.

<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>

This suggests, to me at least, that Apple does have a bug in that it will not load dynamic content.

Concur? Disagree? Thoughts?

I'm not really curious what the "right" way to do this is.

Another experiment, I changed the video/quicktime to video/mp4 and it worked for the Safari version.

I fear I may have to detect if the browser is Safari, if it handles the VIDEO tag, and if so, emit that hack using the .php selection code instead of Apple's object/embed tags.

UPDATE 3:

Discovered that Safari is issuing this error message:

Failed to load resource: Plug-in handled load

Found this interesting post in which someone else confirms that videos from PHP don't work, but directly served they do.

This suggests videos should no longer be sent via blob servers.

SOLVED:

That was the problem. Where one used to be able to send the whole file, Safari and iOS don't like that anymore.

This is why delivering the same content behaved differently. It was the delivery mechanism, not the content, that was the problem.

See the marked answer for working PHP code and credits.


回答1:


This StackOverflow article got me to a working solution:

Using php to output an mp4 video

The problem is that Safari and iOS don't want the whole .MOV file delivered at once, and in fact, the plug-in will throw an error. Rather it wants to chunk it up.

Here's the code that solved the problem, taken pretty much from the answer above and wrapped in a function:

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();

}


来源:https://stackoverflow.com/questions/31887262/html-for-playing-mov-files-in-safari-8-what-changed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!