2013-05-08 9 views
9

Mamy problemy z obsługą mp4, które będą odtwarzane na iPadzie przy użyciu domyślnej aplikacji rails 3. Mp4 wyświetla się poprawnie podczas przeglądania trasy w chrome i innych przeglądarkach na pulpicie.Jaki jest właściwy sposób udostępniania plików MP4 przez szyny na Ipad?

Oto nasz kod:

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

Trafiliśmy 0.0.0.0:3000/video/test.mp4 aby obejrzeć film i są przedstawiane z nie może grać ikonę na iPada. Próbowaliśmy zmodyfikować różne nagłówki "Content-Length", "Content-Range", itp., Ale nie wpływają one na końcowy efekt.

Mamy również spróbował wykorzystać send_data do pewnego stopnia

tj

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

ten sam film służy dobrze z folderu publicznego, gdy patrzy się na iPadzie.

Jaki jest właściwy sposób udostępniania plików MP4 przez szyny do iPada?

Odpowiedz

15

Problem polega na tym, że szyny nie obsługują żądań o zakresie http, które ios potrzebuje do strumieniowania MP4.

To był nasz rozwiązaniem dla rozwoju, (za pomocą cienkich jak nasz serwer):

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 

Docelowo będziemy używać nginx XSendfile służyć aktywa w naszym środowisku produkcyjnym jak powyżej rozwiązania jest znacznie wolniejszy niż co potrzebujemy.

+2

Myślę, że w kodzie występuje błąd bariery. Wierzę, że długość powinna wynosić "bajtów.end - bajtów.begin + 1" - jeśli zakres bajtów jest od bajtu od 10 do 12, powinno to być 3 bajty. Ponadto, jeśli używasz 'send_data' z jakiegoś powodu, upewnij się, że ustawiłeś' Content-Length' w nagłówkach odpowiedzi. – tovodeverett

+0

Dziękuję za to rozwiązanie! Dodałem poprawki oparte na komentarzu @tovodeverett. Używając Sinatry (zamiast Railsów) do programowania, udało mi się replikować zachowanie send_data za pomocą sinatra/streaming contrib w następujący sposób: 'stream {| out | out.write IO.binread (ścieżka pliku, długość, przesunięcie); out.flush} ' –

+1

Dzięki za rozwiązanie! Zauważyliśmy, że aby to podejście działało w Chrome, trzeba jawnie ustawić status odpowiedzi na "206". –

Powiązane problemy