2013-05-08 4 views
9

デフォルトのレール3アプリを使用してipadで再生するmp4を配信するのに問題があります。 mp4は、デスクトップ上のクロムなどのブラウザでルートを表示するときに正しく配信されます。ここでIpadにレール経由でmp4ファイルを提供する適切な方法は何ですか?

は、私たちのコードです:

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

私たちは、ビデオを見るために0.0.0.0:3000/video/test.mp4を打つとiPad上のアイコンを再生することはできませんが提示されています。さまざまなヘッダー "Content-Length"、 "Content-Range"などを修正しようとしましたが、最終結果には影響しないようです。 iPadで見たとき

我々はまた、

すなわち

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

ある程度SEND_DATAを使用して試した同じビデオは、パブリックフォルダから細かい機能します。

レールを介してMP4ファイルをIpadに送信する適切な方法は何ですか?

答えて

15

問題は、レールがmp4をストリーミングするために必要なHTTP範囲要求を処理しないことが原因と思われる。

これは、(私たちのサーバーのような薄いを使用して)、開発のための私たちのソリューションでした:

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 

上記の解決策は何よりもはるかに遅いと最終的に私たちは、本番環境で資産を提供するためにnginxのXSendfileを使用することになります私たちは必要です。

+2

コードにフェンスポストエラーがあると思います。私はlengthが 'bytes.end - bytes.begin + 1'であるべきだと信じています - もしバイトの範囲がバイト10から12であれば、それは3バイトでなければなりません。また、何らかの理由で 'send_data'を使用している場合は、必ず応答ヘッダに' Content-Length'を設定してください。 – tovodeverett

+0

このソリューションをありがとうございます! @tovodeverettコメントに基づいて修正を追加しました。開発のためにRailsの代わりにSinatraを使用して、私はsinatra/streaming contribを使ってsend_dataの振る舞いを次のように複製することができました: 'stream {| out | out.write IO.binread(ファイルパス、長さ、オフセット); out.flush} ' –

+1

解決に感謝します!私たちは、このアプローチをChromeで動作させるためには、応答ステータスを '206'に明示的に設定する必要があることに気付きました。 –

関連する問題