Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to serve mp4 files through rails to an Ipad?

We're having trouble serving mp4s that will play on an ipad using a default rails 3 app. The mp4 is served correctly when viewing the route in chrome and other browsers on a desktop.

Here is our code:

file_path = File.join(Rails.root, 'test.mp4')
send_file(file_path, :disposition => "inline", :type => "video/mp4")

We hit 0.0.0.0:3000/video/test.mp4 to view the video and are presented with cannot play icon on the ipad. We've tried modifying various headers "Content-Length", "Content-Range", etc but they don't seem to affect the end result.

We've also tried using send_data to some extent

i.e.

File.open(file_path, "r") do |f|
    send_data f.read, :type => "video/mp4"
end 

The same video serves fine from the public folder when viewed on the Ipad.

What is the proper way to serve mp4 files through rails to an Ipad?

like image 557
Colin Wagner Avatar asked May 08 '13 21:05

Colin Wagner


1 Answers

The problem seems to be that rails doesn't handle http-range requests which ios needs for streaming mp4s.

This was our solution for development, (using thin as our server):

  if(request.headers["HTTP_RANGE"]) && Rails.env.development?

    size = File.size(file_path)
    bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
    offset = bytes.begin
    length = bytes.end - bytes.begin + 1

    response.header["Accept-Ranges"]=  "bytes"
    response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}"
    response.header["Content-Length"] = "#{length}"

    send_data IO.binread(file_path,length, offset), :type => "video/mp4", :stream => true,  :disposition => 'inline',
              :file_name => file_name

  else
    send_file(file_path, :disposition => 'inline', :stream => true, :file_name => file_name)
  end

Ultimately we will be using nginx XSendfile to serve the assets in our production environment as the above solution is much slower than what we need.

like image 94
Colin Wagner Avatar answered Oct 14 '22 15:10

Colin Wagner