javascriptnode.jsaxiostiktok

Posting videos to Tiktok with Video Kit API fails


I'm trying to share a video on tiktok using the video kit api,the video I have is on a google cloud storage link so first I grab that from the cloud and attach it to a formdata with a readstream. I then make an axios post request to the given endpoint with my open id and access token (both of which are valid AND my post request is has the correct header which is multipart/form-data as specified on the docs).

            const storage = new Storage();
            const bucket = storage.bucket("<bucket name>");
            const remoteFile = bucket.file("<file path>");

            const openId = token['open_id'];
            const accessToken = token['access_token'];
            const postUrl = process.env.TIKTOK_POST_URL
                + '?open_id=' + openId
                + '&access_token=' + accessToken;
            let formData = new FormData();
            formData.append('video',remoteFile.createReadStream())
            const postResponse = await axios.post(postUrl,formData,{headers: { "Content-Type": "multipart/form-data" }});
            console.log(postResponse);

However, I keep getting a 400 code from the response with the extra detail;

expecting a binary field `video` in the form-data

I'm assuming I'm either not sending the video file correctly or not sending it at all. So far I've tried;

  1. Downloading the file with axios as a blob and sending the blob itself
  2. Downloading the file with axios as a stream and sending that
  3. Downloading the file with the google library itself and sending its buffer array
  4. [Current attempt] just getting a reference to the file and sending a write stream from it

All of these attempts have resulted in the same error message. Has anyone else faced this issue? There aren't any examples on the docs so I'm not sure how to handle this. I also don't want to download the video and save it to a file and try and post that as I'd rather just send the file from memory.

I'd appreciate any input.

Edit: I've also tried posting a video that is located on my machine like so,

formData.append('video',fs.createReadStream("C:/Users/[ME]/Downloads/tem.mp4"))

and still get the same error.

Edit 2: I've also tried streaming the data from these streams into a variable and have tried passing them into the form data and still get the same result

            stream.on('data',function(data)
            {
                File += data;
                console.log('streaming data');
            })
            stream.on('finish',async function()
            {
                formData.append('video',File)
                const postResponse = await 
axios.post(postUrl,formData,{headers: { "Content-Type": "multipart/form-data" }});
            }

Edit 3:

After failing to upload a small sized I've noticed that you can't upload videos shorter than 3 seconds, the video I was trying to upload was exactly 3 seconds so seeing as that may be the issue I've tried uploading a larger video, and managed to get another error.

Bad Gateway | KRAKEND.BACKEND/3 - request failed/320202:the server closed connection before returning the first response byte. Make sure the server returns 'Connection: close' response header before closing the connection

Solution

  • Here's what I ended up doing, this was part of a stateless cloud run instance so it was vital for me to not download the file anywhere and just pass the downstream directly into the upstream.

    // Grab the openId and access token from the integration
    const openId: string = integrationJSON['open_id'];
    const accessToken: string = integrationJSON['access_token'];
    // create the tiktok posting url
    const postUrl: string =
      process.env.TIKTOK_POST_URL +
      '?open_id=' +
      openId +
      '&access_token=' +
      accessToken;
    // Grab a downstream stream of the video from the storage URL
    const downStream = await axios({
      method: 'GET',
      responseType: 'stream',
      url: url,
    });
    // Append the downstream into a form data to be attached to our post request
    var data: FormData = new FormData();
    data.append('video', downStream.data);
    // Make a post request to tiktok with the downstream of the video and return the response
    const response = await axios({
      method: 'post',
      url: postUrl,
      headers: {
        'Content-Type': 'multipart/form-data',
        ...data.getHeaders(),
      },
      data: data,
      maxContentLength: Infinity,
      maxBodyLength: Infinity,
    });
    return response;