So using Wit.ai I'm trying to use speech to text. I am using the Wit3D example from Github: https://github.com/afauch/wit3d/blob/master/Assets/UserScripts/Wit3D.cs
Recording of sound and saving to the .wav file works just fine. Sending the request to the server does not.
The .wav file is valid as I get a response when manually making a request through Postman.
The request code looks like this:
string GetJSONText(string file)
{
// get the file w/ FileStream
FileStream filestream = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryReader filereader = new BinaryReader(filestream);
byte[] BA_AudioFile = filereader.ReadBytes((Int32)filestream.Length);
filestream.Close();
filereader.Close();
//var bytes = File.ReadAllBytes(Path.Combine(Application.dataPath, "sample.wav"));
// create an HttpWebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.wit.ai/speech?v=20160901");
request.Method = "POST";
request.Headers["Authorization"] = "Bearer 3XFWDOBVS65V5A2VZWZFBB2PHOKDWGOH";
request.ContentType = "audio/wav";
//request.Timeout = 10000;
request.GetRequestStream().Write(BA_AudioFile, 0, BA_AudioFile.Length);
// Process the wit.ai response
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
print("Http went through ok");
StreamReader response_stream = new StreamReader(response.GetResponseStream());
return response_stream.ReadToEnd();
}
else
{
return "Error: " + response.StatusCode.ToString();
return "HTTP ERROR";
}
}
catch (Exception ex)
{
return "Error: " + ex.Message;
return "HTTP ERROR";
}
}
With or without putting a Timeout on the request I get the following Error message: "Error: The request timed-out"
Removing the line:
request.GetRequestStream().Write(BA_AudioFile, 0, BA_AudioFile.Length)
Will get me a response:
Error: Error getting response stream (Write: The authentication or decryption has failed.)
Which makes sense, because there is nothing to decrypt.
My firewall doesn't seem to be the problem. Any ideas of why there is a time-out? Using different methods of getting a byte[] didn't fix it either.
EDIT:
Putting the code in a normal Console application does work. So this seems to be a Unity issue.
Add this to top of your script:
using System.Collections.Generic;
Use this code.
public void SendRequest(string wavPath)
{
if(!File.Exists(wavPath))
{
Debug.Log("Invalid wav path.");
return;
}
StartCoroutine(SendRequestToWitAi(wavPath));
}
public IEnumerator SendRequestToWitAi(string wavPath)
{
string API_KEY = "3XFWDOBVS65V5A2VZWZFBB2PHOKDWGOH";
string url = "https://api.wit.ai/speech?v=20160526";
byte[] postData = File.ReadAllBytes(wavPath);
Dictionary<string, string> headers = new Dictionary<string, string>();
headers["Content-Type"] = "audio/wav";
headers["Authorization"] = "Bearer " + API_KEY;
float timeSent = Time.time;
WWW www = new WWW(url, postData, headers);
yield return www;
while (!www.isDone)
{
yield return null;
}
float duration = Time.time - timeSent;
if (www.error != null && www.error.Length > 0)
{
Debug.Log("Error: " + www.error + " (" + duration + " secs)");
yield break;
}
Debug.Log("Success (" + duration + " secs)");
Debug.Log("Result: " + www.text);
}
Use a JSON parser to parse www.text value. The "_text" field contains the result text.
Related
private void Upload(){
string apiURL = Globals.GoogleSpeechToTextURL + Globals.GoogleSpeechToTextApiKey;
string Response;
Debug.Log("Uploading " + filePath);
var fileInfo = new System.IO.FileInfo(filePath);
Debug.Log("Size: "+fileInfo.Length);
gtext.text = fileInfo.Length + " ";
Response = HttpUploadFile(apiURL, filePath, "file", "audio/wav; rate=44100");
var list = new List<Event>();
JObject obj = JObject.Parse(Response);
//return event array
var token = (JArray)obj.SelectToken("results");
if (token != null)
{
foreach (var item in token)
{
string json = JsonConvert.SerializeObject(item.SelectToken("alternatives")[0]);
list.Add(JsonConvert.DeserializeObject<Event>(json));
}
Debug.Log("Response String: " + list[0].transcript);
}
}
public string HttpUploadFile(string url, string file, string paramName, string contentType)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
Debug.Log(string.Format("Uploading {0} to {1}", file, url));
Byte[] bytes = File.ReadAllBytes(file);
String file64 = Convert.ToBase64String(bytes,
Base64FormattingOptions.None);
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Proxy = null;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{ \"config\": { \"languageCode\" : \"en-US\" }, \"audio\" : { \"content\" : \"" + file64 + "\"}}";
// Debug.Log(json);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
// Debug.Log(httpResponse);
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
catch (WebException ex)
{
var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
// Debug.Log(resp);
}
return "empty";
}
This is the code I am using to upload an audio file. When HttpUploadFile gets called, the app pauses and shows a black screen for a second and then continues. I tried calling Upload function through coroutine, and also tried this Use Unity API from another Thread or call a function in the main Thread. But still it pauses while uploading. The file size is around 200 KB
What else can I try to avoid this problem?
Use UnityWebRequest instead. You cannot make blocking HTTP request calls on the main thread.
Also, the HTTP API has a pattern for file uploads, packing an audio file into a base 64-encoded field in JSON is going to crash your JSON parser if the string is too large.
i try to figure it out the black box of the server side that code by python for sending http post. In C# i trying to use httpwebrequest and httpwebresponse to send and receive message back from the server side.
Below is the python code:
**# Request login to server**
import httplib, urllib, requests
import sys, time
from requests.adapters import HTTPAdapter
import select, socket
s = requests.Session()
url = 'http://192.168.1.1/request_login'
data = 'user.login(test,test)' #login account and password set here
r = s.post(url, data=data)
if r.status_code != 200:
print "Failed loging in (%d)" % (r.status_code)
sys.exit(-1)
**# send key file to server**
url = 'http://192.168.1.1/request_sendfile'
files = {'file': (data_xml, open(data_xml, 'rb'), 'application/x-binary', {'Expires': '0'})} # **Don't understand this format**
r = s.post(url, files=files, timeout=30.0)
if r.status_code != 200:
print "Failed sending data file (%d, %s)" % (r.status_code, r.reason)
url = 'http://192.168.1.1/request_sendfile'
data = 'reader.view_log(4)'
r = s.post(url, data=data)
if r.status_code != 200:
print "Failed loging in (%d)" % (r.status_code)
sys.exit(-3)
print "Logs: "
print r.content
sys.exit(-4)
Above is the code for login and sending file to server in one session, i try to use C# do the same way.
I set two http request at the same time, however for the login is success while try to get second http request i get an error of "400" doesn't understand context of verb.
Below is the C# code:
private void httpost()
{
try
{
string Url = "http://192.168.1.1/request_login";
string Urls = "http://192.168.1.1/request_sendfile";
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
HttpWebRequest requests = HttpWebRequest.Create(Urls) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "login";
string param = "user.login(test,test)";
byte[] bs = Encoding.ASCII.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
StreamReader sr = new StreamReader(response.GetResponseStream());
HttpWebResponse resp = (HttpWebResponse)request.GetResponse();
if(resp.StatusCode == HttpStatusCode.OK)
{
richTextBox1.AppendText("Login Response Status:" + resp.StatusCode + "\n");
}
else
{
richTextBox1.AppendText("Login Response Failed: " + resp.StatusCode + "\n");
}
request.KeepAlive = true;
result = sr.ReadToEnd();
sr.Close();
}
using (Stream importFile = requests.GetRequestStream())
{
FileStream fs = File.OpenRead(#"data.xml");
byte[] bytes = ReadWholeArray(fs); // turn xml file to byte function
requests.ContentType = "application/x-binary";
requests.Method = "POST";
importFile.Write(bytes, 0, bytes.Length);
}
using (WebResponse responses = requests.GetResponse())
{
StreamReader srs = new StreamReader(responses.GetResponseStream());
result = srs.ReadToEnd();
srs.Close();
}
}
catch (Exception ex)
{
richTextBox1.AppendText("Exception Throw:" + ex.Message);
}
}
I try the python code it request login and send file at the same time.
And below is the code that i don't understand.
files = {'file': (data_xml, open(data_xml, 'rb'), 'application/x-binary', {'Expires': '0'})}
I've integrated an option for users to pay via PayPal their online shopping on the web shop that I'm creating. The problem came up suddenly when I started to get this error:
You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.
And the code for the Http call is as following:
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost.ToString());
}
}
catch (Exception e)
{
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse(); // this is the line where the exception occurs...
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
Can someone help me out with this? It worked fine a day ago, now its giving me this error?
Okay so if anyone is interested, I was able to fix the error by adding the following line before creating the web request (I was able to fix it by going down to Tls12 like this):
`ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12`;
Cheers :-)
Edit try this:
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// Try using Tls11 if it doesnt works for you with Tls
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = WebRequestMethods.Http.Post;
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost.ToString());
}
}
catch (Exception e)
{
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
public string HttpCall(string NvpRequest) //CallNvpServer
{
string url = pendpointurl;
//To Add the credentials from the profile
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode( BNCode );
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception e)
{
/*
if (log.IsFatalEnabled)
{
log.Fatal(e.Message, this);
}*/
}
//Retrieve the Response returned from the NVP API call to PayPal
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
//Logging the response of the transaction
/* if (log.IsInfoEnabled)
{
log.Info("Result :" +
" Elapsed Time : " + (DateTime.Now - startDate).Milliseconds + " ms" +
result);
}
*/
return result;
}
After a number of hours wasted, it turned out to be the Tls protocol version.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I build a windows-mobile 6.5 application (based on cf 2.0) and have a problem with a special test case of one method. So I hope someone can give me an advice or has a helpful idea what the reason for this behaviour is...
The method is called continuous every 30 seconds from inside a thread, looks for files to be transferred via a HTTP request to a web server (jboss) and brings them on their way. The server url itself is under my control.
Everything works fine ... until I stop the web server and force an 503 server error. So far so good. But after restarting the web server, I would expect, that the next call of the transfer method will end in success - but it does not. Every further try ends in a timeout exception and I have to restart the application to make it work again.
So my question is: where is the problem, when I want to connect to an uri after an earlier try has failed with error 503? It seems, that there is something cached, but what the hell should it be?
Many thanks for every hint you have.
Juergen
public static Boolean HttpUploadFile2(string url, string file)
{
HttpWebRequest requestToServer = null;
WebResponse response = null;
try
{
Logger.writeToLogFileCom(string.Format("Uploading {0} to {1}", file, url));
requestToServer = (HttpWebRequest)WebRequest.Create(url);
requestToServer. Timeout = 40000;
string boundaryString = "----SSLBlaBla";
requestToServer.AllowWriteStreamBuffering = false;
requestToServer.Method = "POST";
requestToServer.ContentType = "multipart/form-data;
boundary=" + boundaryString;
requestToServer.KeepAlive = false;
ASCIIEncoding ascii = new ASCIIEncoding();
string boundaryStringLine = "\r\n--" + boundaryString + "\r\n";
byte[] boundaryStringLineBytes = ascii.GetBytes(boundaryStringLine);
string lastBoundaryStringLine = "\r\n--" + boundaryString + "--\r\n";
byte[] lastBoundaryStringLineBytes = ascii.GetBytes(lastBoundaryStringLine);
// Get the byte array of the myFileDescription content disposition
string myFileDescriptionContentDisposition = String.Format(
"Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}",
"myFileDescription",
"A sample file description");
byte[] myFileDescriptionContentDispositionBytes
= ascii.GetBytes(myFileDescriptionContentDisposition);
string fileUrl = file;
// Get the byte array of the string part of the myFile content
// disposition
string myFileContentDisposition = String.Format(
"Content-Disposition: form-data;name=\"{0}\"; "
+ "filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n",
"myFile", Path.GetFileName(fileUrl), Path.GetExtension(fileUrl));
byte[] myFileContentDispositionBytes =
ascii.GetBytes(myFileContentDisposition);
FileInfo fileInfo = new FileInfo(fileUrl);
// Calculate the total size of the HTTP request
long totalRequestBodySize = boundaryStringLineBytes.Length * 2
+ lastBoundaryStringLineBytes.Length
+ myFileDescriptionContentDispositionBytes.Length
+ myFileContentDispositionBytes.Length
+ fileInfo.Length;
// And indicate the value as the HTTP request content length
requestToServer.ContentLength = totalRequestBodySize;
// Write the http request body directly to the server
using (Stream s = requestToServer.GetRequestStream())
{
//TIMEOUT OCCURED WHEN CALLING GetRequestStream
// Send the file description content disposition over to the server
s.Write(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
s.Write(myFileDescriptionContentDispositionBytes, 0,
myFileDescriptionContentDispositionBytes.Length);
// Send the file content disposition over to the server
s.Write(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
s.Write(myFileContentDispositionBytes, 0,
myFileContentDispositionBytes.Length);
// Send the file binaries over to the server, in 1024 bytes chunk
FileStream fileStream = new FileStream(fileUrl, FileMode.Open,
FileAccess.Read);
byte[] buffer = new byte[1024];
int bytesRead = 0;
Logger.writeToLogFileCom("writing data...");
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
s.Write(buffer, 0, bytesRead);
} // end while
fileStream.Close();
Logger.writeToLogFileCom("... finished, File closed");
// Send the last part of the HTTP request body
s.Write(lastBoundaryStringLineBytes, 0, lastBoundaryStringLineBytes.Length);
Logger.writeToLogFileCom("... finished, File closed");
} // end using
// Grab the response from the server. WebException will be thrown
// when a HTTP OK status is not returned
Logger.writeToLogFileCom("lese Response");
response = requestToServer.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string replyFromServer = responseReader.ReadToEnd();
response.Close();
if (Regex.Split(Regex.Split(replyFromServer, "content\\:RESPONSE\"\\>")[1], "\\</span\\>")[0].Equals("OK"))
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
Logger.writeToLogFileCom("Fehler im HTML Sender");
Logger.writeToLogFileCom(ex.Message);
Logger.writeToLogFileCom(ex.StackTrace);
}
finally
{
try
{
if (response != null)
{
response.Close();
}
}
catch (Exception ex) { }
}
return false;
}
I solved the problem.
I added an additional try / catch block inside the finally clause to call getResponse in every situation.
finally
{
try { response = requestToServer.GetResponse(); }
catch (Exception ex) { }
[...]
I am developing a Windows Store App using C# and I am very new at this platform (I have been primarily working on IOS and Android).
I have a simple Async method to download raw data from a remote server. It works ok except that I keep seeing random incomplete reads from the WebResponse class. It is pretty simple method and I cant figure out why it would end prematurely. The remote server is working fine ( ios/web/android fine and are retrieving data) so I am obviously doing something wrong here.
Any help will be great in figuring out this problem.
public async Task<byte[]> doGETRequestAsync(String url)
{
callSuccess = false;
byte[] responseFromServer = null;
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
WebResponse response = await request.GetResponseAsync();
using (Stream dataStream = response.GetResponseStream())
{
responseFromServer = new byte[response.ContentLength];
int readCount = await dataStream.ReadAsync(responseFromServer, 0, (int)response.ContentLength);
if (readCount != response.ContentLength)
throw new IOException("Premature end of data. Expected: " + response.ContentLength + " received: " + readCount);
}
response.Dispose();
}
catch (HttpRequestException hre)
{
Debug.WriteLine("Exception performing network call : " + hre.ToString());
}
catch (Exception e)
{
Debug.WriteLine("Exception performing network call : " + e.ToString());
}
return responseFromServer;
}
I switched to using HttpClient and HttpClientHandler and it works perfectly. This also supports storing cookies and reusing that on every call.
Here is the code that can handle both GET and POST and return the data as an array of bytes[]. If the response is a utf8 encoded string, then the bytes can be converted to string using System.Text.Encoding.UTF8.GetString(respBytes, 0, respBytes.Length);
Hope it is helpful
class Network
{
static CookieContainer cookieJar = new CookieContainer();
List<KeyValuePair<string, string>> postParameters = new List<KeyValuePair<string, string>>();
// Add post parameter before calling NetworkRequestAsync for POST calls.
public void addPostParameter(String key, String value)
{
postParameters.Add(new KeyValuePair<string, string>(key, value));
}
public async Task<byte[]> NetworkRequestAsync(String url, bool GET_REQUEST)
{
callSuccess = false;
byte[] respBytes = null;
try
{
HttpClientHandler handler = new HttpClientHandler()
{
// Use and reuse cookies in the cookiejar
CookieContainer = cookieJar
};
handler.AllowAutoRedirect = false;
handler.UseCookies = true;
HttpClient client = new HttpClient(handler as HttpMessageHandler)
{
BaseAddress = new Uri(#url)
};
HttpResponseMessage response = null;
if (GET_REQUEST)
{
response = await client.GetAsync(client.BaseAddress);
}
else
{
HttpContent content = new FormUrlEncodedContent(postParameters);
//String postparam=await content.ReadAsStringAsync();
//Debug.WriteLine("Post Param1=" + postparam);
response = await client.PostAsync(client.BaseAddress, content);
callSuccess = true;
}
respBytes = await response.Content.ReadAsByteArrayAsync();
}
catch (Exception e)
{
Debug.WriteLine("Exception performing network call : " + e.ToString());
}
return respBytes;
}
}