Twitter への動画つき投稿
簡単な方法がありそうでなかったので、地道に api をコツコツ呼びました。
詳細は以下のサイトにまとまっているのですが、基本的な仕組みとswiftでの実装メモを書きました。
CORETWEETで30秒を超える動画をTWITTERにアップロードしてみる
Twitter api を2つ使います
// 動画アップロード用 : こちらに色々なコマンドを投げる
let UPLOAD_URL = NSURL(string: "https://upload.twitter.com/1.1/media/upload.json")
// ツイート用 : 最後に1回投げてツイート完了
let STATUS_URL = NSURL(string: "https://api.twitter.com/1.1/statuses/update.json")
最初に動画をアップロードして、media_id_string を取得
- UPLOAD_URLにコマンドを投げます。
大きなファイルは分割してアップロード。以下4コマンドを順次呼び出します。
1. INIT (開始。media_id_stringを取得。以後の呼び出しは、全てこの値を使う)
2. APPEND (ファイルを適当な容量に分割して全部アップロードできるまで呼ぶ)
3. FINALIZE (終了)
4. STATUS
ポイントは、アップロード完了から、メディアが使用可能になるまで間があるとこです。
STATUS の戻り値で、state == "succeeded" になるまでポーリングが必要です。
if json["processing_info"]["state"] == "succeeded" {
// 次の処理へ
}
media_id_string と text を一緒にツイート
- STATUS_URL にコマンドを投げます。
let params = [
"status": self.mTweet,
"media_ids": self.mMediaIdString
]
swift での実装メモ
通信で使用するクラス・メソッド
SLRequest
.addMultipartData
.performRequestWithHandler
バイナリファイル分割
// CHUNK_SIZE = 2 * 1024 * 1024 など、大きすぎないサイズ。
// mSegmentIndex は、0からの連番。append を呼ぶたびに +1。
var _range = NSRange()
_range.location = mSegmentIndex * CHUNK_SIZE
_range.length = min(CHUNK_SIZE, mFileSize)
let _mediaData = NSData(contentsOfFile: self.mFilePath)
let mediaData = _mediaData?.subdataWithRange(_range)
非同期コードの塊ですが、SwiftTask を使うとネストが深くならずに快適に実装できました。
SwiftTask(Promise拡張)を使う
メモ
FINALIZE -> STATUS 確認まで5秒程必要っぽいので、ツイート編集画面を表示した時点などでこっそりアップロードを開始したいところですが、キャンセル時など、数メガのアップロードが無駄になると思うと悩ましいところです。
以上です。