I am trying to create an Azure Function using NAudio / NLayer.NAudioSupport, in which I can pass in a URL (such as https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_1MG.mp3), read the bytes, and return the mp3 file converted at 128Kbps. However I'm currently getting an exception stating:
System.Private.CoreLib: Exception while executing function : ReduceMp3Bitrate. NAudio.Lame: unsupported encoding format MpegLayer3 (Parameter format).
Here's my current code (Exception occurs on Line 5):
const string linkUrl = #"https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_1MG.mp3";
var audioFile = new HttpClient().GetByteArrayAsync(linkUrl);
await using var ms = new MemoryStream(await audioFile);
var audioReader = new Mp3FileReader(ms);
await using var audioWriter = new LameMP3FileWriter(#"C:\temp\test.mp3", audioReader.Mp3WaveFormat, LAMEPreset.ABR_128);
await audioReader.CopyToAsync(audioWriter);
I think the issue is with audioReader.Mp3WaveFormat, but I'm not sure why this would be the issue, as it's returning MpegLayer3.
I've also tried running this on a .Net Framework 4.7 console application running on Windows (taking Azure Functions out the equation) and it still doesn't work.
Change the audioReader.Mp3WaveFormat to audioReader.WaveFormat (in line 5).
Explanation: As mentioned in https://github.com/naudio/NAudio/blob/master/NAudio/Wave/WaveStreams/Mp3FileReader.cs#L28 Mp3WaveFormat is NOT the output format of the Mp3FileReader stream. That is present in WaveFormat.
Related
I want to convert html code to pdf so I use SelectPDF library, so my code is:
var converter = new HtmlToPdf();
var today = DateTime.UtcNow;
var fileName = $"test - {today}";
var doc = converter.ConvertHtmlString(html);
using var ms = new MemoryStream();
ms.Position = 0;
doc.Save(ms);
var res = ms.ToArray();
doc.Close();
return File(res, "application/pdf", fileName);
I tested using localhost and everything works well, always do a fast conversion (not more than 5 seconds).
The problem starts when I publish on the server, after the method executed sometimes (not always) it returns an error 500
Failed to load resource: the server responded with a status of 500 ()
Message: "Conversion error: Navigation timeout."
Is it a way always to get a fast result? I know I can expand load time as:
converter.Options.MaxPageLoadTime = 120;
But I want to convert it fast, 2 minutes for a simple HTML to pdf conversion is to much
If it works locally and you are getting a time-out on the server sometimes, it is likely that your Html contains a file reference (e.g. javascript, css or image) that is not available to the server at the time.
Make sure external references in your html that are always accessible to your server.
I have a component library that uses JS code to generate an image as a base64 string and the image needs to be transposed to C#. The image size is larger than MaximumReceiveMessageSize.
Can I get the value of the MaximumReceiveMessageSize property in C#? I need a way to correctly split the picture into chunks, or some other way to transfer it.
My component can be used in a Wasm or Server application. I can't change the value of the MaximumReceiveMessageSize property.
Thanks
Using a stream as described in the Stream from JavaScript to .NET solved my problem.
From Microsoft docs:
In JavaScript:
function streamToDotNet() {
return new Uint8Array(10000000);
}
In C# code:
var dataReference = await JS.InvokeAsync<IJSStreamReference>("streamToDotNet");
using var dataReferenceStream = await dataReference.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
var outputPath = Path.Combine(Path.GetTempPath(), "file.txt");
using var outputFileStream = File.OpenWrite(outputPath);
await dataReferenceStream.CopyToAsync(outputFileStream);
In the preceding example: JS is an injected IJSRuntime instance. The dataReferenceStream is written to disk (file.txt) at the current user's temporary folder path (GetTempPath).
We do use MediaPlayerElement in UWP to play videos. However, occasionally (the occurance seems to be rare), the video which is working normally in any other way fails with following exception:
A valid type has not been set for this stream or a stream that it dependes on. (Exception from HRESULT
0xC00D6D60)
What can cause this exception in our case? How to prevent it?
Edit - added snippet according to RoyLi comment:
This is how we create MediaPlaybackItem.
StorageFile manifest_file = await Storage.MovieManifestFile(mi.UserGUID, mi.OrderItemGUID);
amscr = await AdaptiveMediaSource.CreateFromStreamAsync(await manifest_file.OpenReadAsync(), new Uri(mi.MPDManifestUrl), "application/dash+xml");
MediaSource converted_amscr = MediaSource.CreateFromAdaptiveMediaSource(amscr.MediaSource);
MediaPlaybackItem ampi = new MediaPlaybackItem(converted_amscr);
The video source is MPEG-DASH stream protected with PlayReady. The issue was reproduced only on some devices and it happened not just for MPEG-DASH, but also for PIFF files.
After creating the MediaPlaybackItem, we simply use it as source for MediaPlayerElement.
me.MediaPlayer.Source = ampi;
me.MediaPlayer.Play();
I have a bot created with the Microsoft Bot Framework and that uses Skype as a channel. When the user tries to speak with the bot by sending an audio using one of the mobile apps (Android or iOS) I want to be able to get the audio from the attachments and send it to the Bing Speech API in order to convert it to text.
I'm having some issues doing this, the main problem I believe is the fact that I have to send a WAV to the Bing Speech API. I read the demo in the Bot Builder repository, and in the demo there's the following code:
var audioAttachment = activity.Attachments?.FirstOrDefault(a => a.ContentType.Equals("audio/wav"));
if (audioAttachment != null)
{
using (var client = new HttpClient())
{
var stream = await client.GetStreamAsync(audioAttachment.ContentUrl);
var text = await this.speechService.GetTextFromAudioAsync(stream);
message = ProcessText(activity.Text, text);
}
}
However when I send an audio through the Skype mobile app (I'm testing with Android) I don't have an "audio/wav" file type, the file type (ContentType) comes as just "audio".
When I try to get the audio file in the Bot State Manager API using Postman (the URL looks like this: https://smba.trafficmanager.net/apis/v3/attachments/0-eus-d1-0000000000000/views/original) I get something with the content type of "application/octet-stream", and I don't know if this is an MP3, or WAV, or whatever.
The just few lines I can see inside Postman are just something like this:
ftypmp42isommp42pmoovlmvhd�_ ��_ ���#ymeta!hdlrmdta+keysmdtacom.android.version%ilstdata7.1.1�trak\tkhd�_ ��_ ��#mdia mdhd�_ ��_ ��D��,hdlrsounSoundHandle�minfsmhd$dinfdrefurl �stbl[stsdKmp4a�D'esds#ww0stts��-�stsz
I download this content to a Stream using the ReadAsStreamAsync method and pass this string to the Bing Speech API, on the following endpoint:
https://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?language=pt-BR&format=detailed
However this is what I get back:
{"RecognitionStatus":"InitialSilenceTimeout","Offset":11000000,"Duration":0}
In this case it's an audio with audible speech, and it doesn't detect the audio. As I said, I believe the problem is the file type. What is the file type used by Skype, and how can use this file to call the Bing Speech API?
What is the file type used by Skype, and how can use this file to call the Bing Speech API?
You're right, the problem is the file type. The Bing Speech Api only supports WAV/PCM format currently, if your audio file is not with this format, you'll need try to convert it to PCM.
If you want to detect if the user attachment is an audio file, you can for example modify your code like this:
var audioAttachment = activity.Attachments?.FirstOrDefault(a => a.ContentType.Contains("audio"));
Then the real problem now is to convert it to a .wav audio. For C#, you may try use the NAudio package.
May be the below snippet may help for converting to wav format required for bing. This answer may be late for you but may be for future , it may help. I had a requirement for converting mp3 to wav file for use with bing speech (converting speech to text) and hence I had to write a small piece as below. Here we use stream to pipe input from ffmpeg to bing directly (so there is no need to have intermediate file system).
const http = require('http'),
fs = require('fs'),
path = require('path');
const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('#ffmpeg-installer/ffmpeg').path;
ffmpeg.setFfmpegPath(ffmpegPath);
const stream = require('stream');
var bing = require('bingspeech-api-client/lib/client');
const bingSpeechkey = '';
var bingClient = new bing.BingSpeechClient(bingSpeechkey);
function bingUploadFromStream() {
const pass = new stream.PassThrough();
console.log('Bing upload');
bingClient.recognizeStream(pass).then(response => console.log(response.results[0].name));
return pass;
}
function speechToText(input) {
ffmpeg(input)
.format('wav')
.on('progress', (progress) => {
console.log('Processing: ' + progress.targetSize + ' KB converted');
})
.on('error', (err) => {
console.log('An error occurred: ' + err.message);
})
.on('end', () => {
console.log('Processing finished !');
})
.output(bingUploadFromStream())
.run();
}
I'm trying to use C# with the Live Connect API to upload a blank (or one that says "test") text file to SkyDrive. The code I have so far:
LiveConnectClient client = await LiveSignin();
string folderID = await getFolder(client);
client.BackgroundUploadAsync(folderID, "pins.txt", "", OverwriteOption.Rename);
where LiveSignin() is a function that handles the sign in code and returns a LiveConnectClient, and getFolder(LiveConnectClient client) is a function that gets the folder ID that I'm trying to upload to.
That code throws an error about the blank string (third parameter on the last line) having to be a "Windows.Storage.Streams.IInputStream", but I can't seem to find any documentation on how to convert a String to an IInputStream, or, for that matter, much of any documentation on "IInputStream" that I can find.
With earlier versions of the Windows Runtime/Live Connect (on another project) I had used:
byte[] byteArray = System.Text.Encoding.Unicode.GetBytes(Doc);
MemoryStream stream = new MemoryStream(byteArray);
App.client.UploadCompleted += client_UploadCompleted;
App.client.UploadAsync(roamingSettings.Values["folderID"].ToString(), docTitle.Text + ".txt", stream);
but that throws a lot of errors now (most of them because UploadAsync has been replaced with BackgroundUploadAsync).
So, is there a way to convert a string to an IInputStream, or do I not even need to use an IInputStream? If my method just doesn't work, how would one upload a blank text file to SkyDrive from a C# Metro app? (developing in Visual Studio 2012 Express on the evaluation of Windows 8 Enterprise, if that makes much of a difference)
EDIT: I finally found "Stream.AsInputStream", but now I'm getting the same error as this
An unhandled exception of type 'System.AccessViolationException'
occurred in Windows.Foundation.winmd
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt
the code now:
LiveConnectClient client = await LiveSignin();
string folderID = await getFolder(client);
Stream OrigStream = new System.IO.MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes("test"));
LiveOperationResult result = await client.BackgroundUploadAsync(folderID, "pins.txt", OrigStream.AsInputStream(), OverwriteOption.Rename);
Hi
Had same problem today and as far as I can see the only solution to this problem is to write your text into a local file first and then upload it.
My solution looks like this:
var tmpFile= await ApplicationData.Current.
LocalFolder.CreateFileAsync
("tmp.txt", CreationCollisionOption.ReplaceExisting);
using (var writer = new StreamWriter(await tmpFile.OpenStreamForWriteAsync()))
{
await writer.WriteAsync("File content");
}
var operationResult =
await client.BackgroundUploadAsync(folderId, tmpFile.Name, tmpFile,
OverwriteOption.Overwrite);