Ruby on rails - 将常规的Youtube"链接"转换为嵌入式视频



我的目标是:我试图允许用户在我的网站中嵌入指向Youtube视频的链接,同时让我控制播放器的设置。

我想通过仅要求用户提供链接(而不是整个嵌入代码)来做到这一点,从那里我可以以某种方式将该链接粘贴到嵌入代码中。

我尝试用一些 Youtube 链接(http://youtu.be/...)进行简单的替换,但它们不起作用,说"电影未加载"。有没有可靠的方法可以做到这一点?

我经常为客户这样做,它的要点是你从URL中解析出ID,然后使用它生成iframe的HTML。

def youtube_embed(youtube_url)
  if youtube_url[/youtu.be/([^?]*)/]
    youtube_id = $1
  else
    # Regex from # http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url/4811367#4811367
    youtube_url[/^.*((v/)|(embed/)|(watch?))??v?=?([^&?]*).*/]
    youtube_id = $5
  end
  %Q{<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/#{ youtube_id }" frameborder="0" allowfullscreen></iframe>}
end
youtube_embed('youtu.be/jJrzIdDUfT4')
# => <iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/jJrzIdDUfT4" frameborder="0" allowfullscreen></iframe>

我把它放在一个助手中。根据口味更改高度、宽度和选项。

另一个答案是使用这个处理YouTube和vimeo的宝石,并且可以扩展到更多。 它还与AR很好地集成,因此您可以缓存生成的html,而不是在每个渲染上进行过滤:

https://github.com/dejan/auto_html

我使用了关于函数的最高评分答案youtube_embed但是当我在我的视图中实现时,我看到iframe代码出现在我的页面中,但没有视频。 我在函数调用之前添加了 raw,现在页面一切都很好。

在我的视野中.html.erb

<p><%= raw(youtube_embed(@experiment.researchsection.videolink)) %></p>

像这样的东西(例如在模型中):

@@video_regexp = [ /^(?:https?://)?(?:www.)?youtube.com(?:/v/|/watch?v=)([A-Za-z0-9_-]{11})/, 
                   /^(?:https?://)?(?:www.)?youtu.be/([A-Za-z0-9_-]{11})/,
                   /^(?:https?://)?(?:www.)?youtube.com/user/[^/]+/?#(?:[^/]+/){1,4}([A-Za-z0-9_-]{11})/
                   ]
def video_id
  @@video_regexp.each { |m| return m.match(source_url)[1] unless m.nil? }
end

其中source_url是视频的完整链接。然后是助手:

def youtube_video(video_id)
  render :partial => 'youtube_video', :locals => { :id => video_id }
end

和样本部分(哈姆尔):

%iframe{:allowfullscreen => "", :frameborder => "0", :height => "349",
        :src => "http://www.youtube.com/embed/#{id}", :width => "560"}

并查看简单如下:

= youtube_video Model.video_id

这是YouTube使用的:

<iframe width="425" height="349" src="http://www.youtube.com/embed/zb-gmJVW5lw" frameborder="0" allowfullscreen></iframe>

然后只需使用正则表达式将链接从:

http://www.youtube.com/watch?v=zb-gmJVW5lw

到:

http://www.youtube.com/embed/zb-gmJVW5lw

以下是用于匹配常规 youtube 链接的概念验证正则表达式:

  • http://rubular.com/r/Fitt7PPJW1

以下是用于匹配 youtu.be 链接的概念证明正则表达式:

  • http://rubular.com/r/MTgd9nXzFA

请注意,嵌入网址也可以加载到浏览器中,这将打开一个全屏视频页面。

我不得不在我最近的一个项目中加入这个功能。我必须支持链接YouTube和Vimeo视频。我正在使用Ruby和HTTParty的"uri"模块。基本上我有以下几点:

class LinkVideo < ActiveRecord::Base
  require 'uri'
  include HTTParty
  cattr_reader :per_page
  @@per_page = 12
  belongs_to :user
  validates :weblink, :presence => true, :domain => true

  def embed(width = "640", height = "390")
    embed_code = nil
    case base_uri
      when "www.youtube.com"
        embed_code = "<object width='#{width}' height='#{height}'>" +
              "<param name='movie' value='#{url}'></param>" +
              "<param name='allowFullScreen' value='false'></param>" +
              "<param name='allowscriptaccess' value='always'></param>" +
              "<embed src='#{url}' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='false' 
                  width='#{width}' height='#{height}'> </embed>" +
            "</object>"
        when "www.vimeo.com"
          embed_code = "<iframe src='#{url}' width='#{width}' height='#{height}' frameborder='0'></iframe>"
      end
      embed_code
  end
  def url
    url = nil
    case base_uri
      when "www.youtube.com"
        url = "http://www.youtube.com/v/" + video_id + "&amp;hl=en_US&amp;fs=1"
      when "www.vimeo.com"
        url = "http://player.vimeo.com/video/" + video_id
    end
    url
  end
  def thumbnail
    url = nil
    case base_uri
      when "www.youtube.com"  
        url = "http://img.youtube.com/vi/" + video_id + "/2.jpg"
      when "www.vimeo.com"
        url = thumbnail_path( image_base_uri, video_id )
    end
    url  
  end
  # Video Paths:
  #   http://www.youtube.com/watch?v=Gqraan6sBjk
  #   http://www.vimeo.com/21618919
  # Thumbnail Paths:
  #   http://img.youtube.com/vi/Gqraan6sBjk/2.jpg
  private
    def image_base_uri
      image_base_uri = nil
      case base_uri
        when "www.youtube.com"
          image_base_uri = "http://img.youtube.com/vi/"
        when "www.vimeo.com"
          image_base_uri = "http://vimeo.com/api/v2/video/"
      end
      image_base_uri
    end
    def thumbnail_path(base_uri, videoid = nil, format = 'xml')
      path = nil
      return path if base_uri.nil?
      xml     = HTTParty.get( base_uri + ( videoid.nil? ? video_id : videoid ) + format.insert(0, '.') )
      values  = xml.parsed_response.values_at("videos").first.fetch('video')
      if values["user_portrait_medium"].include?('100')
        path  = values["user_portrait_medium"]
      else values["user_portrait_large"].include?('100')
        path = values["user_portrait_large"]
      end
      path
    end
    def base_uri
      @uri ||= parse_it
      @uri.host
    end
    def video_id
      video_id = nil
      case base_uri
        when "www.youtube.com"
          video_id = @uri.query.split('=')[1].slice(0, 11)
        when "www.vimeo.com"
          video_id = @uri.path.delete('/')
      end
      video_id
    end
    def parse_it
      @uri = URI.parse( weblink )
    end
end

您可能更喜欢推出自己的解决方案,但值得考虑嵌入式 API。 http://embed.ly/

我认为实现您要做的事情的最简单方法是:

您正在尝试从中获取:

http://www.youtube.com/watch?v=zb-gmJVW5lw

对此:

<iframe width="640" height="360" src="http://www.youtube.com/embed/zb-gmJVW5l" frameborder="0" allowfullscreen></iframe>

所以你可以简单地这样做:

#### Use a regular expression to extract the video code
@video_id = (/([w-]{11})/.match(@v_url)).to_s
#### Put this information in the right format
@embed_code = "<iframe width='640' height='360' src='http://www.youtube.com/embed/#{@video_id}' frameborder='0' allowfullscreen></iframe>"

然后在你看来,只需做:

<%= raw(@embed_code) %>

我创建了一个简单的帮助程序来嵌入YouTube视频:

# Helpers for better embedding and manipulation of videos
module VideosHelper
  # Regex to find YouTube's video ID
  YOUTUBE_REGEX = %r(^(http[s]*://)?(www.)?(youtube.com|youtu.be)/(watch?v=){0,1}([a-zA-Z0-9_-]{11}))
  # Embeds YouTube video of given URL in an iframe
  #
  # @param url [String] URL of desired video
  # @param width [String] width of embedded video. Can be any valid CSS unit
  # @param height [String] height of embedded video. Can be any valid CSS unit
  # @return [String] HTML string of embedded video
  def youtube_embed(url, width = "100%", height = "250px")
    youtube_id = find_youtube_id(url)
    result = %(<iframe title="YouTube video player" width="#{width}"
                height="#{height}" src="//www.youtube.com/embed/#{ youtube_id }"
                frameborder="0" allowfullscreen></iframe>)
    result.html_safe
  end
  # Finds YouTube's video ID from given URL or [nil] if URL is invalid
  # The video ID matches the RegEx [a-zA-Z0-9_-]{11}
  #
  # @param url [String] URL of desired video
  # @return [String] video ID of given URL
  def find_youtube_id(url)
    url = sanitize(url).to_str
    matches = YOUTUBE_REGEX.match url
    if matches
      matches[6] || matches[5]
    end
  end
end

假设您有一个文章模型,其中包含一个名为 embed 的字段(字符串):

要处理的 YouTube 示例:

https://www.youtube.com/watch?v=u75Zsl1ECPQ&list=PLu9lbDbw-S8zyBwu9_aA2nE-3QocgyzRE&index=4

https://www.youtube.com/watch?v=u75Zsl1ECPQ

https://youtu.be/u75Zsl1ECPQ

https://youtu.be/u75Zsl1ECPQ?t=12

等。。

在模型中(注意。我没有在 iframe 中应用宽度和高度,因为我将在样式表中全局处理它。此外,您可以删除该正则表达式并取消注释 self.embed.include? ..要实现相同的验证,请执行以下操作:

  #show (before_save)
  # Returns a string (html_safe) .. iframe element from the embed string field
  def iframe
    if self.embed.present?
      ### YouTube
      ## Browser link --- use array to handle most playlist links, etc
      if self.embed =~ /^(https?://)?(www.)?youtube.com/watch?v=/  # self.embed.include? 'https://www.youtube.com/watch?v='
        ("<iframe src='https://www.youtube.com/embed/#{self.embed[32..42]}' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture' allowfullscreen></iframe>").html_safe
      ## YouTube share link --- using array, because .split('https://youtu.be/').last wouldn't handle start at option ()?t=12)
      elsif self.embed =~ /^(https?://)?(www.)?youtu.be//  # self.embed.include? 'https://youtu.be/'
        ("<iframe src='https://www.youtube.com/embed/#{self.embed[17..27]}' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture' allowfullscreen></iframe>").html_safe
      ### Validate + Generate iframe for whatever other embeds you want to allow (Google Maps, Vimeo, etc)
      # elsif
      else
        self.embed = nil
      end
    end
  end

在文章#show视图中(注意..用于处理响应性的引导类):

  <% if @article.embed.present? # no markup if nil %>
    <div class="embed-responsive embed-responsive-16by9">
      <%= @article.iframe %>
    </div><!-- .embed-responsive -->
  <% end %>

如果要获取嵌入的缩略图,此方法的工作方式相同:

  #_articles (before_save)
  # Returns a string (html_safe) .. img element from the embed string field
  def thumb
    if self.embed.present?
      ### YouTube
      ## Each YouTube video has 4 generated images [ /0 .. /3 ]
      if self.embed =~ /^(https?://)?(www.)?youtube.com/watch?v=/
        ("<img alt='Media' class='card-img-top' src='https://img.youtube.com/vi/#{self.embed[32..42]}/0.jpg' />").html_safe
      elsif self.embed =~ /^(https?://)?(www.)?youtu.be//
        ("<img alt='Media' class='card-img-top' src='https://img.youtube.com/vi/#{self.embed[17..27]}/0.jpg' />").html_safe
      else
        self.embed = nil
      end
    end
  end

因此,在文章#索引视图中,您可以调用 thumb 方法:

<% if article.embed.present? %>
  <%= link_to article.thumb, article_path(article) %>
<% end %>

在每种情况下,您都将在 article.rb 模型中使用 activerecord 回调:

before_save :iframe, :thumb

最新更新