Search code examples
c#unity-game-enginecurl

How can I call this API endpoint in Hume.ai using Unity stuff?


Im trying to translate the cURL and javascript examples here into Unity and C# land..

cURL

    curl -X POST https://api.hume.ai/v0/batch/jobs \
         -H "X-Hume-Api-Key: keykeykeykeykeykeykeykey" \
         -H "Content-Type: multipart/form-data" \
         -F json='{}' \
         -F "file[]"=@"SpeechTest.mp3;type=audio/mpeg"

typescript example (they have an sdk for typscript afaik)

    const formData = new FormData();
    const fileFiles = document.getElementById("file").files;

    fileFiles.forEach((file) => {
      formData.append("file", file);
    });

    formData.append("json", JSON.stringify({}));
    // Start inference job from local file (POST /v0/batch/jobs)
    const response = await fetch("https://api.hume.ai/v0/batch/jobs", {
      method: "POST",
      headers: {
        "X-Hume-Api-Key": "keykeykeykeykeykeykeykey"
      },
      body: formData,
    });

    const body = await response.json();
    console.log(body);

My Unity code so far. I think the -F in cURL means I have to use wwwForm in Unity. Also in my use case I am only sending one file, but the endpoint seems like its designed to take one or more files in an array. I have tested the other stuff (like posting, headers) on different calls that dont require files and they are ok. Right now Im getting "400 bad request" back. I reckon its close though, any suggestions?

    IEnumerator HumeStartInferenceFromLocalFilesMultiple()
    {
        byte[] data = File.ReadAllBytes("C:\\PROJECTS\\MyProject\\Assets\\03_AUDIO\\SpeechTest.mp3");
        WWWForm form = new WWWForm();
        form.AddBinaryData("file", data, "SpeechTest.mp3", "audio/mpeg");
        form.AddField("json", "{}");  //json = '{}'

        using (UnityWebRequest www = UnityWebRequest.Post("https://api.hume.ai/v0/batch/jobs",form))
        {
            www.downloadHandler = new DownloadHandlerBuffer();
            www.SetRequestHeader("X-Hume-Api-Key", MyAPIKey);
            www.SetRequestHeader("Content-Type", "multipart/form-data");

            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError(www.error);
            }
            else
            {
                Debug.Log(www.downloadHandler.text);
            }
        }
    }

Solution

  • Ok the solution was just dont set the content type header. If I comment out that line it works.. Apparently when sending a multipart WWWform Unity automatically sets that and also sets the boundary string needed to separate different parts of the multipart data... And when you manually set content type it messes that up apparently.

        IEnumerator HumeStartInferenceFromLocalFilesMultiple()
        {
            byte[] data = File.ReadAllBytes("C:\\PROJECTS\\MyProject\\Assets\\03_AUDIO\\SpeechTest.mp3");
            WWWForm form = new WWWForm();
            form.AddBinaryData("file", data, "SpeechTest.mp3", "audio/mpeg");
            form.AddField("json", "{}");  //json = '{}'
    
            using (UnityWebRequest www = UnityWebRequest.Post("https://api.hume.ai/v0/batch/jobs",form))
            {
                www.downloadHandler = new DownloadHandlerBuffer();
                www.SetRequestHeader("X-Hume-Api-Key", MyAPIKey);
                //www.SetRequestHeader("Content-Type", "multipart/form-data");
    
                yield return www.SendWebRequest();
    
                if (www.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError(www.error);
                }
                else
                {
                    Debug.Log(www.downloadHandler.text);
                }
            }
        }