I'm having problem with the encode of speech input for Amazon Lex.
If i assign InputStream as null, it works, i receive the default voice answer from Lex : "How can i help you"
var amazonLexClient = new AmazonLexClient("APPID", "APPSECRET", Amazon.RegionEndpoint.USEast1);
var amazonPostRequest = new Amazon.Lex.Model.PostContentRequest();
var amazonPostResponse = new Amazon.Lex.Model.PostContentResponse();
amazonPostRequest.BotAlias = "BookTrip";
amazonPostRequest.BotName = "BookTrip";
amazonPostRequest.ContentType = "audio/l16; rate=16000; channels=1";
amazonPostRequest.UserId = "user";
amazonPostRequest.InputStream = null;
amazonPostResponse = await amazonLexClient.PostContentAsync(amazonPostRequest);
If i try to send a recorded voice "How are you" using the encode (required by Lex : 16KHz, 8bits, 1 channel) below
var amazonLexClient = new AmazonLexClient("APPID", "APPSECRET", Amazon.RegionEndpoint.USEast1);
var amazonPostRequest = new Amazon.Lex.Model.PostContentRequest();
var amazonPostResponse = new Amazon.Lex.Model.PostContentResponse();
amazonPostRequest.BotAlias = "BookTrip";
amazonPostRequest.BotName = "BookTrip";
amazonPostRequest.ContentType = "audio/l16; rate=16000; channels=1";
amazonPostRequest.UserId = "user";
amazonPostRequest.InputStream = new MemoryStream();
WaveFormat target = new WaveFormat(16000, 8, 1);
WaveStream streamIn = new WaveFileReader("F:\\Whatever.wav");
WaveFormatConversionStream str = new WaveFormatConversionStream(target, streamIn);
WaveFileWriter.WriteWavFileToStream(amazonPostRequest.InputStream, str);
amazonPostResponse = await amazonLexClient.PostContentAsync(amazonPostRequest);
Then it doesn't work, after about 20~25s Lex server will return null.
Amazon.Runtime.AmazonUnmarshallingException: 'Error unmarshalling response back from AWS.'
NullReferenceException: Object reference not set to an instance of an object.
Can anyone tell me how to encode a wav file to make it work with Amazon Lex?
Btw im using Visual Studio 2017, C# with NAudio library.
Amazon Lex expects the audio to be in PCM or Opus format (read this documentation for more details). You can refer this AI blog post from Amazon to get more information on how to PCM encode your wav audio.
There seems to be some kind of problem inside the AWSSDk for c# - what's happened is that the Lex service has returned a plain-text error message, and the SDK is trying to parse it as JSON. Sometimes you can dig into the exception details and find that raw response, or just use Fiddler.
Related
I'm trying to create a QR barcode in .NET using IronBarcode.
I'm following their tutorial for writing binary data, but it isn't working working with Arabic text for some reason. It works great with any English that I input, but with Arabic the console output is ?????. I've tried UTF8, UTF7 but nothing seems to be working.
Tutorial:
https://ironsoftware.com/csharp/barcode/tutorials/csharp-qr-code-generator/#reading-and-writing-binary-data
My code is:
using IronBarCode;
var Msg = "مرحبا";
byte[] BinaryData = System.Text.Encoding.UTF8.GetBytes(Msg);
var bitmap = IronBarCode.QRCodeWriter.CreateQrCode(BinaryData,500, IronBarCode.QRCodeWriter.QrErrorCorrectionLevel.Highest).ToBitmap();
var barcodeResult = IronBarCode.BarcodeReader.ReadASingleBarcode(bitmap);
var stringResult = System.Text.Encoding.UTF8.GetString(barcodeResult.BinaryValue);
Console.WriteLine(stringResult) // outputs '?????'
Please can someone advise what I'm missing?
var Msg = "هذا لا يعمل";
byte[] BinaryData = System.Text.Encoding.UTF8.GetBytes(Msg);
var bitmap = IronBarCode.QRCodeWriter.CreateQrCode(BinaryData, 500, IronBarCode.QRCodeWriter.QrErrorCorrectionLevel.Highest).ToBitmap();
var barcodeResult = IronBarCode.BarcodeReader.ReadASingleBarcode(bitmap);
var stringResult =
System.Text.Encoding.UTF8.GetString(barcodeResult.BinaryValue);
// stringResult is "هذا لا يعمل"
The issue you are seeing is that Console.WriteLine doesn’t support Arabic characters in Visual Studio. It prints "?????" for all non-Roman characters.
You can verify the correct result by saving to file, or putting in a debugging breakpoint and hover over the variable in Visual Studio.
This video explains the issue, and also has a work-around:
https://m.youtube.com/watch?v=rTqBnJ8HrSc
Console.OutputEncoding = System.Text.Encoding.Unicode;
I'm using the AWS .NET-SDK for sending SMS messages with the AWS SNS service. So far, so good; but when I use line breaks, I see the ? char at this point before the line break begins in the SMS. After that character, the line break is added as expected. Is there any possibility to get a line break without this ? character?
I have also tried following:
StringBuilder.AppendLine,
"\\n",
"\\r\\n",
#"\n",
#"\r\n",
Environment.NewLine
And encoding the string into UTF-8.
Example which doesn't work:
// Create message string
var sb = new StringBuilder();
sb.AppendLine("Line1.");
sb.Append("Line2.\\n");
sb.AppendLine(Environment.NewLine);
sb.Append(#"Line4\n");
// Encode into UTF-8
var utf8 = UTF8Encoding.UTF8;
var stringBytes = Encoding.Default.GetBytes(sb.ToString());
var decodedString = utf8.GetString(stringBytes);
var message = decodedString;
// Create request
var publishRequest = new PublishRequest
{
PhoneNumber = "+491234567890",
Message = message,
Subject = "subject",
MessageAttributes = "Promotional"
};
// Send SMS
var response = await snsClient.PublishAsync("topic", message, "subject");
Simply remove all attempts to encode the string. .NET strings are Unicode, specifically UTF16 already. PublishAsync expects a .NET string, not UTF8 bytes.
As for why this error occurs, it's because the code converts the string into bytes using the local machine's codepage and then tries to read those bytes as if they were UTF8, which they aren't - using UTF8 as a system codepage is a beta feature on Windows 10 which breaks a lot of applications.
The newline character for SMS is \n. Environment.NewLine returns \r\n unless you use .NET Core on Linux. StringBuilder.AppendLine uses Environment.NewLine so you can't use it.
You shouldn't need anything more than String.Join to combine multiple lines into a single message:
var message=String.Join("\n",lines);
If you need to use a StringBuilder, use AppendFormat to append a line with the \n character at the end, eg :
builder.AppendFormat("{0}\n",line);
Update
I was able to send an SMS containing newlines with this code:
var region = Amazon.RegionEndpoint.EUWest1;
var snsClient = new AmazonSimpleNotificationServiceClient(region);
var sb = new StringBuilder()
.Append("Line1.\n")
.Append("Line2.\n")
.Append("Line4\n");
var message = sb.ToString();
// Create request
var publishRequest = new PublishRequest
{
PhoneNumber = phone,
Message = message,
};
// Send SMS
var response = await snsClient.PublishAsync(publishRequest);
The message I received contained :
Line1.
Line2.
Line4.
I decided to get fancy and changed the last line to :
.Append("Line4ΑΒΓ£§¶\n");
I received this text without problems too
In the following code i want to use a predefined protobuf message in c#. I found that I was able to write and use the method to take a method that has been created and make a byte[]:
ContainerMessage containerMessage = new ContainerMessage();
containerMessage.Type = CommandType.Connect;
containerMessage.Connect = new Connect();
containerMessage.Connect.ClientName = "TemporaryClientName";
byte[] stream = new byte[containerMessage.CalculateSize()];
using (Google.Protobuf.CodedOutputStream outstream = new Google.Protobuf.CodedOutputStream(stream))
{
containerMessage.WriteTo(outstream);
}
This works as expected and i can inspect the message and the values are as expected as are the values in the byte[]. But if I try to Deserialize even this simple byte[] that i have just created:
using (Google.Protobuf.CodedInputStream instream = new Google.Protobuf.CodedInputStream(stream))
{
instream.ReadMessage(containerMessage);
}
It fails with:
An unhandled exception of type 'Google.Protobuf.InvalidProtocolBufferException' occurred in Google.Protobuf.dll
Additional information: Protocol message contained an invalid tag (zero).
Is this way of deserializing from a byte[] correct for protobuf?
The Protobuf Definition is:
message ContainerMessage {
CommandType type = 1;
bool commandSuccess = 2;
oneof message {
Connect connect = 3;
}
}
enum CommandType {
START = 0;
CONNECT = 2;
}
message Connect {
string ClientName = 1;
uint32 PushPullPort = 2;
}
And the CS file is generated with the command line:
protoc.exe -I=%CD% --csharp_out=..\GeneratedCsMessaging\ Connect.proto
The CodedOutputStream and CodedInputStream are mainly intended to be used by the compiled proto classes. The API for CodedOutputStream states such and mentions that if you want to have manually-written code calling either of both classes you need to use their WriteTag method before each value.
However, since you want to use the Google Protobuf for serializing and parsing any System.IO.Stream will do the job just like intended. This is very well documented and described in the Parsing and serialization section of the Protocol Buffer Basics for C#. The examples which can be found in Google Protobuf's Github can be quite helpful for getting the hang of Google Protobuf quickly. There you can see that a MemoryStream is used to serialize the object while the Parse.ParseFrom method can be used to parse an object out of the serialized data.
As you've mentioned in the comments to your question using Google.Protobuf; is an essential part to be able to use Google Protobuf's features.
EDIT: A sample usage in your case could look something like this
byte[] serializedBytes;
ContainerMessage containerMessage = new ContainerMessage()
{
Connect = new Connect()
{
ClientName = "TemporaryClientName",
},
Type = CommandType.Connect,
};
using( MemoryStream stream = new MemoryStream())
{
containerMessage.WriteTo(stream);
serializedBytes = stream.ToArray();
}
ContainerMessage parsedCopy = ContainerMessage.Parser.ParseFrom(serializedBytes);
I am a BLE newbie. I am using my Raspberry Pi 3, running Windows 10 Iot Core, to send some advertisement packets.
When sending only the Manufacturer Data, it works perfectly fine. But when I try to send data in Data Section, it gives me the following error.
The data is invalid. Invalid advertisement payload detected
Here is the code
Using only Manufacturer Data
private void StartPublish()
{
string data = "SHASHWAT";
DataWriter writer = new DataWriter();
writer.WriteInt32(data.Length);
writer.WriteString(data);
var adv = new BluetoothLEAdvertisement();
var manufacturerData = new BluetoothLEManufacturerData(
0x0006, writer.DetachBuffer());
adv.ManufacturerData.Add(manufacturerData);
var publisher = new BluetoothLEAdvertisementPublisher(adv);
publisher.Start();
}
Using Data Section along with Manufacturer Data
private void StartPublishWithDataSection()
{
string data = "SHASHWAT";
DataWriter writer = new DataWriter();
writer.WriteInt32(data.Length);
writer.WriteString(data);
var adv = new BluetoothLEAdvertisement();
var manufacturerData = new BluetoothLEManufacturerData(
0x0006, writer.DetachBuffer());
adv.ManufacturerData.Add(manufacturerData);
DataWriter writer2 = new DataWriter();
writer2.WriteString("Hello Shashwat");
var dataSection = new BluetoothLEAdvertisementDataSection();
dataSection.Data = writer2.DetachBuffer();
adv.DataSections.Add(dataSection);
var publisher = new BluetoothLEAdvertisementPublisher(adv);
publisher.Start();
}
This throws invalid data exception.
Please let me know if I am doing something wrong.
Any help would be appreciated.
The reason of this exception is advertisement payload length exceeds the limitation(official state this value is ~20 bytes). You can check here.
Based on my tests, the maximum length of the advertisement payload is 25 bytes including BluetoothLEManufacturerData and BluetoothLEAdvertisementDataSection.
The SendGrid API docs specify you can add attachments from a Stream. The example it gives uses a FileStream object.
I have some blobs in Azure Storage which I'd like to email as attachments. To achieve this I'm trying to use a MemoryStream:
var getBlob = blobContainer.GetBlobReferenceFromServer(fileUploadLink.Name);
if(getBlob != null)
{
// Get file as a stream
MemoryStream memoryStream = new MemoryStream();
getBlob.DownloadToStream(memoryStream);
emailMessage.AddAttachment(memoryStream, fileUploadLink.Name);
}
emailTransport.Deliver(emailMessage);
It sends fine but when the email arrives, the attachment appears to be there but it's actually empty. Looking at the email source, there is no content for the attachment.
Is using a MemoryStream a known limitation when using the SendGrid C# API to send attachments? Or should I be approaching this in some other way?
You probably just need to reset the stream position back to 0 after you call DownloadToStream:
var getBlob = blobContainer.GetBlobReferenceFromServer(fileUploadLink.Name);
if (getBlob != null)
{
var memoryStream = new MemoryStream();
getBlob.DownloadToStream(memoryStream);
memoryStream.Seek(0,SeekOrigin.Begin); // Reset stream back to beginning
emailMessage.AddAttachment(memoryStream, fileUploadLink.Name);
}
emailTransport.Deliver(emailMessage);
You might want to check who cleans up the stream as well and if they don't you should dispose of it after you've called Deliver().
According to their API, they have implemented void AddAttachment(Stream stream, String name).
You are probably using a MemoryStream which you have written to before. I suggest resetting the position inside the stream to the beginning, like:
memoryStream.Seek(0, SeekOrigin.Begin);
I ended up with the following which fixed the issue for me:
fileByteArray = new byte[getBlob.Properties.Length];
getBlob.DownloadToByteArray(fileByteArray, 0);
attachmentFileStream = new MemoryStream(fileByteArray);
emailMessage.AddAttachment(attachmentFileStream, fileUploadLink.Name);
The thread is a bit old, but I use a varient with NReco PDF converter:
private async Task SendGridasyncBid(string from, string to, string displayName, string subject, **byte[] PDFBody**, string TxtBody, string HtmlBody)
{
...
var myStream = new System.IO.MemoryStream(**PDFBody**);
myStream.Seek(0, SeekOrigin.Begin);
myMessage.AddAttachment(myStream, "NewBid.pdf");
...
}
convert the html to pdf and return it instead of writing it for download...
private byte[] getHTML(newBidViewModel model)
{
string strHtml = ...;
HtmlToPdfConverter pdfConverter = new HtmlToPdfConverter();
pdfConverter.CustomWkHtmlArgs = "--page-size Letter";
var pdfBytes = pdfConverter.GeneratePdf(strHtml);
return **pdfBytes**;
}
I am not sure how efficient this is, but it is working for me and I hope it helps someone else get their attachments figured out.