Use YouTube API with Ruby on Rails
I’ve got 150+ videos on @SupeRails Youtube channel, and now I want to list them on my own superails.com website.
I could copypaste the information manually, but that would take ages.
I could use web scraping, but what’s the point, if there is an easy to use Youtube API?
Youtube API is accessible in Ruby via the gem ‘google-api-client’
1. Generate a Youtube API key #
First, access Google Cloud Console. Search for YouTube Data API v3:
Click to enable the API:
Create an API key:
View Youtube API docs
2. Find a youtube channel ID #
To make the API call to list videos, you need to provide a channel ID. Here’s how you can access any channel ID:
3. API call to list all videos on a channel #
Install the gem:
# Gemfile
# gem 'google-api-client' # https://github.com/googleapis/google-api-ruby-client
gem 'google-apis-youtube_v3'
Make a list_searches
API call to get up to 50 videos per page form the selected channel.
# rails c
require 'google/apis/youtube_v3'
CHANNEL_ID = 'UCyr6ZTmztFW3FB4qG_97FoA'
YOUTUBE_KEY = 'MySecretKey'
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = YOUTUBE_KEY
# list videos and playlists
response = youtube.list_searches('snippet', channel_id: CHANNEL_ID, max_results: 50)
# list only videos
response = youtube.list_searches('snippet', channel_id: CHANNEL_ID, max_results: 5, type: 'video')
This will provide you basic information about up to 50 videos per page.
4. API call to show details of one video #
If you want to have more detailed info about a specific video, you should make a list_videos
API call while passing the video_id
.
# rails c
require 'google/apis/youtube_v3'
CHANNEL_ID = 'UCyr6ZTmztFW3FB4qG_97FoA'
YOUTUBE_KEY = 'MySecretKey'
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = YOUTUBE_KEY
video_id = "07XQY8nRvd0"
video_response = youtube.list_videos('snippet', id: video_id)
5. Import Youtube videos into a Rails app #
Genarate a Post
model, and jobs to make async API calls:
rails g model Post video_id title description:text tags:text published_at:datetime cover_image_url
rails g job Youtube::ListVideosJob
rails g job Youtube::CreateVideoJob
The API call will give us tags as an array, so let’s store them as such:
# app/models/post.rb
serialize :tags, Array
Job to LIST and Paginate all the videos on a Youtube channel:
# app/jobs/youtube/list_videos_job.rb
require 'google/apis/youtube_v3'
# Youtube::ListVideosJob.perform_later
class Youtube::ListVideosJob < ApplicationJob
queue_as :default
CHANNEL_ID = Rails.application.credentials.dig(:youtube, :channel_id)
YOUTUBE_KEY = Rails.application.credentials.dig(:youtube, :youtube_key)
def perform
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = YOUTUBE_KEY
video_ids = fetch_all_videos(youtube)
process_videos(video_ids)
end
private
def fetch_all_videos(youtube)
video_ids = []
next_page_token = nil
loop do
response = youtube.list_searches('snippet', channel_id: CHANNEL_ID, max_results: 50, page_token: next_page_token)
response_ids = response.items.map { |item| item.id.video_id }.compact
video_ids += response_ids
next_page_token = response.next_page_token
break if next_page_token.nil?
end
video_ids
end
def process_videos(video_ids)
video_ids.each do |video_id|
Youtube::CreateVideoJob.perform_later(video_id)
end
end
end
Job to get detailed info for a specific youtube video and create a local record:
# app/jobs/youtube/create_video_job.rb
require 'google/apis/youtube_v3'
# Youtube::CreateVideoJob.perform_later
class Youtube::CreateVideoJob < ApplicationJob
queue_as :default
CHANNEL_ID = Rails.application.credentials.dig(:youtube, :channel_id)
YOUTUBE_KEY = Rails.application.credentials.dig(:youtube, :youtube_key)
def perform(video_id)
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = YOUTUBE_KEY
video_response = youtube.list_videos('snippet', id: video_id)
video = video_response.items.first.snippet
video_hash = {
video_id: video_id,
title: video.title,
description: video.description,
tags: video.tags,
published_at: video.published_at,
cover_image_url: video.thumbnails.maxres.url
}
Post.find_or_create_by(video_id: video_hash[:video_id]).update(video_hash)
end
end
6. Display videos in a view: #
<% @posts.each do |post| %>
<h3><%= post.title %></h3>
<p><%= post.description %></p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/<%= post.video_id %>" frameborder="0" allowfullscreen></iframe>
<hr>
<% end %>
Example fixture of a stored video:
one:
youtube_video_id: "Ubrr9mqE94o"
title: "Ruby on Rails #27 Gem Letter Opener - best way to preview emails in development"
description: "gem letter_opener:\nhttps://github.com/ryanb/letter_opener\nSource Code for the Post:\nhttps://github.com/corsego/26-action-mailer/commit/24fb10065fb5c4502b15ea75d651aec8e61413e0\n\nTo fix Launchy error - run these commands in console:\nexport BROWSER=/dev/null\nexport LAUNCHY_DRY_RUN=true"
tags: ["ruby", "rails", "ruby on rails", "tutorial", "programming"]
published_at: "2021-05-19T13:00:15Z"
cover_image_url: "https://i.ytimg.com/vi/Ubrr9mqE94o/maxresdefault.jpg"
Did you like this article? Did it save you some time?