5

アップロードされたビデオを保護してプライベートフォルダーに入れるRailsアプリがあります。

今、私はこれらのビデオを再生する必要があります、そして私がコントローラーでこのようなことをするとき:

  def show
    video = Video.find(params[:id])
    send_file(video.full_path, type: "video/mp4", disposition: "inline")
  end

そして、/ videos /:idでブラウザ(ChromeまたはFF)を開きます。ブラウザはビデオを再生しません。

同じビデオをパブリックフォルダに置き、/video.mp4のようにアクセスすると再生されます。

ディスポジションを削除すると、「インライン」でビデオがダウンロードされ、コンピューターから再生できます。同じことがwebmビデオでも起こります。

私は何が欠けていますか?これは可能ですか?

4

1 に答える 1

6

ビデオをストリーミングするには、一部のブラウザで要求されたバイト範囲を処理する必要があります。

解決策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

于 2016-06-01T13:28:48.247 に答える