16

In our Java EE application we use the HTML5 <video> tags for playing MP4 videos. We use JBoss 7 as the application server. Videos are retrieved via Struts2 action like this : www.myproject.com/namespace/documents/3/zbRdTKQKLWnA2ZiY61Gx

where zbRdTKQKLWnA2ZiY61Gx is a name of video on the server.

struts.xml :

...

<action name="documents/*/*" class="namespace.action.GestionDocumentAction" method="obtain">
    <param name="typeId">{1}</param>
    <param name="identifiantDocument">{2}</param>
    <result name="success" type="stream">
        <param name="contentType">video/mp4</param>
        <param name="inputName">flux</param>
        <param name="allowCaching">true</param>
        <param name="contentDisposition">inline;filename=${filename}</param>
    </result>
</action>

...

It works fine in Chrome and Firefox, but not in Safari on Mac.

In Safari when I open the page containing a <video> tag, "Loading" is displayed but it doesn't load the video.

Here comes the really weird thing.

If paste the link to a video directly in the browser, it plays correctly. Then if I reload the page with the said video, it plays fine.

The same thing happens with all videos in the application.

What is happening ? Why are the videos not playing at first?


Dev tools in Safari :

When I initially load the page I get the following result : enter image description here

All warnings are for CSS.

For opening the file directly in browser for the first time I get : enter image description here

The error is "Failed to load resource: load handled by the module" : enter image description here

When I reload the page I get the same response, but now I can play the video : enter image description here

I think the problem goes from range headers. Actually I use this one :

this.getServletResponse().setHeader("Accept-Ranges", "bytes");
this.getServletResponse().setHeader("Content-Type", "video/mp4");
this.getServletResponse().setHeader("Content-Length", "383631");      // 383631 - just for exemple, I use a real size
this.getServletResponse().setHeader("Content-Range", "bytes 0-383630/383631"); // 0-383630/383631 - the same
this.getServletResponse().setStatus(206);
illusion
  • 161
  • 1
  • 6
  • Hi @illusion are you using https? – Pablo Recalde Jul 28 '15 at 14:09
  • Hi @r1verside ! No, we use http. – illusion Jul 28 '15 at 14:13
  • Can you reproduce this in a fiddle with safari? Or is it specific to your enviroment (server)? – Szabolcs Páll Jul 28 '15 at 15:29
  • @SzabolcsPáll, it's specific to our environment, we use Struts2. I have updated the question. – illusion Jul 29 '15 at 07:20
  • Seems to me a mime-type issue, but might as well be a problem with the stream (that would explain why after caching it plays just fine), but it's hard to tell without having a test environment. – Szabolcs Páll Jul 29 '15 at 07:26
  • if you open the dev tools in Safari and look at error console and/or network resources when you initially load the page does anything appear weird? are you seeing the request in the server logs? – Offbeatmammal Aug 05 '15 at 03:51
  • @Offbeatmammal, I answered in my question. – illusion Aug 05 '15 at 17:06
  • What happens if your server appends the extension `.mp4` to the resource URL? (and of course, resolves it properly) – Aaron D Aug 10 '15 at 13:31
  • @AaronD, thanks for the idea. It seems to me that it's a right way. I have tried this, but it didn't change the situation. Perhaps, I didn't apply it correctly... but with a direct link in a browser it still works well. Do I need change something else in the code, header, for example? – illusion Aug 10 '15 at 16:37
  • There may be other problems. [Here](http://stackoverflow.com/questions/20347352/html5-video-tag-not-working-in-safari-iphone-and-ipad) is another list of answers to the same problem - one big one at least for iOS Safari is whether your application supports byte-range requests. [Here](https://gist.github.com/fehmicansaglam/1781977) is a GitHub gist showing one implementation of that. – Aaron D Aug 10 '15 at 17:05
  • @illusion I'm having a similar issue, did you ever find a solution? – Josh Sherick May 27 '16 at 22:03

1 Answers1

9

Safari has a problem where if the video resource requested does not specifically have the extension .mp4, even if the mime type is correctly set. I could replicate your problem - if the video resource was just a string identifier (without .mp4), Safari would display a preview for the video but it wouldn't actually play. When the resource was renamed to filename.mp4, Safari started playing the video as expected. Chrome worked fine either way.

If you change your namespace.action.GestionDocumentAction class so that when the second parameter ends in .mp4 it strips off the extension to find the correctly-named local resource, it should be able to return the video with the URL ending in .mp4 as Safari expects - www.myproject.com/namespace/documents/3/zbRdTKQKLWnA2ZiY61Gx.mp4.

Aaron D
  • 7,540
  • 3
  • 44
  • 48