Media not found on video upload

creative
video
best-practices

#1

Hi,

We’re using python to upload (in chunks) video to https://upload.twitter.com/1.1/media/upload.json which, judging by the response, seems to work:

{u’video’: {u’video_type’: u’video/mp4’}, u’media_id_string’: u’707206295934394368’, u’media_id’: 707206295934394368, u’expires_after_secs’: 86400, u’size’: 2432638}

However when subsequently adding the video to the creatives in the ads api (/accounts/[account_id]/videos) it produces an error: ‘Media not found’.

We’ve tried with both media_id as a string and as an id:

{‘description’: u’Test video 17’, ‘video_media_id’: u’707206295934394368’, ‘title’: u’Test video 17’}
{‘description’: u’Test video 17’, ‘video_media_id’: 707206295934394368, ‘title’: u’Test video 17’}

Any idea what the problem could be?

Thanks in advance.


#2

Hi @MySocialData! If you’re using the sandbox environment for the second call, that won’t work, because sandbox is a completely different environment than production (see Create Card issues).


#3

Thanks but no, this is on https://ads-api.twitter.com/0/


#4

Additional note: the same problem occurs on the video cards.


#5

The media_id is short lived. You should attempt to do the full flow – media upload + tweet w/ media – in one pass, and not time delayed. Is there significant time delayed between the two? Some more notes below.

Video Formatting

Also, make sure sure your video format is correct. As a general rule, ensure that your video is a standard landscape or portrait dimension (16:9, 3:2, or 1:1) and fits one of the below combinations of formats.

Orientation Width Height Video Bitrate Audio Bitrate
Landscape 1280 720 2048K 128K
Landscape 640 360 768K 64K
Landscape 320 180 256K 64K
Portrait 640 640 1024K 96K
Portrait 480 480 768K 64K
Portrait 240 240 256K 64K

The most up-to-date documentation on supported video formats is located on our video specifications and recommendations page.

To work with sample videos, we’ve found that http://www.videotoolbox.com/ is useful for modifying videos.

Other Common issues

Below are a number of common errors and issues when uploading media, and suggestions on how to resolve them.

  • media parameter is invalid. Format of the file does is not supported. See the most recent video specifications.
  • Invalid or unsupported media, Reason: UnsupportedMedia. Format of the file does is not supported. See the most recent video specifications.
  • Segments do not add up to provided total file size. Either the INIT command specified the wrong initial size, or the sum of the sizes of the chunks do not match the initial size. Alternatively, the chunks are not < 5MB each.
  • media type unrecognized. Indicate you’re using the non-chunked version of the media/upload API, or the media is unsupported.
  • checkVideoProcessingStatus called on a sync upload or an expired request. The media is still being processed. Try again later to confirm media is fully processed.

Sample & Test Code

Additionally, we have sample code here:

You can test this on our public hosting of our site:

http://django-rest-apis.herokuapp.com/


#6

Thanks for the extensive answer!

The sample videos we’ve used have all been succesfully uploaded to twitter in the past so I think that’s not it and the upload / linking in the api is done in a single process so there is no time delay. Looking at the sample code I suspect we missed the final step in the upload of the video: checking the status. I’ve added that step but the response is ‘over capacity’ at the moment. I’ll try again later today.


#7

It’s been 10 hours, I’ve tried occasionally but the server returns either

{“errors”:[{“message”:“Over capacity”,“code”:130}]}

or

{“errors”:[{“message”:“Internal error”,“code”:131}]}

I’ve also tried to verify that at least the steps are correct but I get different errors from twurl:

$ twurl -H upload.twitter.com “/1.1/media/upload.json” -d “command=INIT&media_type=video/mp4&total_bytes=2432638”
{“media_id”:707657874483257345,“media_id_string”:“707657874483257345”,“expires_after_secs”:86400}

$ twurl -H upload.twitter.com “/1.1/media/upload.json” -d “command=APPEND&media_id=707657874483257345&segment_index=0” --file shortvid.mp4 --file-field “media”

$ twurl -H upload.twitter.com “/1.1/media/upload.json” -d “command=FINALIZE&media_id=707657874483257345”
{“media_id”:707657874483257345,“media_id_string”:“707657874483257345”,“size”:2432638,“expires_after_secs”:86400,“video”:{“video_type”:“video/mp4”}}

$ twurl -H upload.twitter.com “/1.1/media/upload.json” -d “command=STATUS&media_id=707657874483257345”
{“errors”:[{“code”:38,“message”:“media parameter is missing.”}]}

Though I think the documentation says media_id … https://dev.twitter.com/rest/reference/post/media/upload-chunked

twurl -H upload.twitter.com “/1.1/media/upload.json” -d “command=STATUS&media=707657874483257345”
{“errors”:[{“code”:324,“message”:“The validation of media ids failed.”}]}

Is there any other way to debug this?

Thanks in advance.

Update: Also tried https://github.com/twitterdev/django-rest-apis now. (BTW, there’s a step missing in the setup instructions: python manage.py makemigrations home --settings=app.settings_my without it the video upload view breaks)

Using videos that are downloaded from twitter (using https://dev.twitter.com/ads/reference/get/accounts/%3Aaccount_id/videos) it also fails:

https://upload.twitter.com/1.1/media/upload.json INIT request: {‘media_type’: ‘video/mp4’, ‘command’: ‘INIT’, ‘total_bytes’: 2432638, ‘media_category’: u’amplify_video’}
https://upload.twitter.com/1.1/media/upload.json INIT response: {u’media_id_string’: u’707671080480051200’, u’media_id’: 707671080480051200, u’expires_after_secs’: 15552000}
https://upload.twitter.com/1.1/media/upload.json APPEND request: segment 0
https://upload.twitter.com/1.1/media/upload.json APPEND response: <Response [204]>
https://upload.twitter.com/1.1/media/upload.json FINALIZE request: 707671080480051200
https://upload.twitter.com/1.1/media/upload.json FINALIZE response: {u’media_id_string’: u’707671080480051200’, u’media_id’: 707671080480051200, u’processing_info’: {u’check_after_secs’: 5, u’state’: u’pending’}, u’expires_after_secs’: 15552000, u’size’: 2432638}
https://upload.twitter.com/1.1/media/upload.json STATUS request: {‘media_id’: u’707671080480051200’, ‘command’: ‘STATUS’}
https://upload.twitter.com/1.1/media/upload.json STATUS response: {u’media_id_string’: u’707671080480051200’, u’media_id’: 707671080480051200, u’processing_info’: {u’check_after_secs’: 5, u’state’: u’in_progress’, u’progress_percent’: 94}}
https://api.twitter.com/1.1/statuses/update.json request: {‘status’: u’Test video’, ‘media_ids’: [u’707671080480051200’]}
https://api.twitter.com/1.1/statuses/update.json response: {“errors”:[{“code”:44,“message”:“media parameter is invalid.”}]}


#8

@MySocialData I’ll see if I can help at all here.

It’s worth noting that media IDs are only valid for 60 mins. They must be used in a tweet, card or video object before then or they’ll be flushed from the storage bucket used by the media upload endpoint. This includes multipart upload sessions where you get a media ID from the INIT request. This behavior exists to prune unused or orphaned uploads to this endpoint.

When you do see an “Over capacity” error message from the media upload endpoint, this means that the video transcoding / processing pipeline can’t handle any more requests at the moment. In this situation, your implementation for video uploads should apply some retry logic with an exponential back-off.

It looks like you may not be using segment_index correctly. Here’s a quick script I wrote that may help and will allow you to experiment with media uploads in your terminal. It demonstrates what a simple, healthy upload session looks like.

Once loaded into your shell, here’s an example of using it:
http://showterm.io/efca218e71dd2873a65d5

After a successful upload, you also must check the media upload using the STATUS command and wait for the transcoding state=succeeded before you can use it in a tweet or create a reusable video object in POST /videos.

twurl -H upload.twitter.com "/1.1/media/upload.json?command=STATUS&media_id=707681967303577600"

{
  "media_id": 707681967303577600,
  "media_id_string": "707681967303577600",
  "size": 44540137,
  "expires_after_secs": 15551447,
  "processing_info": {
    "state": "succeeded",
    "progress_percent": 100
  }
}

If the video has not finished transcoding, the response from the STATUS command will indicate when you should check back for it’s completion (eg. check_after_secs).


#9

Hi Brandon,

Much appreciated. Uploading works with the bash-script and getting the status works too (I was doing a POST to get the status) so the sad conclusion is it must be my upload code. I’ve tried many different ways, media and raw chunks, media_data and the chunks of b64encoded data, using 3 or 4 different libraries to do the oauth requests but apart from obvious errors the result seems to always come back to the following scenario:

init works – a media id is returned etc.
append(s) work – or seem to: the response is 204. If the request is malformed this returns 400 errors with no additional message but I can get the server to accept the request in many ways
finalize works : if i upload the data and e.g. set the total_bytes to the length of the b64 encoded data it produces an error but if I set the length of the original video it doesn’t complain in this step (both when using media: rawdata or media_data: b64encoded data)

The final step, however, always fails: When I request the status I get the dreaded ‘Over capacity’ or (occasionally) ‘internal error’. I’ve verified the status request with twurl: if the upload was done with my script it also returns Over capacity. I suspect this is NOT actually the correct error. I’m sure I’m doing something wrong but the server is not giving me clues what my mistake(s) is/are or is my reasoning simply wrong?


#10

Im getting the same error