I have figured out how to do it on the command line:
curl -X POST --upload-file audio/test.wav
--header "Content-Type: audio/l16; rate=44100;"
"https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=MYKEY"
or
curl -X POST --data-binary @audio/test.wav
--header "Content-Type: audio/l16; rate=44100;"
"https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=MYKEY"
Where 'MYKEY' is my developer key.
How do I do this in C++, with libcurl? I have searched for hours but cannot figure out how to properly attach my audio file to a post request using CURLOPT_POSTFIELDS (or other parameters).
Here is what I have so far. It breaks with an access violation.
#include <iostream>
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl; // curl handle
CURLcode res;
curl = curl_easy_init();
if (curl)
{
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Content-Type: audio/l16; rate=44100");
std::cout << curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "file=@audio/test.wav") << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 177644) << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk) << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_CAINFO, "ca-bundle.crt") << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=MYKEY") << std::endl;
res = curl_easy_perform(curl);
std::cout << res;
curl_easy_cleanup(curl);
}
return 0;
}
I don't think the "file=@audio/test.wav" is correct, I saw that syntax on the PHP documentation for curl and decided to try it with libcurl.
I'm really at a loss, any help would be appreciated.
EDIT: Here is a working example [pastebin]. It took me a ridiculous amount of time to figure out. It uses the example functions given in http://curl.haxx.se/libcurl/c/post-callback.html, so its not a final solution, but is a good starting point. Make sure to put your API key into the speech API link.
#include <iostream>
#include <stdio.h>
#include <curl/curl.h>
#include <direct.h>
#include <string>
struct WriteThis {
const char *readptr;
long sizeleft;
};
// callback function from http://curl.haxx.se/libcurl/c/post-callback.html
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct WriteThis *pooh = (struct WriteThis *)userp;
if (size*nmemb < 1)
return 0;
if (pooh->sizeleft) {
*(char *)ptr = pooh->readptr[0]; /* copy one single byte */
pooh->readptr++; /* advance pointer */
pooh->sizeleft--; /* less data left */
return 1; /* we return 1 byte at a time! */
}
return 0; /* no more data left to deliver */
}
int main(void)
{
CURL *curl; // curl handle
CURLcode res;
curl = curl_easy_init();
if (curl)
{
FILE *file;
errno_t err = fopen_s(&file, "testaudio.wav", "r");
fseek(file, 0, SEEK_END);
int fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
std::cout << "file open status: " << err << std::endl;
std::cout << "file " << fileSize << std::endl;
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Content-Type: audio/l16; rate=44100");
char *audioData = (char*)malloc(fileSize);
struct WriteThis pooh;
fread(audioData, fileSize, 1, file);
fclose(file);
pooh.readptr = audioData;
pooh.sizeleft = fileSize;
std::string sizeHeader = "Content-Length: ";
sizeHeader += std::to_string(fileSize);
chunk = curl_slist_append(chunk, sizeHeader.c_str());
std::cout << curl_easy_setopt(curl, CURLOPT_POST, 1L) << std::endl;
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
std::cout << curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk) << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_CAINFO, "ca-bundle.crt") << std::endl;
std::cout << curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=yourkey") << std::endl;
res = curl_easy_perform(curl);
std::cout << res;
curl_easy_cleanup(curl);
}
return 0;
}
You need to use callback to upload the data file. You can find example here:
http://curl.haxx.se/libcurl/c/post-callback.html
data-binary is irrelevant in this example because you don't do anything with the file passing the data in callback, so it will be posted as is.