Serving media files to iPad/iPhone on Domino part 2

Finally, after almost 2 months I finally have time to blog a bit again. This blog will be the second part in a 2 part series about how to serve files for iPad / iPhone devices on a domino server.

Back in part 1 I talked about an xpage application I was developing where the customer wanted to serve video streams to mobile devices. After a couple of days development I got a nice little application running where video’s could be uploaded and watched on all major browsers. The site used the video tag from HTML5 to serve the video files to the browser which accepted this tag. As said in Part 1 mobile safari uses the byte range header to retrieve the first few bytes of a stream to see which type of file is being streamed. By default, as far as I know, the domino server does not understand this header so we have to build this ourselves.

The first step in building this functionality is to create a simple custom control. The custom control contains the following lines of code:

As you can see nothing to fancy, an xp:text box which generates the correct html for the video tag. In the afterPageLoad I generate the correct url for for the video to be played. As you already notice I’m using an xPage as the url for the video tag src attribute. Lets see what happens on the this videoTest page?

The VideoRangeUtil.renderResponse method is called with the current facescontext, the id of the document and the filename we want to retrieve. The renderReponse method looks like this. I have added comments on important places. This code was not completely written by me but was inspired by code from balusC.

Just be aware that this code is not perfect and can be optimized here and there.

 

Serving media files to iPad/iPhone on Domino part 1

 

“We want a video library application” they said

“No problem, can be done” I said

“Bad iPad” I screamed!

the lines above are a  little summary of what happened the last few days. At the office  I’m building  a web application which is used to serve Video files. Everything worked fine except for iPhone and iPad devices. I needed to get it working. At first I thought it was a simple encoding issue. So I grabbed my MediaInfo installation, checked the codec information on the mp4 file(s) and spotted that the wrong baseline was used. It was 4 and according to the official apple sources the baseline level needs to be 3.0 (source). So I re-encoded the file and uploaded the new version. I fired up the iPad and noted that the file still didn’t work. Ah! Maybe it was browser caching . So I renamed the file, uploaded it and again.. nothing. On all devices/browser it worked (ie 9, firefox, chrome, safari on windows, my android phone..) except for the freaking iPad!

So being out of options the only thing I could do was head over to stackoverflow and ask my question there. And so I did. Here I present to you a possible solution:

The server needs to support byte-range requests for the mobile Safari ( which is installed on iOs devices ) to be able to play video files using HTML 5.  Byte-range requests? What are byte-range requests I here you think. Actually its fairly easy to explain.

A byte range request is actually nothing more then sending only a little part of the complete file to the client (more). To be able to support this feature a server must react on the range request header and send the Accept-Ranges header accordingly. Because I didn’t know of this requirement I was really puzzled to why the file played correctly on my local Apache install and not on my domino server. To make it even more exciting I tested the following situations

Description Result
File resource Correct
File resource in domino/html Correct
File attachment on document Fail!

As you can see for some reason when serving attachments to the browser the correct headers are not send to the browser. I tried to add them by website rules but of course this failed. Since the system needs to support it as well. So I checked back my question on Stackoverflow to see if there where new additions. And Sven added a little code resource to his answer which actually does exactly that what I wanted.

The code example uses a servlet to serve the file using the range headers if it was requested or the full file if not. I’ve adapted the code and changed it a bit so it is usable for the domino server ( see part 2 for the full code example and explanation ). When you call the code in a beforerenderresponse event with the following line

it will serve the correct file with byte-range support! How cool is that!

In the next Part I will explain to you which code I used and will show you what I changed to get it working for Domino/XPages