5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonを使ってTwitterに長い動画を簡単に投稿する方法

Last updated at Posted at 2021-05-13

Tweepyは開発版しか動画投稿がサポートされていない

  • これを使うと投稿できるらしいが、まだpipには無い。色々調べたら結果的に遠回りになったがTweepy以外のほうが楽そうだったので情報をまとめる。
    • python-twitterを使って投稿する方法(おすすめ)
    • Twitterのエンドポイントにライブラリを使わないでやる方法(ひたすらダルい)

python-twitterを使う

  • api.PostUpdate(status=text, media=mediaId)のmediaにmp4のアドレスを指定しても30秒までなら何故かいけた。
    • 30秒以上の動画は分割して圧縮しなきゃならないらしい(後述処理でまんまそれをやっている)、python-twitterだと内部処理で行ってくれているらしい、非常にありがたい。
      • 欲を言うならステータス確認的なコードが欲しかった。
import twitter
# 認証
api = twitter.Api(consumer_key=baka,
                  consumer_secret=aho,
                  access_token_key=manuke,
                  access_token_secret=darazu)
# アップロード
mediaId = api.UploadMediaChunked(
    media="./a.mp4", media_category="tweet_video")
# 仕様です https://github.com/bear/python-twitter/issues/654
time.sleep(10)
# ツイート
api.PostUpdate(status=text, media=mediaId)
  • 地味にByteIO型も対応しているのでFaaSでも安心!
from io import BytesIO
import requests

movieUrl = "http://~~~~~~.mp4"
ioimg = requests.get(movieUrl)
upimg = BytesIO(ioimg.content)
upimg.mode = 'rb'
upimg.name = 'mobie.mp4'
# 可能
mediaId = api.UploadMediaChunked(
    media=upimg, media_category="tweet_video")

素でエンドポイントにPostする

from requests_oauthlib import OAuth1Session
import os

# ツイート用エンドポイント
twUrl = "https://api.twitter.com/1.1/statuses/update.json"
# メディア用エンドポイント
upUrl = "https://upload.twitter.com/1.1/media/upload.json"

# 認証
twitter = OAuth1Session(consumer_key, consumer_secret, access_key, access_secret)
# サイズ指定が必要なので後で使う
totalBytes = os.path.getsize("./a.mp4")

# ID取得
initParams = {
    "command": "INIT",
    "media_type": "video/mp4",
    "total_bytes": totalBytes,
    "media_category": "tweet_video"
}
initResponse = twitter.post(url=upUrl, data=initParams)
mediaId = initResponse.json()['media_id']

# 分割アップロード処理
segmentId = 0
bytesSent = 0
with open("./a.mp4") as f: #ByteIO型はgetsize含めて別に作りこみが必要
    while bytesSent < totalBytes:
        chunk = f.read(1*1024*1024)

        addParams = {
            "command": "APPEND",
            "media_id": mediaId,
            "segment_index": segmentId
        }

        files = {
            "media": chunk
        }

        appendResponse = twitter.post(url=upUrl, data=addParams, files=files)
        print(appendResponse)

        segmentId = segmentId + 1
        bytesSent = f.tell() # バイナリモードの時にファイルの先頭からのバイト数を返却する
        print("%s of %s bytes uploaded" % (str(bytesSent), str(totalBytes)))

    print("upload complete")

    # ファイナライズ処理
    finalizeParams = {
        "command": "FINALIZE",
        "media_id": mediaId
    }

    finalizeResponse = twitter.post(url=upUrl, data=finalizeParams)

    statusParams = {
        "command": "STATUS",
        "media_id": mediaId
    }

    statusResponse = twitter.get(url=upUrl, params=statusParams)
    print(statusResponse)
    processingInfo = statusResponse.json().get("processing_info", None)

    while processingInfo['state'] == 'in_progress':
        time.sleep(1)
        statusResponse = twitter.get(url=upUrl, params=statusParams)
        processingInfo = statusResponse.json().get("processing_info", None)
        print(processingInfo)

    # ツイートする
    params = {
        "status": "動画ツイート",
        "media_ids": mediaId
    }

    twitter.post(url=twUrl, data=params)

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?