ビデオをストリーミングするには、一部のブラウザで要求されたバイト範囲を処理する必要があります。
解決策1:send_file_with_range
宝石を使用する
簡単な方法は、 send_file_with_rangegemsend_file
によってメソッドにパッチを適用することです。
Gemfileにgemを含めます
# Gemfile
gem 'send_file_with_range'
range: true
次のオプションを提供しsend_file
ます。
def show
video = Video.find(params[:id])
send_file video.full_path, type: "video/mp4",
disposition: "inline", range: true
end
パッチは非常に短く、一見の価値があります。しかし、残念ながら、Rails4.2では機能しませんでした。
send_file
解決策2:手動でパッチを適用する
宝石に触発されて、コントローラーを手動で拡張するのはかなり簡単です。
class VideosController < ApplicationController
def show
video = Video.find(params[:id])
send_file video.full_path, type: "video/mp4",
disposition: "inline", range: true
end
private
def send_file(path, options = {})
if options[:range]
send_file_with_range(path, options)
else
super(path, options)
end
end
def send_file_with_range(path, options = {})
if File.exist?(path)
size = File.size(path)
if !request.headers["Range"]
status_code = 200 # 200 OK
offset = 0
length = File.size(path)
else
status_code = 206 # 206 Partial Content
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
offset = bytes.begin
length = bytes.end - bytes.begin
end
response.header["Accept-Ranges"] = "bytes"
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
send_data IO.binread(path, length, offset), options
else
raise ActionController::MissingFile, "Cannot read file #{path}."
end
end
end
参考文献
stream: true
最初はとの違いがわからなかったので、range: true
このrailscastが役に立ちました。
http://railscasts.com/episodes/266-http-streaming