d60/twikit

Error when tweeting a video

Closed this issue · 11 comments

Hi, I'm using the library (ver 1.5.11) to upload videos.
I'm uploading the video like this:

media_id = await client.upload_media(source=video_bytes, media_type="video/mp4")
client.create_tweet(
    text="Video Tweet",
    media_ids=[media_id],
    is_note_tweet=True. # I'm using premium so i can post longer texts and videos
)

The upload is successful, but when I post the tweet I'm getting this err:

2024-04-30 21:43:23 - root - INFO - Media uploaded: [1785379xxxxx1136]
2024-04-30 21:43:24 - root - ERROR - Error while posting to Twitter: BadRequest: Not valid video (324)
Traceback (most recent call last):
  File "/app/tg.py", line 90, in post_to_twitter
    tweet = await tw.post_tweet(
            ^^^^^^^^^^^^^^^^^^^^
  File "/app/tw.py", line 38, in post_tweet
    return await client.create_tweet(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/twikit/twikit_async/client.py", line 1119, in create_tweet
    raise_exceptions_from_response(response['errors'])
  File "/usr/local/lib/python3.11/site-packages/twikit/errors.py", line 100, in raise_exceptions_from_response
    raise exception(error['message'])
twikit.errors.InvalidMedia: BadRequest: Not valid video (324)

Anybody?

d60 commented

@david-lev That's because the video upload is not yet complete. Set wait_for_completion to True to wait until the upload is complete.

media_id = await client.upload_media(source=video_bytes, wait_for_completion=True, media_type="video/mp4")

@d60 Thanks for your help. I try to wait_for_completion but I'm getting this err now:

2024-05-01 21:09:34 - root - ERROR - Error while uploading media to Twitter: 'coroutine' object is not subscriptable
Traceback (most recent call last):
  File "/app/tw.py", line 24, in post_tweet
    [await client.upload_media(source=media, wait_for_completion=True) for media in medias]
  File "/app/tw.py", line 24, in <listcomp>
    [await client.upload_media(source=media, wait_for_completion=True) for media in medias]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/twikit/twikit_async/client.py", line 771, in upload_media
    processing_info = state['processing_info']
                      ~~~~~^^^^^^^^^^^^^^^^^^^
TypeError: 'coroutine' object is not subscriptable
/app/tw.py:30: RuntimeWarning: coroutine 'Client.check_media_status' was never awaited
  return
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Okay, I 'awaited' manually for check_media_status and when processing_info["state"] == "succeeded" I posted the tweet. this the err in got:

Traceback (most recent call last):
  File "/app/tg.py", line 83, in post_to_twitter
    tweet = await tw.post_tweet(
            ^^^^^^^^^^^^^^^^^^^^
  File "/app/tw.py", line 45, in post_tweet
    return await client.create_tweet(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/twikit/twikit_async/client.py", line 1119, in create_tweet
    raise_exceptions_from_response(response['errors'])
  File "/usr/local/lib/python3.11/site-packages/twikit/errors.py", line 100, in raise_exceptions_from_response
    raise exception(error['message'])
twikit.errors.InvalidMedia: BadRequest: Duration too long, maximum:2.minutes+20.seconds, actual:4.minutes+33.seconds+400.milliseconds (MediaId: snf:1785736xxxx5488) (324)
d60 commented

@d60 Thanks for your help. I try to wait_for_completion but I'm getting this err now:

2024-05-01 21:09:34 - root - ERROR - Error while uploading media to Twitter: 'coroutine' object is not subscriptable
Traceback (most recent call last):
  File "/app/tw.py", line 24, in post_tweet
    [await client.upload_media(source=media, wait_for_completion=True) for media in medias]
  File "/app/tw.py", line 24, in <listcomp>
    [await client.upload_media(source=media, wait_for_completion=True) for media in medias]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/twikit/twikit_async/client.py", line 771, in upload_media
    processing_info = state['processing_info']
                      ~~~~~^^^^^^^^^^^^^^^^^^^
TypeError: 'coroutine' object is not subscriptable
/app/tw.py:30: RuntimeWarning: coroutine 'Client.check_media_status' was never awaited
  return
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Sorry I forgot to add "await". I have just released version 1.5.12 and fixed that.

d60 commented

Okay, I 'awaited' manually for check_media_status and when processing_info["state"] == "succeeded" I posted the tweet. this the err in got:

Traceback (most recent call last):
  File "/app/tg.py", line 83, in post_to_twitter
    tweet = await tw.post_tweet(
            ^^^^^^^^^^^^^^^^^^^^
  File "/app/tw.py", line 45, in post_tweet
    return await client.create_tweet(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/twikit/twikit_async/client.py", line 1119, in create_tweet
    raise_exceptions_from_response(response['errors'])
  File "/usr/local/lib/python3.11/site-packages/twikit/errors.py", line 100, in raise_exceptions_from_response
    raise exception(error['message'])
twikit.errors.InvalidMedia: BadRequest: Duration too long, maximum:2.minutes+20.seconds, actual:4.minutes+33.seconds+400.milliseconds (MediaId: snf:1785736xxxx5488) (324)

That error is probably because you are trying to upload a video longer than the maximum size (2 minutes 20 seconds).

wow you are fast.. thanks!!
Premium accounts can upload longer videos. Is it possible to add support for this in the library? I can check the endpoints

  • Start upload
curl 'https://upload.twitter.com/i/media/upload2.json?command=INIT&total_bytes=30034657&media_type=video%2Fmp4&video_duration_ms=273400&media_category=tweet_video' \
  -X 'POST' \
  -H 'accept: */*' \
  -H 'accept-language: en-US,en;q=0.9,he;q=0.8,he-IL;q=0.7' \
  -H 'authorization: Bearer xxxxx' \
  -H 'cache-control: no-cache' \
  -H 'content-length: 0' \
  -H 'cookie: kdt=VABcmEXj4RA=="' \
  -H 'dnt: 1' \
  -H 'origin: https://twitter.com' \
  -H 'pragma: no-cache' \
  -H 'priority: u=1, i' \
  -H 'referer: https://twitter.com/' \
  -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?1' \
  -H 'sec-ch-ua-platform: "Android"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36' \
  -H 'x-csrf-token: xxxx' \
  -H 'x-twitter-auth-type: OAuth2Session'
  • Continue upload:
curl 'https://upload.twitter.com/i/media/upload2.json?command=APPEND&media_id=1785xxxxx7391488&segment_index=0' \
  -X 'OPTIONS' \
  -H 'accept: */*' \
  -H 'accept-language: en-US,en;q=0.9,he;q=0.8,he-IL;q=0.7' \
  -H 'access-control-request-headers: authorization,x-csrf-token,x-twitter-auth-type' \
  -H 'access-control-request-method: POST' \
  -H 'cache-control: no-cache' \
  -H 'origin: https://twitter.com' \
  -H 'pragma: no-cache' \
  -H 'priority: u=1, i' \
  -H 'referer: https://twitter.com/' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36'
  • Post tweet (after upload & process is done):
  curl 'https://twitter.com/i/api/graphql/zIdRTsSqcD6R5uMtm_N0pw/CreateTweet' \
  -H 'accept: */*' \
  -H 'accept-language: en-US,en;q=0.9,he;q=0.8,he-IL;q=0.7' \
  -H 'authorization: Bearer xxxxxxx' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'cookie: xxxxxx' \
  -H 'dnt: 1' \
  -H 'origin: https://twitter.com' \
  -H 'pragma: no-cache' \
  -H 'priority: u=1, i' \
  -H 'referer: https://twitter.com/compose/post' \
  -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?1' \
  -H 'sec-ch-ua-platform: "Android"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-origin' \
  -H 'user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36' \
  -H 'x-client-transaction-id: xxxx' \
  -H 'x-csrf-token: xxxxxxx' \
  -H 'x-twitter-active-user: yes' \
  -H 'x-twitter-auth-type: OAuth2Session' \
  -H 'x-twitter-client-language: he' \
  --data-raw '{"variables":{"tweet_text":"test","dark_request":false,"media":{"media_entities":[{"media_id":"1785xxxxx91488","tagged_users":[]}],"possibly_sensitive":false},"semantic_annotation_ids":[]},"features":{"communities_web_enable_tweet_community_results_fetch":true,"c9s_tweet_anatomy_moderator_badge_enabled":true,"tweetypie_unmention_optimization_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"view_counts_everywhere_api_enabled":true,"longform_notetweets_consumption_enabled":true,"responsive_web_twitter_article_tweet_consumption_enabled":true,"tweet_awards_web_tipping_enabled":false,"creator_subscriptions_quote_tweet_preview_enabled":false,"longform_notetweets_rich_text_read_enabled":true,"longform_notetweets_inline_media_enabled":true,"articles_preview_enabled":true,"rweb_video_timestamps_enabled":true,"rweb_tipjar_consumption_enabled":true,"responsive_web_graphql_exclude_directive_enabled":true,"verified_phone_label_enabled":false,"freedom_of_speech_not_reach_fetch_enabled":true,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":true,"tweet_with_visibility_results_prefer_gql_media_interstitial_enabled":true,"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,"responsive_web_graphql_timeline_navigation_enabled":true,"responsive_web_enhance_cards_enabled":false},"queryId":"zIxxxxxuMtm_N0pw"}'
d60 commented

@david-lev Thanks! i'll get to work on it right away, but it may take some time. If you need to use the functionality immediately, change the UPLOAD_MEDIA endpoint on line 206 of twikit/utils.py.

d60 commented

@david-lev Added is_long_video argument in version 1.5.13 .You can upload long videos by setting this argument to True.

@d60 Works great. The best library ever!!