Twitter の Media API が更新され、公式クライアント以外からでも最大140秒の動画がアップロードできるようになりました。
ここでは、.NET用のTwitter APIライブラリCoreTweetにて当該の操作が可能だったため2016年6月23日正午時点での情報を綴ります。おそらく今後すぐにこの操作はもっと楽になると思われるので、ご注意ください。
APIの仕様
まず、アップロード可能な動画に関する情報は従来通りUploading Media | Twitter Developersに掲載されています。今回の仕様変更により一部の制限が以前より緩和されています。
APIを叩く手順は以前と比べて1段階追加されました。
日本語で@mpyw氏によりQiitaにまとめられています。
→TwitterAPIのアップロード系エンドポイントまとめ (140秒動画対応) – Qiita
以前と比較するとおおまかには
Before:
After:
と言った感じです。
以前はFINALIZEでファイナライズが完了するまで待っていましたが、今回より「FINALIZEはファイナライズ開始」、「STATUSが官僚を示すまで待つ(state: “in_progress”ではなくなるまで)」という手順に分割されました。
※なお、この手順では動画アップロードに失敗した際(140秒を超える場合など)については対応出来ていません。おそらくどこかで……最悪ツイート送信ではエラーが出るので
CoreTweetで試す
現在の最新リリースされているCoreTweetはSTATUSコマンドに対応していません。が、既にSTATUSコマンドに対応しているブランチ、uploadstatusが存在するのでこれを利用します。
なお、このブランチのバイナリはNightly Buildとしては配布されていないため、自分でチェックアウトしてビルドする必要があります。ビルドの方法についてはCoreTweetのREADMEをご覧ください。
同日のアップデート
(0.6.4)より非同期アップロードがサポートされました。
token
として用意してることを前提としたコードを示します。まず、従来のものを以下とします。
1 2 3 4 5 6 7 8 9 |
var fi = new FileInfo("C:\Foo\bar\movie.mp4"); MediaUploadResult result = await tokens.Media.UploadChunkedAsync(fi.OpenRead(), fi.Length, UploadMediaType.Video, new {}, CancellationToken.None); Status s = await tokens.Statuses.UpdateAsync( status => text, media_ids => result.MediaId ); |
Wikiに書かれてるコードをAsyncにしただけの単純なコードですね。
これに今回の変更を適用すると、例えば次のようなコードになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var fi = new FileInfo("C:\Foo\bar\movie.mp4"); UploadStatusCommandResult uploadStatus; MediaUploadResult result = await tokens.Media.UploadChunkedAsync(fi.OpenRead(), fi.Length, UploadMediaType.Video, new {media_category = "tweet_video"}, CancellationToken.None); while ((uploadStatus = ( await tokens.Media.UploadStatusCommandAsync(result.MediaId)))?.ProcessingInfo?.State == "in_progress") { await Task.Delay(uploadStatus.ProcessingInfo.CheckAfterSecs * 1000); } Status s = await tokens.Statuses.UpdateAsync( status => text, media_ids => result.MediaId ); |
変更点は2点。まず、INITコマンドに渡すパラメータとしてmedia_category = "tweet_video"
を追加しました。この値がないと非同期アップロードとならないので注意。
また、処理が終了するまでSTATUS
コマンドを叩く必要があるのでMedia.UploadStatusCommandAsync
をポーリングします。processing_info.stateがin_progressでなくなるまで、processing_info.check_after_secs秒(原状固定値5?)寝かせながら。
なお、この際processing_info.progress_percentにファイナライズの進行状況(%)が入っています。
state
は、“pending” -> “in_progress” -> [“failed” | “succeeded”]
の順に値を持つようですが、pending
まで無限ループにするとエラーが起こっているのにずっとpending といった状況がみられるようなので(またそれ以外のFINALIZE開始後の場合にpendingになっているのを確認できないため)ループ条件からは除外しています。
failed時はそれ用の分岐を作って例外を投げてもいいかもしれません。この際エラーが含まれるはずですが、どうやら非常にざっくりすぎるようなので無視しました。
悲報
公式キー限定だった pic.twitter.com/4a6q4EX6gF
— 休学確定 (@mpyw) June 23, 2016
なお、場合によりTwitterAPIでよくみかけるエラーの形が変えることもあるらしい。
【140秒を超える動画に関するまとめ】
・失敗時はstateがfailedになることがある(ただし200 OK)
・公式アプリのキーは140秒以上アップロードできる
・エラー内容によっては400以上でいつものerrors配列がくることもある— 休学確定 (@mpyw) June 23, 2016
— 休学確定 (@mpyw) June 23, 2016
エラー時はそのまま突き進んでもStatuses.UpdateAsyncで従来通りの例外を吐くので、合わせてtry-catchしておけばいいかと思います。
以上がCoreTweetで最大140秒の動画をアップロードする場合です。
なお、今後おそらくもっと手軽にこのアクションが出来るようになろうと思われるのでご期待ください。(上記のコードが使えなくなるかもしれません。)
なお、Twitterは140秒以上の動画だって上げれてしまう模様……
ちなみに、いわゆる公式キーを使用した場合、140秒を超える(確認済みでは5分)動画もアップロード出来るようでした。
@tos Test uploading long video using TwistOAuth ( YouTube URL: https://t.co/OEYG0dOLWo ) pic.twitter.com/V9CVblZuzD
— 休学確定 (@mpyw) June 23, 2016
わけがわからないよ……
UploadChunked
は非同期アップロード時に自動的にSTATUSコマンドを叩くようになりました。また、failed時にはMediaProcessingException
を投げます。