概要
- YouTubeDataAPIでは一日の上限Queries(呼び出し回数 × Cost)が制限されているため、「任意の配信者の動画一覧を取得し、その配信者が現在配信中の動画のリアルタイム情報(視聴者数など)を毎分APIを通して監視しよう」と考えるとすぐにAPI上限に達してしまう
- YouTubeが公開しているRSSフィード用のURL経由で最新動画1件のvideo_idを調べ、そのidの動画情報のみをAPIを用いて取得することで、Queries上限に達しないよう節約している
使用環境
- Rails 6.0.4.1
- YouTube Data API v3
- MariaDb Ver 15.1
データベース
配信者テーブル (streamers)
id | title | channel_code | description |
---|---|---|---|
1 | YouTubeアカウント名 | チャンネルID | チャンネル概要 |
2 | 27歳高学歴ニートさの | UCmFq0wZGLfjtXdUINyOZ7hQ | 毎日たのしく生きてたら大卒27歳職歴なしになってしまいました。 |
3 | レンジの中に毒を持て | UCfBjINK2PzS432RihFow99w | ポーカーで生きる人間の業 |
動画テーブル (streamer_videos)
id | streamer_id | title | video_code | audience |
---|---|---|---|---|
1 | 外部キー | 動画タイトル | 動画ID | 視聴者数 |
2 | 2 | 最速で慶應ロースクールに落ちました | UbHSJapfMSAM | 258 |
3 | 3 | Piosolverと配信デート | DfG32VJMZV0 | 1120 |
対応方針
以下のRSSフィード用URLを用いて最新動画の動画IDを取得することで、「任意の配信者の動画一覧を取得する」というフローのAPI実行を削減している
https://www.youtube.com/feeds/videos.xml?channel_id=チャンネルID
実装のイメージは以下です
本質的な処理だけ抽出しているので、実際のソースコードとは異なります。
youtube = Google::Apis::YoutubeV3::YouTubeService.new
youtube.key = Rails.application.credentials.google[:api_key]
Streamer.all.each do |streamer|
# YouTubeが公開しているRSSフィード用のURLは以下
feed_url = "https://www.youtube.com/feeds/videos.xml?channel_id=#{streamer.channel_code}"
xml = URI.open(feed_url)
parsed_xml = Nokogiri::HTML.parse(xml, nil, 'utf-8')
video_ids = parsed_xml.xpath('//entry/videoid').map{|v| v.text}
# データベースに保存している最新動画と、RSSフィードで取得した最新動画を突き合わせる
saved_latest = streamer.streamer_videos.order(created_at: :desc).first
if saved_latest
saved_index = video_ids.index(saved_latest.video_code)
# 最新動画がすでに保存されているアーカイブ動画である場合は無視
next if saved_index == 0 && saved_latest.uploaded?
end
# 最新1件の動画に対して、動画情報を取得するAPI実行
response = youtube.list_videos('snippet, liveStreamingDetails, contentDetails', {:id => video_ids[0]})
video = StreamerVideo.find_or_initialize_by(video_code: response.items[0])
if video.new_record?
video.streamer_id = streamer.id
video.title = r.snippet.title
video.description = r.snippet.description
end
case r.snippet.live_broadcast_content
when "live" then # ライブ配信中の動画は、ここで毎分視聴者数を取得して更新している
video.video_type = "live"
video.audience = r.live_streaming_details.concurrent_viewers.to_i
when "none" then # ライブ配信ではない動画は、ここでデータを登録して以降処理を行わない
video.video_type = "uploaded"
end
video.save!
end