[MAGNOLIA-3855] h.264 (mp4) video in a html 5 video tag does stream from docroot, but not from repository Created: 10/Oct/11  Updated: 09/Mar/20  Resolved: 10/Jan/12

Status: Closed
Project: Magnolia
Component/s: core
Affects Version/s: 4.4.5
Fix Version/s: 4.4.6

Type: Bug Priority: Major
Reporter: Tom Wespi Assignee: Jan Haderka
Resolution: Fixed Votes: 1
Labels: 5, h264, html, html5, video
Remaining Estimate: 1d
Time Spent: Not Specified
Original Estimate: 1d
Environment:

mac os x 10.6, java 6, derby, community edition


Attachments: PDF File Screen shot 2011-10-11 at 11.00.42.pdf     HTML File html5-video-test.html     File sintel-trailer.3gp     File sintel-trailer.m4v     File sintel-trailer.ogv     PNG File sintel-trailer.png     File sintel-trailer.webm    
Issue Links:
Relates
causality
caused by MGNLDMS-215 Support byte-range HTTP requests to a... Closed
is causing MGNLDMS-220 Cache request fails Closed
dependency
depends upon MAGNOLIA-4079 Serving of file types (especially vid... Closed
relation
is related to MGNLDMS-185 DMSDownloadServlet logs error message... Closed
is related to MGNLDMS-211 MimeMappings config should include ma... Closed
is related to MGNLRES-39 Chrome refuses to load FlowPlayer fro... Closed
is related to MGNLDAM-679 Broken pipe when video is loaded Closed
is related to MAGNOLIA-3882 Add support for multiple byte range s... Closed
supersession
supersedes MAGNOLIA-4146 Fix video streaming with HTML5 video tag Closed
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Date of First Response:

 Description   

when inserting a html 5 video tag with a h.264 video (mp4), the video is played when served from docroot

<video src="${contextPath}/docroot/video.mp4" width="200" height="110" controls="true">
<p>If you are reading this, it is because your browser does not support the HTML5 video element.</p>
</video>

when served from repo (website / dms), the video is not working.



 Comments   
Comment by Matt Dertinger [ 10/Oct/11 ]

I believe this issue is caused by MGNLDMS-215. There's no byte-range header in the response.

Comment by Tom Wespi [ 11/Oct/11 ]

It also not work from website repo.

And it also not working with "oldschool" quicktime embeding. it is working from docroot.

<EMBED SRC="${contextPath}/test/video.mp4" WIDTH="200" HEIGHT="110" AUTOPLAY="true" CONTROLLER="false" LOOP="false" HREF="${contextPath}/test/video.mp4" TARGET="myself" PLUGINSPAGE="http://www.apple.com/quicktime/" />

Comment by Federico Grilli [ 14/Dec/11 ]

Reopening this as it looks it does not work. Also serving from docroot appears to be broken. I used latest Safari, FF and Chrome + tomcat 6.0.26

To reproduce it:

  • upload a mp4 video to dms (one can be found here http://www.808.dk/?code-html-5-video)
  • add the following snippet to howTo.jsp
    <video src="http://localhost:8080/magnolia-empty-webapp/dms/path/to/video.mp4" width="200" height="110" controls="true"/>
    

or

  • place the video in docroot
  • add the following snippet to howTo.jsp
    <video src="http://localhost:8080/magnolia-empty-webapp/docroot/video.mp4" width="200" height="110" controls="true">
    <p>If you are reading this, it is because your browser does not support the HTML5 video element.</p>
    </video>
    

The HTML5 player shows up with a "loading..." message but no video is played. It should be added that sometimes, after multiple page reloads the video served from docroot is played. This is the error stacktrace with DMS (further down there's the stacktrace for docroot test) I get no error now, still the video served from docroot does not display, unless one first requests the video directly, i.e by entering the URL http://localhost:8080/magnolia-empty-webapp/docroot/video.mp4 :

 
2011-12-14 12:35:50,105 ERROR info.magnolia.module.dms.DMSDownloadServlet       : error during download
ClientAbortException:  java.net.SocketException: Broken pipe
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:358)
	at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434)
	at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:293)
	at org.apache.catalina.connector.OutputBuffer.writeByte(OutputBuffer.java:399)
	at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:77)
	at info.magnolia.cms.filters.RangedOutputStream.write(RangedOutputStream.java:64)
	at java.io.OutputStream.write(OutputStream.java:99)
	at info.magnolia.module.dms.DMSDownloadServlet.sendUnCompressed(DMSDownloadServlet.java:123)
	at info.magnolia.module.dms.DMSDownloadServlet.handleResourceRequest(DMSDownloadServlet.java:108)
	at info.magnolia.module.dms.DMSDownloadServlet.process(DMSDownloadServlet.java:184)
	at info.magnolia.module.dms.DMSDownloadServlet.doGet(DMSDownloadServlet.java:74)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at info.magnolia.cms.filters.ServletDispatchingFilter.doFilter(ServletDispatchingFilter.java:119)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:66)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.VirtualUriFilter.doFilter(VirtualUriFilter.java:69)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.module.cache.executor.Bypass.processCacheRequest(Bypass.java:57)
	at info.magnolia.module.cache.executor.CompositeExecutor.processCacheRequest(CompositeExecutor.java:65)
	at info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:147)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.i18n.I18nContentSupportFilter.doFilter(I18nContentSupportFilter.java:75)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.RangeSupportFilter.doFilter(RangeSupportFilter.java:86)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.security.BaseSecurityFilter.doFilter(BaseSecurityFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.LogoutFilter.doFilter(LogoutFilter.java:88)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.auth.login.LoginFilter.doFilter(LoginFilter.java:85)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CosMultipartRequestFilter.doFilter(CosMultipartRequestFilter.java:86)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContentTypeFilter.doFilter(ContentTypeFilter.java:104)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContextFilter.doFilter(ContextFilter.java:120)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:66)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:105)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:216)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:680)
Caused by: java.net.SocketException: Broken pipe
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
	at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:741)
	at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434)
	at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:349)
	at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:765)
	at org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:118)
	at org.apache.coyote.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:574)
	at org.apache.coyote.Response.doWrite(Response.java:560)
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:353)
	... 75 more

stacktrace for serving video from docroot test (seems not to occur anymore)

Dec 14, 2011 12:46:01 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
java.lang.RuntimeException: ClientAbortException:  java.net.SocketException: Broken pipe
	at info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:159)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.i18n.I18nContentSupportFilter.doFilter(I18nContentSupportFilter.java:75)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.RangeSupportFilter.doFilter(RangeSupportFilter.java:86)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.security.BaseSecurityFilter.doFilter(BaseSecurityFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.LogoutFilter.doFilter(LogoutFilter.java:88)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.auth.login.LoginFilter.doFilter(LoginFilter.java:85)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CosMultipartRequestFilter.doFilter(CosMultipartRequestFilter.java:86)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContentTypeFilter.doFilter(ContentTypeFilter.java:104)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContextFilter.doFilter(ContextFilter.java:120)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:66)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:105)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:216)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:680)
Caused by: ClientAbortException:  java.net.SocketException: Broken pipe
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:358)
	at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434)
	at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:293)
	at org.apache.catalina.connector.OutputBuffer.writeByte(OutputBuffer.java:399)
	at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:77)
	at info.magnolia.cms.filters.RangedOutputStream.write(RangedOutputStream.java:64)
	at java.io.OutputStream.write(OutputStream.java:99)
	at org.apache.catalina.servlets.DefaultServlet.copyRange(DefaultServlet.java:2107)
	at org.apache.catalina.servlets.DefaultServlet.copy(DefaultServlet.java:1847)
	at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:896)
	at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:339)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:76)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.module.samples.filters.SampleFilter.doFilter(SampleFilter.java:58)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:76)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:66)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.VirtualUriFilter.doFilter(VirtualUriFilter.java:69)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.module.cache.executor.Bypass.processCacheRequest(Bypass.java:57)
	at info.magnolia.module.cache.executor.CompositeExecutor.processCacheRequest(CompositeExecutor.java:65)
	at info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:147)
	... 45 more
Caused by: java.net.SocketException: Broken pipe
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
	at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:741)
	at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434)
	at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:349)
	at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:765)
	at org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:118)
	at org.apache.coyote.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:574)
	at org.apache.coyote.Response.doWrite(Response.java:560)
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:353)
	... 82 more

Comment by Federico Grilli [ 14/Dec/11 ]

OK, as Natascha has told me FF and Chrome do not support mp4 videos so far. Therefore this test only remains valid for Safari.

Comment by Matt Dertinger [ 14/Dec/11 ]

Hi Federico,

Regarding browser support for mp4 videos in Chrome, currently Chrome does support them. However, they may not be supporting them in future versions in favor of WebM - see HTML Video Codec Support in Chrome

I think there could be a few things happening here.

  1. The ClientAbortException exception is a Tomcat specific exception that is thrown when a browser cancels a request for a resource. This is normal browser behavior for loading videos, since the user hasn't initialized the video yet, there's no reason to download the entire file. To see what's happening:
    1. open up the Developer Tools in Chrome
    2. click on the Network tab
    3. refresh the page
    4. In the list of resources, find the video file
    5. Note that the status of the request is (cancelled) or (pending)
      Since these exceptions are thrown a lot, and tend to fill up the error logs, I provided a patch for MGNLDMS-185 to suppress these exceptions.
  2. Probably not causing this issue, but the HTML snippet you're using to test with should probably be modified a bit. Something like the following should be valid:
    <video src="http://localhost:8080/magnolia-empty-webapp/dms/path/to/video.mp4" width="200" height="110" controls="controls" preload="none" />
    

    or better yet (this one has the advantage that you can test other video formats). Note you'll need to convert your mp4 file to the WebM format, then test in Firefox:

    <video width="200" height="110" controls="controls" preload="none">
      <source src="http://localhost:8080/magnolia-empty-webapp/dms/path/to/video.mp4" type="video/mp4" />
      <source src="http://localhost:8080/magnolia-empty-webapp/dms/path/to/video.webm" type="video/webm" />
    </video>
    
    
  3. A reason for the video just displaying the loading message and not playing could be that other Filters are affecting the response headers and negating the byte-range header. You'll want to make sure that the video formats are excluded from the GZIP filter and Content-Disposition, see MGNLDMS-211 regarding adding the video formats to the rejected contentType node in the DMS modules configuration.
  4. Next thing to try is running the following command from Terminal:
    $ curl --range 0-99 http://localhost:8080/magnolia-empty-webapp/dms/path/to/video.mp4 -o /dev/null
    
    

    You should get a print out of the number of bytes downloaded, this should be 100. The print out should look something like this:

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0   100    0   100    0     0  19182      0 --:--:-- --:--:-- --:--:-- 50000
    
    

I hope this helps. I'll be on the Magnolia IRC today if you or anyone else wants to chat about this.

Cheers,
Matt

Comment by Federico Grilli [ 14/Dec/11 ]

Hi Matt,

thanks a lot for your help. I've just tried what you suggest: I added the preload=none and the type attributes but to no avail. The status pending for the video request shows up and I actually find it suspicious that the resource type is shown as undefined.
I disabled the gzip filter altogether and eventually I also tried

curl -u superuser:superuser --range 0-99 http://localhost:8080/magnolia-empty-webapp/dms/demo-docs/video/gizmo.mp4 -o /dev/null

and got this.

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0   100    0   100    0     0   1348      0 --:--:-- --:--:-- --:--:--  1492

Same thing happens with the video served from docroot

curl -u superuser:superuser --range 0-99http://localhost:8080/magnolia-empty-webapp/docroot/gizmo.mp4 -o /dev/null

The only difference is that when serving from dms I get the above stacktrace which I don't in the docroot case. I think I'll stop here and let the implementor look further into this issue

Comment by Matt Dertinger [ 14/Dec/11 ]

Hi Federico,

Yeah, the resource type will show as undefined until you click to play the video, at which time Chrome will make another request for the video. At that time you should see the resource type is video/mp4 and the status is {{206
Partial Content}}.

If the curl test worked, then that's a very good sign. Suppressing the ClientAbortException in the DMSDownloadServlet or similar should be enough.

Should we relate this issue to MGNLDMS-185?

Cheers,
Matt

Comment by Matt Dertinger [ 14/Dec/11 ]

Adding video mime-types to the list of rejected contentTypes under the dms modules contentDisposition should fix the video not playing problem. See MGNLDMS-211.

Comment by Matt Dertinger [ 14/Dec/11 ]

Added link to MGNLDMS-185 to suppress the ClientAbortException as seen by Federico.

Comment by Federico Grilli [ 15/Dec/11 ]

OK, to sum everything up:

I tested with

  • magnolia-empty-webapp 4.4.6-SNAPSHOT served by eclipse
  • tomcat 6.0.26
  • samples's howTo.jsp page with following snippets
<video src="http://localhost:8080/magnolia-empty-webapp/docroot/gizmo.mp4" preload="none" width="200" height="110" controls="true" />

and

<video src="http://localhost:8080/magnolia-empty-webapp/dms/demo-docs/video/gizmo.mp4"  type="video/mp4" width="200" height="110" controls="true" preload="none"/> 

Results:

  • video/mp4 should be definitely added to /config/dms/config/contentDisposition/contentType/rejected. This will prevent videos served from dms from being downloaded and instead played in the browser (when requested directly by typing their url in the browser)
  • Safari (latest): weird behavior. Video (both from docroot and dms) does not play immediately after pressing the play button, rather only after several minutes (about 20 or so). Only plays after having requested the video directly via browser's URL (likely served from browser's cache).
  • Chrome (latest): have not seen the video play yet.

Thanks again to Matt for his kind help in trying to sort this out.

Comment by Federico Grilli [ 15/Dec/11 ]

One last piece of information: I noticed I had a js error in the Safari console: javascript.js returned 500 error due to a null stream for /mgnl-resources/js-classes/mgnl/workflow/Inbox.js. The server side error was somehow hidden and I could see it only when requesting the javascript.js file directly. Here it is

java.lang.NullPointerException
	java.io.Reader.<init>(Reader.java:61)
	java.io.InputStreamReader.<init>(InputStreamReader.java:55)
	org.apache.commons.io.IOUtils.copy(IOUtils.java:1049)
	org.apache.commons.io.IOUtils.toString(IOUtils.java:359)
	info.magnolia.module.admininterface.pages.JavascriptIncludePage.renderHtml(JavascriptIncludePage.java:133)

I thought it could have something to do with the issue but I managed to temporarily fix the NPE and still the video can not be played.

Comment by Matt Dertinger [ 19/Dec/11 ]

Hi,

Just wanted to add some more info I came across while debugging.

Currently, when clicking play for the video while serving the video from /docroot, two requests for gizmo.mp4 are made (see attached screenshot screenshot-chrome-network-tab-magnolia-docroot.png). Both of the requests do not include any response information. When requesting the video from Apache 2.2 or Tomcat 7.0.22, only one request is made.

I tested the same video served directly from an Apache 2.2 instance I have configured to serve video files with the byte-range header. Additionally, I tested the video served directly from Tomcat 7.0.22 (outside of Magnolia) using the default Tomcat configuration. The results of these tests are shown in the tables below.

Request Headers for gizmo.mp4

Request Header Apache 2.2 Tomcat 7 Tomcat 7 via Magnolia
Accept / / /
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.3 ISO-8859-1,utf-8;q=0.7,*;q=0.3 ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding identity;q=1, *;q=0 identity;q=1, *;q=0 identity;q=1, *;q=0
Accept-Language en-US,en;q=0.8 en-US,en;q=0.8 en-US,en;q=0.8
Connection keep-alive keep-alive keep-alive
Host localhost:84 localhost:8080 localhost:8080
Range bytes=0- bytes=0- bytes=0-
Referer http://localhost:84/html5-video-test.html http://localhost:8080/html5-video-test.html http://localhost:8080/magnolia-empty-webapp/docroot/html5-video-test.html
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7

Response Headers for gizmo.mp4

Response Header Apache 2.2 Tomcat 7 Tomcat 7 via Magnolia
Accept-Ranges bytes bytes bytes
Cache-Control Not-Present Not-Present max-age=600, public
Connection Keep-Alive Not-Present Not-Present
Content-Length 383631 383631 2147483647
Content-Range bytes 0-383630/383631 bytes 0-383630/383631 bytes 0-2147483646/2147483647 bytes 0-383630/383631
Content-Type video/mp4 video/mp4 video/mp4;charset=UTF-8
Date Mon, 19 Dec 2011 16:09:20 GMT Mon, 19 Dec 2011 16:11:45 GMT Mon, 19 Dec 2011 20:28:33 GMT
ETag "b6ce742-5da8f-4b42262d72fc0" W/"383631-1323959687000" gizmo.mp4_2147483647_-1
Expires Not-Present Not-Present Mon, 19 Dec 2011 20:38:33 GMT
Keep-Alive timeout=5, max=100 Not-Present Not-Present
Last-Modified Thu, 15 Dec 2011 14:34:47 GMT Thu, 15 Dec 2011 14:34:47 GMT Thu, 15 Dec 2011 14:34:47 GMT
Pragma Not-Present Not-Present
Server Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/1.0.0d DAV/2 PHP/5.3.6 Apache-Coyote/1.1 Apache-Coyote/1.1

Based on the above comparisions, it looks like some potential problems may be coming from the Content-Length, Content-Range and possibly the ETag response headers.

I have yet to figure out why the Content-Length is getting set to 2147483646 instead of the expected 383631. Any insights?

In addition to these findings, I came across the following article regarding the ETag Response Header and Byte-Range requests: http://en.wikipedia.org/wiki/HTTP_ETag

Strong and weak validation

The ETag mechanism supports both strong validation and weak validation. They are distinguished by the presence of an initial "W/" in the ETag identifier, as:

"123456789"   -- A strong ETag validator
W/"123456789"  -- A weak ETag validator

Two strongly validating ETags that match effectively make a claim that the resource content is byte-for-byte identical, as well as all other entity fields (such as Content-Language) also being unchanged. Strong ETags permit the caching and reassembly of partial responses, as with byte-range requests.

Weakly validating ETags that match only make a claim that the resources at the URL are semantically equivalent; meaning that for practical purposes they are interchangeable and that cached copies can be used. However the resources are not necessarily byte-for-byte identical, and thus weak ETags are not suitable for byte-range requests. Weak ETags may be useful for cases in which strong ETags are impractical for a web server to generate, such as with dynamically-generated content.

Based on this excerpt, I'm thinking we may want to use a strong ETag validator for resources that will be served for byte-range requests.

I hope the following information helps.

Cheers,
Matt

Comment by Jan Haderka [ 20/Dec/11 ]

Hi Matt,
I'll look into the size issue. Either way, it seems that range filter needs to be amended to check for the range header in the response before adding it to prevent bytes 0-2147483646/2147483647 bytes 0-383630/383631 in the response in case underlying code is taking care of ranged requests itself. Up until now range filter made an assumption nobody except it takes care (my bad).

Comment by Jan Haderka [ 20/Dec/11 ]

BTW I'm not able to reproduce failure reported by Federico when using video tag and serving content from ftl page ... it just works (Safari/Snow Leopard). Will try with other browsers and possibly other OS as well.

Comment by Matt Dertinger [ 21/Dec/11 ]

Hi Jan,

I'm attaching some video files, a poster image, and a simple html page you can use for testing.

Files attached:

  • html5-video-test.html - A simple HTML5 page with the multiple video source elements.
  • sintel-trailer.png - A poster image for the video element.
  • sintel-trailer.m4v - Supported by IE9, Safari, Chrome (future versions of Chrome will not support this format), iOS
  • sintel-trailer.webm - Supported by Chrome and Firefox 3.6+
  • sintel-trailer.ogv - Supported by Firefox, Chrome, Opera
  • sintel-trailer.3gp - Supported by mobile devices, used by iOS over cellular networks

For further information regarding what browsers support what video formats, you can have a look at the following compatibility tables:

Please let me know if you have any questions.

Cheers,
Matt

Comment by Jan Haderka [ 23/Dec/11 ]

Hi Matt,
I've noticed that the attached test case doesn't work even on plain tomcat w/o passing through MAgnolia filter chain. Is that correct? Is Tomcat itself not able to handle such requests?

Comment by Jan Haderka [ 23/Dec/11 ]

Did some more debugging with my original test case:

add 1)
  <div><video src="/magnoliaAuthor/docroot/test.mp4" preload="none" width="200" height="110" controls="true"/></div>
add 2)
  <div><video src="/magnoliaAuthor/dms/test/test.mp4" preload="none" width="200" height="110" controls="true"/></div>
add 3)
  <div><video width="200" height="110" controls="controls" preload="none">
    <source src="/magnoliaAuthor/docroot/test.mp4" type="video/mp4" />
    <source src="/magnoliaAuthor/docroot/test.webm" type="video/webm" />
  </video></div>
add 4)
  <div><video width="200" height="110" controls="controls" preload="none">
    <source src="/magnoliaAuthor/dms/test/test.mp4" type="video/mp4" />
    <source src="/magnoliaAuthor/dms/test/test.webm" type="video/webm" />
  </video></div>

and figured that when we report wrong size of the document, <video> tag would keep requesting next range in the loop forever (always taking 16K of content that was already streamed, plus something extra). This is different from quicktime that would just stop requesting more data after it doesn't get what it expected.

For anyone interested the "chat" between server and browser/video_tag looks like:

==> GET /test.mp4 range=0-1
<== 206, len 2, ETAG
==> GET /test.mp4 range=0-<END>
<== 206, len <END+1>, ETAG
==> GET /test.mp4 range=0-1, if-none-match=ETAG
<== 304, len 0, ETAG
==> GET /test.mp4 range=<CHUNK>-<END>
<== 206, len <END>-<CHUNK>+1, ETAG
Comment by Matt Dertinger [ 23/Dec/11 ]

Hi Jan,

Regarding:

I've noticed that the attached test case doesn't work even on plain tomcat w/o passing through MAgnolia filter chain. Is that correct? Is Tomcat itself not able to handle such requests?

AFAIK, it depends on what version of Tomcat your using. The test case attached should still play on desktop browsers, albiet with some wrong header information (i.e. both Tomcat 6 and 7 send a weak ETag validator - which isn't suitable for byte-range requests - see my comment above). Tomcat 6 also doesn't set the content-type header to for these files, so it will send them as application/octet-stream. Tomcat 7 (at least with 7.0.22 does set the content-type header with the proper mime-type.

I just did another test with Tomcat 6.0.32, I got the following for the response headers:

sintel-trailer.m4v response directly from Tomcat 6.0.32
Accept-Ranges:bytes
Content-Length:10291616
Content-Range:bytes 0-10291615/10291616
Date:Fri, 23 Dec 2011 18:41:34 GMT
ETag:W/"10291616-1324497954000"
Last-Modified:Wed, 21 Dec 2011 20:05:54 GMT
Server:Apache-Coyote/1.1

Can you give me some more info about what's not working for you with the test case I attached? Are the videos playing for you when you click play? What version of Tomcat are you testing with?

Thanks,
Matt

Comment by Matt Dertinger [ 23/Dec/11 ]

Hi Jan,

I've found this article about the weak ETag header and Tomcat, there's an example of how to set it to use a strong ETag.

Tomcat, Weak ETags, and JavaScript/CSS Caching

I've also been looking at Tomcat's DefaultServlet to see how they are handling the byte-range requests/responses. If you'd like to take a look, here's the link to the source code: Tomcat's DefaultServlet.java

Some things I noticed are that they're using long datatypes instead of int datatypes for the range start, end and length properties. They also seem to be setting the default values of these properties to 0. This is different in RangeSupportFilter, for example, the length property is initially set to Integer.MAX_VALUE which translates to 2147483647, which is the value that is used in the Content-Length and Content-Range response headers.

Cheers,
Matt

Comment by Matt Dertinger [ 24/Dec/11 ]

Hi again Jan,

Ok, I think I made a little more progress.

One thing I did was format the ETag string so that it's a quoted-string. Apparently, according to RFC 2616 the ETag value must be a quoted string.

Code change was on line: 306 of RangeOutputFilter.java

RangeOutputFilter.java (svn head)
eTag = fileName + "_" + length + "_" + lastModTime;
RangeOutputFilter.java (mine)
eTag = String.format("\"%1$s-%2$s\"", length, lastModTime);

Note: for my test I didn't include the fileName in the ETag value.

The double byte-range values seem to be coming from something related to the Cache filter. Under Configuration -> modules -> cache -> config -> configurations -> default -> browserCachePolicy -> policies -> dontCachePages -> voters -> contentType -> allowed, I added a new node data called mp4 with a value of video/mp4 to exclude mp4 files from cache. Then I went to my browser, cleared it's cache, then requested html5-video-test.html from docroot, then clicked the play button. The video played. However, as you can see from the following response headers, there's no longer any Content-Range.

Here are the Response Headers I'm getting now:

sintel-trailer.m4v Response Headers Tomcat 7.0.22 via Magnolia (browser-cache disabled for video/mp4)
Accept-Ranges:bytes
Cache-Control:no-cache, no-store, must-revalidate, max-age=0
Content-Length:10291616
Content-Type:video/mp4;charset=UTF-8
Date:Fri, 23 Dec 2011 22:22:31 GMT
ETag:W/"10291616-1324497954000"
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Last-Modified:Wed, 21 Dec 2011 20:05:54 GMT
Pragma:no-cache
Server:Apache-Coyote/1.1

I hope this helps.

Cheers,
Matt

Comment by Natascha Desmarais [ 02/Jan/12 ]

Hello everyone

Just wanted to add the various tests and results that we have conducted for the video problem in Chrome for STK. They might not all be relevant for your cause, but some might prevent you from having to repeat what we did or even verify some. Just as a quick summary: html 5 video player (flowplayer) does not run in Chrome when serving everything in Magnolia. FF works and Safari uses its own built-in html5 player which also works. No errors/further info in the magnolia log or any kind of JS errors.

  • Alexander Farkas from Aperto mentioned that the attached charset in the Content-Type field of the response might be causing a problem. We commented out the corresponding line in info.magnolia.cms.filters.ContentTypeFilter and made sure it was not set on the response anymore but this didn't solve the Chrome problem.
  • He also said that if the SWF is gzipped, it could pose a problem. It appeared that SWFs are generally not gzipped by default but just to be on the safe side we disabled gzip completely, but still no luck.
  • We upgraded to JQuery 1.7.1 (from 1.6.4) core - no luck.

Behold for very weird behavior is upcoming:

  • We referenced a video file that was being served through Magnolia from within the static prototype somewhere on our machine (src="http://localhost:8080/..../somefile.mov") and it played in Chrome!
  • That being very curious already, we even went further and tried to find out if the aggregated javascripts might be a problem. So we took the output of all aggregated JS (libs & plugins) from Magnolia, saved them into local files and referenced those in the static prototype. Again, the video worked within Chrome.

Just as an info, we always used a .mov file for our tests.

Comment by Natascha Desmarais [ 04/Jan/12 ]

Comment moved to more appropriate and separate issue MGNLRES-39

Comment by Jan Haderka [ 04/Jan/12 ]

So your issue is actually - "Chrome refuses to load flowplayer.js from resources workspace in onDomReady event" - likely due to the fact that content-length is incorrectly set to zero. Can you log it as separate issue from this one and just link the issues? ... pbly also copy/move the last comment to this new ticket. Thx.

Comment by Jan Haderka [ 05/Jan/12 ]

OMG, just realized when downloading attached m4v Safari adds the mp4 extension to the file. Once I fixed that the test works from the docroot and fails from DMS as expected. Hopefully I'll be able to proceed much faster now.

Comment by Jan Haderka [ 10/Jan/12 ]

Finally, last bit of the puzzle - some browsers are picky about the response status (that is not included in your table above). While mobile Safari doesn't really care, the OSX version of Safari/FF/Chrome really does ... in some cases we were returning 200 instead of 206 (partial response) and desktop versions of browsers didn't like that (even tho requested range spanned the whole file).

Comment by Matt Dertinger [ 10/Jan/12 ]

Jan,

Very good news. Sorry for not including the status code info in my comment.

Cheers,
Matt

Comment by Jan Haderka [ 10/Jan/12 ]

Fix will be included in 4.4.6 (w/ DMS 1.5.3) and in upcoming 4.5-b4. Thanks again for very comprehensive test case and all the research.

Generated at Mon Feb 12 03:50:19 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.