node-twitter icon indicating copy to clipboard operation
node-twitter copied to clipboard

Twitter video media upload not working : Error: HTTP Error: 400 Bad Request

Open bhushankummar opened this issue 7 years ago • 18 comments

I am trying upload and post video media to the twitter using 'twitter' npm package.

During this I am facing an error :

error  Error: HTTP Error: 400 Bad Request
at Request._callback (/Volumes/Office/Work/Pack3/developer/tweet-it/node_modules/twitter/lib/twitter.js:221:9)
at Request.self.callback (/Volumes/Office/Work/Pack3/developer/tweet-it/node_modules/request/request.js:185:22)
at Request.emit (events.js:180:13)
at Request.<anonymous> (/Volumes/Office/Work/Pack3/developer/tweet-it/node_modules/request/request.js:1157:10)
at Request.emit (events.js:180:13)
at IncomingMessage.<anonymous> (/Volumes/Office/Work/Pack3/developer/tweet-it/node_modules/request/request.js:1079:12)
at Object.onceWrapper (events.js:272:13)
at IncomingMessage.emit (events.js:185:15)
at endReadableNT (_stream_readable.js:1101:12)
at process._tickCallback (internal/process/next_tick.js:114:19)

Codebase Initialize library

var Twitter = require('twitter');

All details generate through twitter app console.

var twitterClient = new Twitter({
    consumer_key: process.env.TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
    access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
});


function makePost(endpoint, params) {
        return new Promise(function (resolve, reject) {
            twitterClient.post(endpoint, params, function (error, data, response) {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });
    }

exports.postVideo = async function (req, res, next) {
    var params = req.body;

    const pathToMovie = './medias/video_3_640x360_1mb.mp4';
    const mediaType = 'video/mp4'; // `'video/mp4'` is also supported
    const mediaData = require('fs').readFileSync(pathToMovie);
    const mediaSize = require('fs').statSync(pathToMovie).size;
    console.log('mediaData ', mediaData);

    try {

        var options = {
            command: 'INIT',
            total_bytes: mediaSize,
            media_type: mediaType,
        };

// This request about to complete

        var mediaInit = await makePost('media/upload', options);

        console.log('options ', options);
        console.log('mediaInit ', mediaInit);
        console.log('mediaInit.media_id_string ', mediaInit.media_id_string);

// This request is not working.

        await makePost('media/upload', {
            command: 'APPEND',
            media_id: mediaInit.media_id_string,
            media: mediaData,
            segment_index: 0
        });

        var mediaFinalize = await makePost('media/upload', {
            command: 'FINALIZE',
            media_id: mediaInit.media_id_string,
        });
        console.log('mediaFinalize ', mediaFinalize);
        var status = {
            status: params.status,
            media_ids: mediaFinalize.media_id_string
        };

        twitterClient.post('statuses/update', status, function (error, tweet, response) {
            if (error) {
                return next(error);
            }
            req.twitterStore = tweet;
            return next();
        });
    } catch (error) {
        console.log('error ', error);
        return next(error);
    }
};

Video Used : https://www.sample-videos.com/video/mp4/360/big_buck_bunny_360p_1mb.mp4

Reference : https://github.com/desmondmorris/node-twitter/tree/master/examples#chunked-media

bhushankummar avatar Jun 06 '18 06:06 bhushankummar

same issue at my end when trying with GIF.. Can you help me out?

harvinder-ss avatar Jun 12 '18 12:06 harvinder-ss

@harvinder-ss What exactly error are you facing?

gunwantkumar-kind avatar Jun 17 '18 10:06 gunwantkumar-kind

I have got it working now. thanks

harvinder-ss avatar Jun 18 '18 04:06 harvinder-ss

@harvinder-ss I am having the same issue, how did you resolve it?

ljmocic avatar Nov 14 '18 13:11 ljmocic

hi @ljmocic Twitter does not allow Video and gif to be posted in single upload command. You have to first Init the media upload and then Append the request by using the ID returned from Init.

check this for more details : https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-append

harvinder-ss avatar Nov 15 '18 04:11 harvinder-ss

I've figured out in the meantime, but thank you very much for the response!

ljmocic avatar Nov 15 '18 13:11 ljmocic

@ljmocic Can you please tell the solution? I went through the twitter docs as well as the examples of this package thoroughly but still, I am getting

400 bad request

in the FINALIZE step

neer17 avatar Jan 26 '19 11:01 neer17

Update: The error was getting produced by the STATUS step and after removing it the code just works fine. I think the STATUS step is not supported by the package.

neer17 avatar Feb 02 '19 12:02 neer17

@neer17 , @ljmocic, @harvinder-ss

can anyone show me a working example?? I am getting HTTP Error: 400 Bad Request

ashatat avatar Feb 03 '19 18:02 ashatat

I think that my solution was to use another package. Here is how you can solve it with twit. @neer17 @ashatat

twit.postMediaChunked({ file_path: PATH }, (err, data, response) => {
    handleError(err, callback);
    setTimeout(() => {
        getTweet(TEMP_FILENAME, callback).then(res => {
            twit.post('statuses/update', { status: res, media_ids: data.media_id_string }, (err, data, response) => {
                handleError(err, callback);
                callback(null, response)
            });
        });
    }, 3000); // Needed delay for processing of the video
});

ljmocic avatar Feb 04 '19 06:02 ljmocic

@ashatat See this chunked media example it is their official example.
@ljmocic the twit package can work but using that means restructuring the existing code. This twitter package is just fine. I think people are getting confused as in the official Twitter docs they have mentioned an optional step ie STATUS in the chunked upload whereas this package doesn't support it. Also, you can see the discussion on this on the thread that I have opened on StackOverflow regarding the same here.

@ashatat If the error still persists after removing the STATUS step then please put your code along with the error stack

neer17 avatar Feb 05 '19 17:02 neer17

@neer17 I understand, but this was the only use case that I needed to cover in my script. Maybe you could look up in the implementation inside that package, so you can extend the functionality of this one.

ljmocic avatar Feb 05 '19 18:02 ljmocic

@ljmocic I saw the chunked media example, they're using the chunked method but they're sending only one chunk, I need to send the file on multiple chunks with the APPEND command

I did some tweaks to my code, but it worked only for some images and some videos, which is weird and I have no clue of what is going on

here is my code

ashatat avatar Feb 05 '19 19:02 ashatat

@ashatat Are you making sure that all the images and videos are under 5MB and 15MB resp.?

neer17 avatar Feb 10 '19 18:02 neer17

@neer17 yeah all of the videos that I uploading are less than 15MB

ashatat avatar Feb 12 '19 09:02 ashatat

Why does this library not give you there error response from twitter? If we knew what the error was from twitter it would be easier to debug.

pr1ntr avatar May 28 '19 22:05 pr1ntr

I was able to view the error by changing the promise rejection from

reject(error);

to

reject(JSON.parse(response.body).error);

function makePost (endpoint, params) {
            console.log('Creating post for upload');
            return new Promise((resolve, reject) => {
              account_tweet.twitter_client.post(endpoint, params, (error, data, response) => {
                if (error) {
                  reject(JSON.parse(response.body).error);
                } else {
                  resolve(data);
                }
              });
            });
          }

In my case it was "InvalidContent". Maybe they don't accept quicktime format, only mp4?

adamjgrant avatar May 15 '20 01:05 adamjgrant

This stackoverflow example worked for me https://stackoverflow.com/a/47633263/15143364 for video chunk upload. Please check and let me know if guys are still facing some issues.

aditodkar avatar Jan 10 '22 06:01 aditodkar