Consistently get 'Decoding Error' 10004 when trying to upload a video using fetch

Here is my javascript

function upload(){
    var input = document.querySelector('input[type="file"]')

    var data = new FormData()
    data.append('file', input.files[0])
    console.log(input.files[0])
    let options = {method: "post",
        body: data,
        headers: {
            "X-Auth-Email": "{email}@gmail.com",
            "X-Auth-Key": "{key}",
            "Content-Type": "multipart/form-data",
        }}
    fetch("https://api.cloudflare.com/client/v4/accounts/{accID}/stream", options)
        .then(response => response.json())
        .then(data => console.log(data));
}

In the console, I get the error

errors: Array(1)
0: {code: 10004, message: 'Decoding Error'}
length: 1
[[Prototype]]: Array(0)
messages: null
result: null
success: false

There is only one input file in my HTML, and after doing some console.logging, I know that is getting the correct video file.

Have you tried uploading via the command line to the API? That will help narrow down whether it’s an issue with your code or the video/API:

https://developers.cloudflare.com/stream/uploading-videos/upload-video-file

The cURL request worked, so I’m pretty sure it’s something up with my code

It probably has nothing to do with your code. I’ve spent a few hours now getting video upload (“copy”) to work from a python script because I need to migrate a lot of videos, which I can’t do by hand and don’t want to do with a shell script.

The API endpoints expects very unconventional way of formatting the data. Basically, the data needs to be sent as Content-Type: application/x-www-form-urlencoded for some reason. Then, the actual data needs to be a JSON dictionary key… Embedded in a string, like so: key = f'{{"url":"{video_url}","meta":{{"name":"{video_title}"}},"thumbnailTimestampPct":{thumbnail_percent}}}' data = {key: ""}

If anyone struggles with requests, here is the function I ended up coding to automatically upload/copy videos from python:

def upload_video_to_cstream(video_url, video_title, thumbnail_percent=0.5):
url = f"{BASE_URL}/copy"
key = f’{{“url”:"{video_url}",“meta”:{{“name”:"{video_title}"}},“thumbnailTimestampPct”:{thumbnail_percent}}}’
data = {key: “”}

headers = {
    "X-Auth-Key": CLOUDFLARE_API_KEY,
    "X-Auth-Email": CLOUDFLARE_AUTH_EMAIL,
    "content-type": "application/x-www-form-urlencoded",
    "user-agent": "curl/7.74.0",
    "accept": "*/*",
    "content-length": f"{len(key)}",
}

r = requests.Request("POST", url, headers, data=data)
prepped = r.prepare()
prepped.headers["content-length"] = f"{len(key)}"
prepped.body = {key.encode("ASCII"): ""}

response = session.send(prepped)
json = response.json()

success = json["success"]
errors = json["errors"]

if not success:
    print("Error while uploading video. Errors:", errors)
    print("Full response:", json)
        sys.exit(1)

result = json["result"]
uid = result["uid"]
thumbnail_url = result["thumbnail"]
preview_url = result["preview"]
playback_url = result["playback"]["dash"]

return (uid, thumbnail_url, preview_url, playback_url)

It’s very ugly but does the work. Note that it’s currently as of 16/01/2022, they might update the endpoint to accept application/json content at some point.

1 Like

Hey, did you figure out what was the issue?