Safari未在Rails应用中加载HTML5视频

sea*_*ter 10 safari video ruby-on-rails html5-video

我有一个Rails应用程序我正在尝试使用以下标记播放HTML5视频:

不起作用:

<video controls poster="http://lvh.me:3000/assets/videos/myvideo.png">
  <source src="http://lvh.me:3000/assets/images/videos/myvideo.mp4" type="video/mp4">
  <source src="http://lvh.me:3000/assets/images/videos/myvideo.webm" type="video/webm">
  <source src="http://lvh.me:3000/assets/images/videos/myvideo.ogv" type="video/ogg">
</video>
Run Code Online (Sandbox Code Playgroud)

在Safari上,该视频显示"正在加载..."但从未播放,尽管它​​在Chrome和Firefox中的效果与预期一致.我认为它最初可能是路径,但我尝试过绝对路径,相对路径和Rails image_path助手,没有结果.

为了调试,我复制了这个示例HTML5视频标签,它按照预期在Safari中播放(这里唯一的区别是源视频):

Works:外部托管的示例视频

<video controls poster="http://easyhtml5video.com/assets/video/Penguins_of_Madagascar.jpg">
  <source src="http://easyhtml5video.com/assets/video/new/Penguins_of_Madagascar.mp4" type="video/mp4">
  <source src="http://easyhtml5video.com/assets/video/new/Penguins_of_Madagascar.webm" type="video/webm">
  <source src="http://easyhtml5video.com/assets/video/new/Penguins_of_Madagascar.ogv" type="video/ogg">
</video>
Run Code Online (Sandbox Code Playgroud)

但是,当我采用这个完全相同的标记并在本地托管这些相同的文件时,视频在Safari中停止工作:

不起作用:本地托管的示例视频

<video controls poster="http://lvh.me:3000/assets/videos/Penguins_of_Madagascar.jpg">
  <source src="http://lvh.me:3000/assets/videos/new/Penguins_of_Madagascar.mp4" type="video/mp4">
  <source src="http://lvh.me:3000/assets/videos/new/Penguins_of_Madagascar.webm" type="video/webm">
  <source src="http://lvh.me:3000/assets/videos/new/Penguins_of_Madagascar.ogv" type="video/ogg">
</video>
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我没有在Safari控制台或Rails日志中收到错误; 没有404s文件或任何东西.
  • 本地托管的视频可在Chrome和FF中使用,因此我知道路径是正确的.
  • 外部托管的视频在Safari中运行良好.
  • 本地托管的视频在Rails应用程序之外的Safari中工作 - 我创建了一个静态页面并使用上面的所有示例产生了良好的效果.

基于所有这些,似乎Safari和Rails的某些组合阻止了视频的加载.

dev*_*and 5

我遇到了同样的问题,并发现这是在视频中前后移动所需的字节范围。

下面是一些增加对字节范围 HTTP 标头支持的中间件

# (c) Thomas Fritzsche
# This is prove-of-concept coding only
# iOS devices insist on support for byte-rage http header, that is not native
# supported by rack apps like dragonfly
# this rack middleware will evaluate the http header and provide byte range support.

# For a dragonfly Rails (3.2.3) app I have tested this will call like this.
# I reload Rack::Cache that case trouble when initialized by Rails.
# This small trick makes it working :-)
#-----------------------
#require 'dragonfly/rails/images'
#require "range"
#
#
#Rails.application.middleware.delete(Rack::Cache)
#Rails.application.middleware.insert 0, Rack::Cache, {
#  :verbose     => true,
#  :metastore   => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"), 
#  :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
#}
#
#Rails.application.middleware.insert_before Rack::Cache, RangeFilter
#
# [...]
#-------------------


class RangeFilter
  def initialize(app)
    @app = app
  end

  def call(env)
    dup._call(env)
  end   

  def _call(env)
    @status, @headers, @response = @app.call(env)    
    range = env["HTTP_RANGE"]
    if @status == 200 and range and /\Abytes=(\d*)-(\d*)\z/ =~ range
      @first_byte, @last_byte = $1, $2


      @data = "".encode("BINARY")
      @response.each do |s|
        @data << s
      end             
      @length = @data.bytesize if @length.nil? 
      if @last_byte.empty?
        @last_byte = @length - 1
      else
        @last_byte = @last_byte.to_i
      end
      if @first_byte.empty?
        @first_byte = @length - @last_byte
        @last_byte = @length - 1
      else
        @first_byte = @first_byte.to_i
      end    
      @range_length = @last_byte - @first_byte + 1
      @headers["Content-Range"] = "bytes #{@first_byte}-#{@last_byte}/#{@length}"
      @headers["Content-Length"] = @range_length.to_s
      [@status, @headers, self]
    else     
      [@status, @headers, @response]
    end  
  end

  def each(&block)
    block.call(@data[@first_byte..@last_byte])
    @response.close if @response.respond_to?(:close)
  end   

end
Run Code Online (Sandbox Code Playgroud)

如需进一步参考,请查看rails 媒体文件流通过 send_data 或 send_file 方法此 Ruby 论坛帖子接受字节范围请求