🎥

LINEからの動画をGASでバイナリデータから直接YouTubeへアップロード

2023/02/22に公開

デカい学びになったのでメモて程度に。
こんにちは。マグロです。

前にPythonでLINEの動画オウム返しBotを作成していましたが、今回はGASを利用してオウム返しします。

https://zenn.dev/maguro_alterna/articles/00083367dd0184

経緯

前回上げた画像オウム返しBotは、バイナリデータを直接アップロードすることでオウム返しを実現しました。

https://zenn.dev/maguro_alterna/articles/21706a293a8eeb

この時はバイナリデータからはすげーなーって思ってたのですが、リファレンス内のmultipart/form-dataの形式が気になったので調べることにしました。
何でも複数のデータを扱えるHTMLフォームの形式らしく、ファイルはバイナリデータで送られてくるとのこと。
なるほど、これを想定しているからバイナリデータを扱えるのか。

ん?じゃあ他のアップロードサービスはどうなんだろう??
例えば、YouTubeとかは、、、、?

https://developers.google.com/youtube/v3/docs/videos/insert?hl=ja

利用可能なメディアの MIME タイプ: video/*、application/octet-stream

お、バイナリデータから直接アップロードできるっぽい。
サンプルコードはPythonやJavaなどから動画ファイルをアップロードしていますが、見た感じバイナリデータには変えてそうです。

確かGASでもYouTube Data APIを使えたはずなので、これは行けるのでは??

設計

Google Apps Scriptを使用します。
GASでLINEBotを動かす説明は省略します。
また、LINE以外のAPIの申請は特に必要ありません。

https://developers.line.biz/ja/reference/messaging-api/#get-content

送られてきたバイナリデータを取得する際、messageIdをURLに含めてリクエストして取得します。

GET https://api-data.line.me/v2/bot/message/{messageId}/content

取得した動画バイナリをYouTube.Videos.insertでアップロードします。

レスポンスとして、下記リンクのようなjsonが返ってきます。

https://developers.google.com/youtube/v3/docs/videos?hl=ja#resource

ここの動画idをURLに当てはめ、動画リンクをLINEに返信します。

コーディング

main.gs
//LINEBotのトークン
const LINE_CHANNEL_ACCESS_TOKEN = ""
function doPost(e) {
  try{
    // LINEBotから送信されたメッセージを取得
    const message = JSON.parse(e.postData.contents).events[0].message;

    // LINE Messaging APIから動画ファイルを取得
    const contentUrl = 'https://api-data.line.me/v2/bot/message/' + message.id + '/content';
    const videoBlob = UrlFetchApp.fetch(contentUrl, {
      headers: {
        'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN
      }
    });

    // YouTubeに動画をアップロード
    const video = YouTube.Videos.insert(
      {
        snippet: {
          title: 'LINEBotからの動画',
          description: 'LINEBotから送信された動画です。'
        },
        status: {
          //"public"で公開、 "private"で非公開、 "unlisted"で限定公開
          privacyStatus: 'private'
        }
      },
      // 動画をアップロードする際のパラメータ。snippetはタイトルや説明、statusは公開範囲の指定
      'snippet,status',
      // 動画のバイナリデータ
      videoBlob.getBlob()
    );

    // アップロードした動画のURLを取得
    const videoUrl = 'https://www.youtube.com/watch?v=' + video.id;

    // LINEBotに動画のURLを返信
    const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
    UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN
      },
      method: 'post',
      payload: JSON.stringify({
        replyToken: replyToken,
        messages: [{
          type: 'text',
          text: '動画をアップロードしました。'
        }, {
          type: 'text',
          text: videoUrl
        }]
      })
    });
  }catch(e){
    if(e=="TypeError: Cannot read properties of undefined (reading 'contents')") return 
    return
  }
}

コーディングが終わったらデプロイします。
その際に認証が必要になります。認証することで自動的にYouTubeAPIの申請が完了し、GASからのアップロードが可能になります。
また、トリガーとLINE側のWebHookの設定もお忘れなく。

完成!!

動画を送信しましょう。
LINEの上限である5分の動画もアップロードできるはずです。

image.png
image.png

あとがき

いやぁほんとYouTubeとGASってすごいなぁって思います。
アップロードのスクリプトがこんなに簡単に作れるのは衝撃でした。
加えてGCPでの認証なしでこういったことができるのも魅力だと思います。

また、バイナリデータから直接アップロードできることが分かったので、「DiscordとLINEの連携」のLINEからDiscordへの動画は一旦作り直して後日記事にしたいと思います。

それではまた次回の記事でお会いしましょう。

Discussion