Safari 没有在 Rails 应用程序中加载 HTML5 视频
Posted
技术标签:
【中文标题】Safari 没有在 Rails 应用程序中加载 HTML5 视频【英文标题】:Safari not loading HTML5 video in Rails app 【发布时间】:2016-02-18 02:20:36 【问题描述】:我有一个 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>
在 Safari 上,视频显示“正在加载...”,但从未播放,尽管它在 Chrome 和 Firefox 中按预期工作。起初我以为它可能是路径,但我尝试了绝对路径、相对路径和 Rails image_path
助手,但没有结果。
为了调试,我复制了这个 HTML5 视频标签示例,它在 Safari 中按预期播放(这里唯一的区别是源视频):
作品:外部托管的示例视频
<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>
但是,当我采用完全相同的标记并在本地托管这些相同的文件时,视频在 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>
注意事项:
Safari 控制台或 Rails 日志中没有出现错误;文件或任何内容上没有 404。 本地托管的视频可以在 Chrome 和 FF 中运行,所以我知道路径是正确的。 外部托管的视频在 Safari 中运行良好。 本地托管的视频可以在 Rails 应用程序之外的 Safari 中工作 - 我创建了一个静态页面并使用了上面的所有示例,效果很好。基于所有这些,似乎 Safari 和 Rails 的某种组合阻止了视频加载。
【问题讨论】:
也许它与内容类型有关,您可以尝试将其添加到您的mime_types.rb
Rack::Mime::MIME_TYPES.merge!( ".ogg" => "application/ogg", ".ogx" => "application/ogg", ".ogv" => "video/ogg", ".wemb" => "video/webm", ".mp4" => "video/mp4", ".m4v" => "video/mp4")
@Chris 我添加了它并重新启动了 Rails,但没有运气。根据 curl 的说法,我确实看到 MIME 类型在没有此更改的情况下已经正确。如果您从某个重要的地方获取该列表,请注意其中有一个错字:".wemb"
。我在本地测试时将其更改为".webm"
。
有趣的是,当我将应用程序部署到 Heroku 时,文件确实正确下载并开始播放。
好的,我在本地测试过,也有同样的问题。但是,当我将视频放在公共文件夹中时,它可以工作。您真的需要将视频放在资产内部吗?它可能适用于生产中的 heroku,因为你有 config.serve_static_files = false
,这意味着文件由 nginx 或 apache 提供
@Chris 我按照 Heroku 的建议在生产中使用 rails_12factor gem。据我了解,这会强制设置config.serve_static_assets = true
。如果我真的需要它成为一种资产,这很难回答。有什么东西真的需要成为资产吗?据我了解,这样做的一个好处是我获得了资产摘要,允许在资产更改时自动缓存清除。这对我来说似乎是件好事。
【参考方案1】:
我知道这个问题已经超过 5 年了,但我遇到了同样的问题并解决了它,所以我会在这里发布我的解决方案。
当您将视频文件放入资产文件夹时,它们会以一种特殊的方式提供。然后,不提供字节范围请求。这意味着 Safari 不会播放视频,因为它需要字节范围请求才能在视频中跳转并以不同的速度播放。
如果您将视频放入公用文件夹并从那里提供服务,则服务它们的是中间件,在这种情况下,范围请求会得到服务。 (轨道 5)
因此,只需将您的视频移至public
。至少这对我来说是固定的......
【讨论】:
【参考方案2】:参考链接:https://superuser.com/questions/870133/html5-video-tag-not-supported-in-safari-5-1-on-windows-7
由于 rails 中的 video_tag 在内部使用 HTML5 'video' 标签属性,而 safari 不支持 HTML5 video 标签属性。
为了让 HTML5 视频在 Windows 上通过 Safari 播放,您 需要安装 Quicktime。
我这样做了,但视频仍然无法播放。
但是,一旦我重新启动我的机器,一切都按预期进行 到!
【讨论】:
【参考方案3】:我遇到了同样的问题,发现这是您在视频中前后移动所需的字节范围。
Here's some middleware that adds support for the byte-range HTTP header:
# (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
如需进一步参考,请查看rails media file stream accept byte range request through send_data or send_file method 或this Ruby Forum post。
【讨论】:
谢谢。我调整了要点,效果很好。如前所述,这可能不是一个好的生产设置,在这种情况下我会使用X-Sendfile
之类的东西。但是,它确实允许它在开发过程中在 Safari 中工作,这正是我所需要的!以上是关于Safari 没有在 Rails 应用程序中加载 HTML5 视频的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Rails 控制台中加载 Ruby EventMachine - 没有要加载的文件
Safari不会在Apache上的Vue.js应用程序中加载预检CORS身份验证请求(XHR)
在 Heroku 和 Amazon S3 上的生产 Rails/Vue 应用程序中加载字体时出现 CORS 错误