title: HTML for playing .MOV files in Safari 8 -- What Changed?
body: <p>I have a fairly large library of <strong>QuickTime .MOV</strong> files that get served by a page that used to work great; <strong>the HTML hasn't changed in years</strong>, but someone noticed it no longer works in Safari, although all other browsers seem to be fine.</p>
  
  <p>Instead, now in <strong>Safari 8.0.7 in OS X</strong>, it shows a "<strong>Missing Plug-In</strong>" button, which when pressed pops up an alert that says:</p>
  
  <blockquote>
    <p>This web page has content that requires an Internet plug-in.</p>
    
    <p>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:</p>
    
    <p><a href="http://www.apple.com/quicktime/download/" rel="nofollow noreferrer">http://www.apple.com/quicktime/download/</a> </p>
    
    <p>Want to open this page?</p>
  </blockquote>
  
  <p>Pressing OK takes me there, but all I get with OS X is "QuickTime is built into Mac OS X."  No plug-in.</p>
  
  <p>While I'd like nothing better than to switch to .MP4 format and use the HTML5 <a href="http://www.w3schools.com/tags/tag_video.asp" rel="nofollow noreferrer">VIDEO</a> tag, <strong>I'm trying to maintain backwards compatibility</strong>.  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]</p>
  
  <p>Except that... it can. <strong>Loading the direct URL to the .MOV file plays perfectly</strong>, suggesting it's not so much the format, but <strong>the HTML that's at fault</strong>.  In fact, I see QuickTime 7.7.3 listed in the <a href="http://file:///Applications/Safari.app/Contents/Resources/English.lproj/Plug-ins.html" rel="nofollow noreferrer">plug-in list</a>.</p>
  
  <p>What's being <em>generated</em> is:</p>
  
  <pre><code>&lt;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"&gt;
    &lt;param name="src" value="file.mov"&gt;
    &lt;param name="kioskmode" value="true"&gt;
    &lt;embed src="file.mov" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true"&gt;
  &lt;/object&gt;
  </code></pre>
  
  <p>I say 'generated' because I'm following Apple's <a href="https://developer.apple.com/library/safari/documentation/QuickTime/Conceptual/QTScripting_HTML/QTScripting_HTML_Document/ScriptingHTML.html#//apple_ref/doc/uid/TP40001525-2-HTMLScripting" rel="nofollow noreferrer">HTML Scripting</a> guidelines, which say to use <a href="https://developer.apple.com/library/safari/samplecode/HTML_video_example/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007723-Intro-DontLinkElementID_2" rel="nofollow noreferrer">this example</a>'s <code>ac_quicktime.js</code> script (v1.2), written <em>by Apple</em>, to generate the correct code for the given browser.</p>
  
  <pre><code>&lt;script language="javacript" type="text/javascript"&gt;
    QT_WriteOBJECT('file.mov', 
      '320', '256', 
      '',
      'kioskmode', 'true',
      'pluginspage','http://www.apple.com/quicktime/download/',
      'align', 'middle'); 
  &lt;/script&gt;
  </code></pre>
  
  <p>Inspecting the DOM with Safari's Web Inspector shows the JavaScript above does indeed generate the object/embed block.</p>
  
  <p>I've even validated with <code>wget</code> that the MIME type is correct when pulling the media file directly:</p>
  
  <pre><code>Content-Type: video/quicktime
  </code></pre>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p><a href="https://www.ffmpeg.org/ffprobe.html" rel="nofollow noreferrer">ffprobe</a> reports a valid video file (H.264, 320x240; AAC 48000 Hz, Mono, 29.97 fps, 19.8 MB, 294.68 kbit/s):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Any thoughts of what might be happening?</p>
  
  <hr>
  
  <p><strong>UPDATE #1:</strong></p>
  
  <p>It was suggested to use the HTML5 VIDEO tag, like so:</p>
  
  <pre><code>&lt;video width="320" height="240" controls&gt;
    &lt;source src="file.mov" type="video/quicktime"&gt;
    Your browser does not support the video tag.
  &lt;/video&gt;
  </code></pre>
  
  <p>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.</p>
  
  <p><strong>It has therefore been confirmed the VIDEO tag is not the solution</strong>, as this breaks the backwards compatibility requirement.</p>
  
  <p><strong>NEW INFORMATION:</strong></p>
  
  <p>I have a confession. The <code>file.mov</code> shown above was done to simplify the example for readers.  The <em>actual</em> value is a URL containing a PHP script that selects which .MOV file to display.</p>
  
  <p>I just discovered that when I use a file with <code>.mov</code>, rather than <code>.php</code>, the page works just fine. <em>This used to work as PHP ...for years.</em></p>
  
  <p>More disturbing, it <em>appears</em> that the plug-in is <em>not</em> looking at the <code>Content-Type</code> 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.</p>
  
  <p>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 <code>.mov</code> extension it works, but not the script, even if both deliver identical content.</p>
  
  <p>I'm doing further experiments to assert the Content-Type is coming across correctly. <code>wget</code> says it is, Safari's web inspector seems to saying otherwise.</p>
  
  <hr>
  
  <p><strong>UPDATE #2:</strong></p>
  
  <p>Something strange is most certainly going on.</p>
  
  <p>If I load <code>file.mov</code> in the browser directly, it plays.</p>
  
  <p>If I load this <code>file.php</code> in the browser directly, it also plays.</p>
  
  <pre><code>&lt;?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
  ?&gt;
  </code></pre>
  
  <p>If I load this <code>file.html</code> in the browser, interesting things happen.  The first entry shows a Missing Plug-In, the others play.</p>
  
  <pre><code>&lt;HTML&gt;
  &lt;BODY&gt;
  
  &lt;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"&gt;
      &lt;param name="src" value="file.php"&gt;
      &lt;param name="kioskmode" value="true"&gt;
      &lt;embed src="file.php" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true"&gt;
  &lt;/object&gt;
  
  &lt;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"&gt;
      &lt;param name="src" value="file.mov"&gt;
      &lt;param name="kioskmode" value="true"&gt;
      &lt;embed src="file.mov" width="320" height="256" pluginspage="http://www.apple.com/quicktime/download/" align="middle" kioskmode="true"&gt;
  &lt;/object&gt;
  
  &lt;video width="320" height="240" controls&gt;
    &lt;source src="file.php" type="video/quicktime"&gt;
    Your browser does not support the video tag.
  &lt;/video&gt;
  
  &lt;video width="320" height="240" controls&gt;
    &lt;source src="file.mov" type="video/quicktime"&gt;
    Your browser does not support the video tag.
  &lt;/video&gt;
  
  &lt;/BODY&gt;
  &lt;/HTML&gt;
  </code></pre>
  
  <p>This suggests, to me at least, that Apple <em>does</em> have a bug in that it will not load dynamic content.</p>
  
  <p>Concur? Disagree? Thoughts?</p>
  
  <p>I'm not <em>really</em> curious what the "right" way to do this is.</p>
  
  <p>Another experiment, I changed the <code>video/quicktime</code> to <code>video/mp4</code> and it worked for the Safari version.</p>
  
  <p>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 <code>.php</code> selection code instead of Apple's object/embed tags.</p>
  
  <p><strong>UPDATE 3:</strong></p>
  
  <p>Discovered that Safari is issuing this error message:</p>
  
  <pre><code>Failed to load resource: Plug-in handled load
  </code></pre>
  
  <p>Found this interesting post in which <a href="https://stackoverflow.com/questions/24042894/php-ipad-does-not-play-mp4-videos-delivered-by-php-but-if-accessed-directly-it">someone else confirms that videos from PHP don't work, but directly served they do</a>.</p>
  
  <p>This suggests videos should no longer be sent via <a href="https://stackoverflow.com/questions/18103103/failed-to-load-resource-plugin-handled-load-on-ios">blob servers</a>.</p>
  
  <p><strong>SOLVED:</strong></p>
  
  <p>That was the problem.  Where one used to be able to send the whole file, Safari and iOS don't like that anymore.</p>
  
  <p>This is why delivering the same content behaved differently.  It was the delivery mechanism, not the content, that was the problem.</p>
  
  <p>See the marked answer for working PHP code and credits.</p>