生涯未熟

生涯未熟

プログラミングをちょこちょこと。

Ruby on RailsでのYoutube API v3を使ったアップロード

f:id:syossan:20160710220453p:plain

YoutubeAPIには動画情報を取得したり、アップロードをしたりと便利なものが色々とありますが、Google API Consoleを弄ったりと多少ハードルが高いです。

更に、Google API Clientのv0.8からv0.9へのアップデートにより大幅な変更が加えられたため、日本語での情報も既に古くなったものが多くあり、これまたハードルをあげています。 (参考:Migrating from version 0.8.x to 0.9

なので、自分の理解を整理するために今回はアップロードの方法をザザザっと書いていきます。

実装の前準備

必要なGem

実装に入る前に、Gemfileに記述しインストールすべきGemを紹介します。

# Google Library
gem 'googleauth'
gem 'google-api-client', '0.9'

googleauthGoogleアカウントを使った認証を行うためのライブラリで、 google-api-clientGoogleに紐付いた各種サービスのAPIを操作するためのライブラリです。

Youtube APIの有効化

次に、Google API ConsoleからYoutube APIを有効にしておきます。 f:id:syossan:20160710092157p:plain

入力後、 Youtube Data API v3 というAPIが表示されていると思いますのでクリックします。 そして有効化すればOKです。

OAuth 2.0 クライアント IDの作成

また、OAuth認証を行うためのクライアントIDを発行します。

先ほどの Youtube Data API v3 の画面の左部メニューの項目に 認証情報 がありますのでクリックします。 そして、 認証情報の作成 からOAuth Client IDの作成 を選択します。 あとは必要な情報を入力し、保存して下さい。

Youtubeでマイチャンネルの作成

最後に、これは忘れがちになるのですがYoutube上でマイチャンネルを作成しておいてください。 マイチャンネルを作成しておかないと、アップロードの際にエラーとなってしまいます。

やり方についてはそこまで難しくありませんので、説明は省略します。

実装

それでは実装していきます。

実装の流れとしては - googleauthでGoogleアカウントを使ったユーザーの認証を行う - google-api-clientでYoutubeAPIを操作する という流れになります。

まず、Googleアカウントを使ったユーザーの認証を行いましょう。

ユーザーの認証には大きく2つの手順があります。 - Google側の認証ページへの遷移 - リダイレクト先でアクセストークンの取得

Google側の認証ページへの遷移

基本的にはOAuth 2.0 Flow: Server-side web appsアクセス トークンを取得するの項に書いてあることをそのまま実装します。 https://accounts.google.com/o/oauth2/auth をベースに使用目的に合わせたパラメータを付加していく形になると思います。

そして、完成したURLを適当な場所にリンクとして埋め込んでください。

<%= link_to 'OAuth認証', 'https://accounts.google.com/o/oauth2/auth?client_id=[client_id]&redirect_uri=[redirect_uri]&response_type=code&scope=https://www.googleapis.com/auth/youtube.upload' %>

一旦、完成したURLを叩くとGoogleアカウントの選択画面が表示され、選択するとYoutubeの権限付与に関するページが表示されると思います。 次は、この認証が完了した後にリダイレクトされる先の処理を書いていきます。

リダイレクト先でアクセストークンの取得

次にリダイレクト先でアクセストークンの取得を行います。 リダイレクト先には code というURLパラメータがくっついていますので、この code を使いアクセストークンを取得します。

取得については本来は googleauth を使うべきなのですが、面倒なので net/http で実装しました。

def callback_auth
    uri = URI.parse 'https://accounts.google.com/o/oauth2/token'

    post_params = Hash.new
    post_params.store('code', params[:code])
    post_params.store('client_id', [client_id])
    post_params.store('client_secret', [client_secret])
    post_params.store('redirect_uri', [ここには設定されている適当なredirect_urlを入力してください])
    post_params.store('grant_type', 'authorization_code')

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE

    http.set_debug_output $stderr

    req = Net::HTTP::Post.new uri.path
    req.set_form_data(post_params)

    http.start do |h|
      response = h.request(req)
      result = JSON.parse(response.body)
      # ここにログインしているユーザーへアクセストークンを保存してあげる処理を書く
    end

    # 適当なページへ遷移
    redirect_to 〜
end

client_id , client_secret はOAuth 2.0 クライアント IDを作成した時に割り振られますので、その値を入力してください。

google-api-clientでYoutubeAPIを操作する

次に、Youtube APIを実際に動かすところを実装してみます。

  authorization = Signet::OAuth2::Client.new(
    access_token: access_token,
    expires_at: Time.current.since(1.hour)
  )

  file = params[:upload_file]ztempfile.path
  youtube = Google::Apis::YoutubeV3::YouTubeService.new
  youtube.authorization = authorization

   part = {
     snippet: {
       title: 'hoge',
       description: 'fuga',
       tags: {}
     }
  }

  response = youtube.insert_video('snippet', part, upload_source: file, content_type: 'video/*')

こんな感じになります。

本来だと有効期限が切れている場合のrefresh_tokenの取得処理などが必要ですが、面倒なので書きませんでした。 とりあえずこのコードを元に諸々検索すると捗るかも。

注意点としては、OAuth2認証ではなくサービスアカウントを使った認証を行うとYoutube APIでのアップロードは出来ないという点です。 また、Youtube APIの公式ドキュメントも google-api-client の扱いについては古いv0.8の情報しかないので注意して下さい。