YouTube から Twitter に自動投稿するボットを作った話

# TL;DR

- YouTube のプレイリストから動画をダウンロードしてツイッターにアップロード
- URL 貼り付けでなく Video Tweet
- ソースコード: https://github.com/teramotodaiki/youtube-to-twitter
- 運用中のボット: https://twitter.com/hackforplay
    - １日１本、 **子どもがプログラミングで作った** ゲームの実況動画を投稿しています。良かったらフォローしてね！

# 何が嬉しいのか

マーケティング施策として YouTube に１日１本動画をアップしています。チャンネル登録者数を増やしたいけど、YouTube のリコメンドだけでは流入が望めません。そこで、動画を数十秒だけ切り取って Twitter にアップして、「続きは YouTube で!!」的なのをやりたくなりました。しかし、

- 動画のトリミング **だるい**
- Twitter の動画アップロード **遅い**
- YouTube の **スケジュール投稿に合わせてツイート** しなきゃいけない

こんな作業を毎日やるとか、、人間の仕事ではない、、

ということで、自動化したいですよね

# それ IFTTT にないの？

結論から言うとないです。それっぽいのはあるけど、あくまで **YouTube リンクをツイートするだけ**。これだと **タイムライン上で動画が再生されません**

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">20秒以内にこの部屋から脱出しないと終わり <a href="https://twitter.com/hashtag/HackforPlay?src=hash&amp;ref_src=twsrc%5Etfw">#HackforPlay</a><br><br>つづきはこちら↓<a href="https://t.co/17bb46f4HP">https://t.co/17bb46f4HP</a> <a href="https://t.co/K9DQSoV2PH">pic.twitter.com/K9DQSoV2PH</a></p>&mdash; HackforPlay公式 (@hackforplay) <a href="https://twitter.com/hackforplay/status/1199331920129208320?ref_src=twsrc%5Etfw">November 26, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

> タイムライン上で動画が再生 **される** ツイート

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">タイムライン上で動画が流れないツイートの例<a href="https://t.co/Z4ZqXC4yUG">https://t.co/Z4ZqXC4yUG</a></p>&mdash; 寺本.hackforplay(); (@teramotodaiki) <a href="https://twitter.com/teramotodaiki/status/1199543693729861632?ref_src=twsrc%5Etfw">November 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

> タイムライン上で動画が再生 **されない** ツイート

タイムライン上で動画を流すには、Twitter に動画をアップロードする必要があります。当然、帯域やらストレージやらを食います。さらに、 **Twitter では動画が 140 秒までに制限されている** ため、トリミング（カット）する必要があります。動画編集にはそれなりの CPU 時間がかかるので、フリーのクラウド使うにしても、無償で提供出来るものではありません

多少おかね払っていいから、そういう SaaS ないの？とも考えたけど、ツイートの内容とかトリミングの秒数とか自分で比較検証することも考えると、やっぱりピッタリなソリューションは存在しないと思います。ないものは作るっきゃねえだろ。千空先生もそう言ってました。

# とにかく今すぐボットを作りたい人

[このリポジトリ](https://github.com/teramotodaiki/youtube-to-twitter)をクローンなりフォークなりしてください。環境変数は `.env.txt` ってファイルにキーだけ書いてあるので、設定してください

~~npm にパッケージも公開してるけど、あんまりオススメしません。なぜなら一部 Python を使っているせいで、環境構築が面倒だと思います~~

### 2019/11/27 追記

Pytube から ytdl に切り替えたので、Python 環境が不要になりました。試してないですが、おそらく動くはずです。自分用なのでテストも型定義も書いてませんが、Issue 立ててくれたら時間のある時に対応します

> npm install --save youtube-to-twitter


あとは適宜 cron jobs を使ってお好みのタイミングで `GET /` を叩いてください

# 前提

- 今回は **再生リスト** に含まれている動画を対象とします
- 動画が **公開されたら** ツイートします
- 一日一回、 cron job で curl してボットにツイートさせます
- 同じ動画を２回ツイートすることがないようにします

# 実装方法とかハマりポイントとか

## YouTube Data API

- 再生リストから動画の URL を取得するのに使います
- API Key が必要なので、Google Cloud Console で発行してください
- 今回使った PlaylistItem API には OAuth は必要ないので、 GET で叩くだけです
- https://developers.google.com/youtube/v3/docs/playlistItems/list


## Pytube

- YouTube から動画をダウンロードするためのライブラリです
- 名前の通り Python のライブラリなので、 `pip` でインストールする必要があります
    - [requirements.txt](https://github.com/teramotodaiki/youtube-to-twitter/blob/master/requirements.txt) 
- YouTube から動画をダウンロードする API はありません。何らかのトリックが必要で、それを Python で実装したライブラリが Pytube です
    - これを書いている途中で [ytdl](https://github.com/fent/node-ytdl-core) なる npm パッケージを見つけたので、そっちに移行するかも知れません
    - 余談ですが、これは YouTube の Terms of Use に抵触している行為なので、もし他人に第三者の動画をダウンロードさせるために使うのであれば権利についてご一考ください


## ffmpeg

- 言わずと知れた動画編集ライブラリです
- 今回は npm パッケージ経由でバイナリを入手し、 CLI から使います

## ffmpeg-installer

- **ffmpeg をインストールするための npm パッケージ**です
- https://github.com/kribblo/node-ffmpeg-installer

何を言ってるか分からない方向けの解説
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://t.co/u5CAbLbs5t">https://t.co/u5CAbLbs5t</a><br>npm を使って ffmpeg をインストール出来るライブラリ。これ自体に ffmpeg のバイナリがバンドルされており、npm install するだけで使える。プラットフォーム毎の下位パッケージがあり、 postinstall のタイミングで必要なパッケージ（バイナリ）のみインストール。賢い！</p>&mdash; 寺本.hackforplay(); (@teramotodaiki) <a href="https://twitter.com/teramotodaiki/status/1198793815894552576?ref_src=twsrc%5Etfw">November 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## Twitter API

- １番の曲者です（笑）
- まず、利用には申請が必要です。 [Twitter Developer](https://developer.twitter.com/)にアクセスして、 **ボットのアカウントでログイン** して申請を行ってください
    - 異なるアカウントで申請してしまうと、更新系の API が使えなくなってしまうので注意
    - どうやら同じメールアドレスで登録していれば、別アカウントでも「書けばすぐ Approve される」ようです
    - ハマりどころなのは、ウェブ上で記入→メールが届く→メールに返信する形でもう一度記入→審査開始、というプロセスになっているところです。メールが届いているのに気付かず、１週間放置していました…
- 同じ動画を２度アップロードしないために、過去２００件のツイートを取得します
    - https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
- 動画をアップロードします。この時、 5MB を超える動画には **chunking** が必要で、 30 秒を超える動画には **async upload** が必須になります。この辺、ドキュメントにも明示されてないし、 Node.js のサンプルがネットにあまりないので苦労しました
    - https://developer.twitter.com/en/docs/media/upload-media/overview
    - chunking についてはこの辺読んでください→ https://github.com/teramotodaiki/youtube-to-twitter/blob/70bf548acb291c36ea6febb33212816327c6ebd6/lib/tweet.js#L23-L34
    - async upload を有効にするには media_category の設定が必要です→ https://github.com/teramotodaiki/youtube-to-twitter/blob/70bf548acb291c36ea6febb33212816327c6ebd6/lib/tweet.js#L90
    - async upload が未完了の時にツイートするとエラーになるので、アップロードが完了したことを確かめるために **polling** が必要です → https://github.com/teramotodaiki/youtube-to-twitter/blob/70bf548acb291c36ea6febb33212816327c6ebd6/lib/tweet.js#L47-L66
- ツイートします。特にハマりポイントはありません
    - https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update