Capture audio with naudio and play with javascript - javascript

I have a client with written c# and a server with written java. I capture audio and send with socket to the server and server send with web socket to the browser and want to play with browser. But when i try browser says Uncaught (in promise) DOMException: Failed to load because no supported source was found.
Could you help me?
private static void Recordwav()
{
waveInEvent = new WaveInEvent();
int devicenum = 0;
for (int i = 0; i < WaveIn.DeviceCount; i++)
{
if (WaveIn.GetCapabilities(i).ProductName.Contains("icrophone"))
devicenum = i;
}
waveInEvent.DeviceNumber = devicenum;
waveInEvent.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(devicenum).Channels);
waveInEvent.DataAvailable += new EventHandler<WaveInEventArgs>(VoiceDataAvailable);
waveInEvent.StartRecording();
}
private static void VoiceDataAvailable(object sender, WaveInEventArgs e)
{
JObject jObject = new JObject();
jObject["voice"] = Convert.ToBase64String(e.Buffer);
byte[] messageByte = Encoding.ASCII.GetBytes(jObject.ToString().Replace("\r\n", "") + "\n");
socket.Send(messageByte);
}
$scope.socket.onmessage = function (response)
{
var data = JSON.parse(response.data);
if(data.id == $scope.id) {
if(data.voice) {
var voice = data.voice;
var sound = new Audio("data:audio/wav;base64," + voice);
sound.play();
}
}
};

you're just sending raw samples, not a properly formatted WAV file. You'd need to use WaveFileWriter to write to a MemoryStream (wrapped in an IgnoreDisposeStream) dispose the WaveFileWriter and then access the MemoryStream underlying byte array. Also you're not taking into account BytesRecorded.
Even if you get this working, I suspect you'll get very choppy audio, as each WAV file will be a few hundred ms, and they won't necessarily play perfectly one after the other.

Related

Trying to send a compressed base64 encoded string from JS to AS3 via Websocket. Problem with uncompressing

Hello and to a very happy and more healthy 2021!
I am setting up a small communication interface between a JS client and a AS3 Server based on the Websockets protocol.
For various reasons I need to compress and base64 encode the payloads.
From AS3 to JS everything works like this (using https://github.com/blooddy/blooddy_crypto to handle the Base64 en/decryption ) :
function encodeMessage(message:String):String{
var rawData:ByteArray=new ByteArray()
rawData.writeUTFBytes( encodeURIComponent(message) );
rawData.compress();
var b64 = Base64.encode(rawData);
return b64;
};
decoding in JS with pako for inflation (https://github.com/nodeca/pako):
decodePayload(payload){
let rawfile = (atob(payload));
var bytes = [];
for (var fileidx = 0; fileidx < rawfile.length; fileidx++) {
var abyte = rawfile.charCodeAt(fileidx) & 0xff;
bytes.push(abyte);
}
var plain = pako.inflate(bytes);
var enc = "";
for (var i = 0; i < plain.length; i++) {
enc += String.fromCharCode(plain[i]);
}
return decodeURIComponent(enc);
}
now the other direction creates some problems:
in JS I use:
encodeMessage(message){
let enc = encodeURIComponent(message)
let zlib = pako.deflate(enc)
let b64 = btoa(zlib);
return b64;
}
but then I am running into issues on the AS3 side:
function decodePayload(payload:String){
var ba:ByteArray = Base64.decode(payload);
//this is where the error happens
ba.uncompress();
}
the error is a "Error: Error #2058: There was an error decompressing the data."
I suspect that the bytearry i receive from pako.deflate is different from what AS3 is using?
Any pointers welcome!
here is the solution - a stupid little oversight of course ;)
in the encode function in JS the Uint8Array needs to be converted into a BinaryString before it gets Base64 encoded:
function encodeMessage(message){
let enc = encodeURIComponent(message);
let zlib = pako.deflate(enc);
let binstring = convertUint8ArrayToBinaryString(zlib);
let b64 = btoa(binstring);
return b64;
};
function convertUint8ArrayToBinaryString(u8Array) {
var i, len = u8Array.length, b_str = "";
for (i=0; i<len; i++) {
b_str += String.fromCharCode(u8Array[i]);
}
return b_str;
}
Then all is well in Roswell.
It's not obvious if your AS3 code is used in just an SWF file or you have an AIR project.
If making an AIR project:
Try using uncompress.apply... (code not yet tested).
//# this is where the error happens
//ba.uncompress();
//# try this..
ba.uncompress.apply(ba, ["deflate"]);
If making an SWF project:
When I needed Deflate algorithm inside an SWF running on browser I used a port of Zlib.
Get as3zlib at: https://github.com/BenV/as3zlib (is a port of Zlib for Java).
note: While in JS it's better to make local vars rather than global, this a quirk of JavaScript
and actually in most C-like languages (Java, C#, AS3, etc) this is opposite, a global variable is less expensive than constantly making local vars every time the function is called.
Here is a usage example:
//# import Zlib Class
import Zlib;
//# setup global vars
var zlibdecomp :Zlib;
var ba :ByteArray = new ByteArray;
var decoded_BA :ByteArray = new ByteArray;
//# try Deflate algo...
function decodePayload(payload:String)
{
zlibdecomp = new Zlib;
ba.clear(); //in case it already has data from a prev decode
//# all code below can be done in this one line
//ba = zlibdecomp.uncompress( Base64.decode(payload) );
ba = Base64.decode(payload);
//# this is where the error happens...
//ba.uncompress();
//# try this...
decoded_BA = zlibdecomp.uncompress( ba ); //inflate to original big from small/compressed
//ba = decoded_BA; //if this way of updating is needed
}

Download an xlsx file with reactJS: Excel can not open file

I'm trying to download an xlsx file with reactJS but i'm receiving this message when i try to open my file after download:
"Excel can not open file 'file.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the file format"
Here's the frontend code:
const REST_DOWNLOAD_URL = REST_URL + '/token';
Rest.ajaxPromise('GET', REST_DOWNLOAD_URL).then(function (res) {
var FILE_URL = "/supermarket/token/" + res;
Rest.ajaxPromise('GET', FILE_URL).then(function (my_file) {
let blob = new Blob([my_file._body], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' });
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, 'file.xlsx');
} else {
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.setAttribute('download', 'file.xlsx');
document.body.appendChild(link);
link.download = '';
link.click();
document.body.removeChild(link);
}
});
});
Why am i getting this error? Please somebody help me, i'm stuck on this for 3 weeks
[EDIT 1]
The file that i'm trying to download is build on backend, basically i get the values on database and use the Apache poi workbook to create the excel sheet. I will show you the mainly parts of the code:
1) This method is called by frontend on the first GET requisition of frontend and aims to prepare the file before the download. Is very simple, just create a token (buildToken()) and associate a temp file with this token (createTempFile(randomBackendToken)). The temp file is filled with what i get on my database (createFile(os))
#RequestMapping(value = "/token", method = RequestMethod.GET)
public String returnToken() throws IOException {
String randomBackendToken = tokenGenerator.buildToken();
OutputStream os = tokenGenerator.createTempFile(randomBackendToken);
tokenGenerator.createFile(os);
return randomBackendToken;
}
2) The method where i create the temp file:
public OutputStream createTempFile(String randomBackendToken) throws IOException {
OutputStream os = null;
File file = File.createTempFile(randomBackendToken, ".xlsx");
os = new FileOutputStream(file);
return os;
}
3) The method where i receive the empty temp file and fills with my data on database:
public void createFile(OutputStream os) throws IOException {
List<Supermakets> supermarkets = service.findAllSupermarkets();
Workbook workbook = writeExcel.createSheet(supermarkets);
workbook.write(os);
IOUtils.closeQuietly(os);
}
4) My WriteExcel Class that build the xlsx file:
private static String[] columns = {"Code", "Name", "Type"};
public Workbook createSheet(List<Supermarket> supermarkets) throws IOException {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("file");
[....]
// Row for Header
Row headerRow = sheet.createRow(0);
// Header
for (int col = 0; col < columns.length; col++) {
Cell cell = headerRow.createCell(col);
cell.setCellValue(columns[col]);
cell.setCellStyle(headerCellStyle);
}
//Content
int rowIdx = 1;
for (Supermarket supermarket : supermarkets) {
Row row = sheet.createRow(rowIdx++);
row.createCell(0).setCellValue(supermarket.getCode());
row.createCell(1).setCellValue(supermarket.getName());
row.createCell(2).setCellValue(supermarket.getType());
}
return workbook;
}
So, this all above is just for the first GET requisition. I make another one and the method below holds the second requisition. I just verify the token that the frontend returns for me and them, based on the validation, i allow the download of the file that i created on the previous step:
public void export(#PathVariable(value = "frontendToken") String frontendToken, HttpServletResponse response) throws IOException {
if (StringUtils.isNotBlank(frontendToken)) {
String tmpdir = System.getProperty("java.io.tmpdir");
File folder = new File(tmpdir);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
boolean fileIsValid = tokenGenerator.validateToken(frontendToken, listOfFiles[i]);
if (fileIsValid) {
InputStream input = new FileInputStream(listOfFiles[i]);
OutputStream output = response.getOutputStream();
int data = input.read();
while (data != -1) {
output.write(data);
data = input.read();
}
input.close();
output.flush();
output.close();
String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.setContentType(mimeType);
listOfFiles[i].delete();
}
}
}
}
}
And that's all that i'm doing. Can't find what's wrong or what i'm missing. When i press F12 on my navigator to see the response of the request, shows for me something encoded, like:
PK#SM_rels/.rels­’ÁjÃ0†_ÅèÞ8í`ŒQ·—2èmŒî4[ILbËØÚ–½ýÌ.[Kì($}ÿÒv?‡I½Q.ž£uÓ‚¢hÙùØx>=¬î#ÁèpâH"Ã~·}¢
Any suspicions of what can be?
guys!
The problem was: my binary data was being converted for string by javascript and this was breaking my excel file. i solved my problem converting my binary data on backend to text and then on frontend i make the inverse. The following links helped me:
java convert inputStream to base64 string
Creating a Blob from a base64 string in JavaScript
Thank you for everyone that tried to help. I hope my question can help others

base64 to image filename [duplicate]

Here is my code:
protected void SaveMyImage_Click(object sender, EventArgs e)
{
string imageUrl = Hidden1.Value;
string saveLocation = Server.MapPath("~/PictureUploads/whatever2.png") ;
HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
WebResponse imageResponse = imageRequest.GetResponse();
Stream responseStream = imageResponse.GetResponseStream();
using (BinaryReader br = new BinaryReader(responseStream))
{
imageBytes = br.ReadBytes(500000);
br.Close();
}
responseStream.Close();
imageResponse.Close();
FileStream fs = new FileStream(saveLocation, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
try
{
bw.Write(imageBytes);
}
finally
{
fs.Close();
bw.Close();
}
}
}
The top imageUrl declartion is taking in a Base64 image string, and I want to convert it into an image. I think my set of code only works for images like "www.mysite.com/test.jpg" not for a Base64 string. Anybody have some suggestions? Thanks!
Here is an example, you can modify the method to accept a string parameter. Then just save the image object with image.Save(...).
public Image LoadImage()
{
//data:image/gif;base64,
//this image is a single pixel (black)
byte[] bytes = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==");
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
It is possible to get an exception A generic error occurred in GDI+. when the bytes represent a bitmap. If this is happening save the image before disposing the memory stream (while still inside the using statement).
You can save Base64 directly into file:
string filePath = "MyImage.jpg";
File.WriteAllBytes(filePath, Convert.FromBase64String(base64imageString));
Here is what I ended up going with.
private void SaveByteArrayAsImage(string fullOutputPath, string base64String)
{
byte[] bytes = Convert.FromBase64String(base64String);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
image.Save(fullOutputPath, System.Drawing.Imaging.ImageFormat.Png);
}
I would suggest via Bitmap:
public void SaveImage(string base64)
{
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
{
using (Bitmap bm2 = new Bitmap(ms))
{
bm2.Save("SavingPath" + "ImageName.jpg");
}
}
}
Here is working code for converting an image from a base64 string to an Image object and storing it in a folder with unique file name:
public void SaveImage()
{
string strm = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
//this is a simple white background image
var myfilename= string.Format(#"{0}", Guid.NewGuid());
//Generate unique filename
string filepath= "~/UserImages/" + myfilename+ ".jpeg";
var bytess = Convert.FromBase64String(strm);
using (var imageFile = new FileStream(filepath, FileMode.Create))
{
imageFile.Write(bytess, 0, bytess.Length);
imageFile.Flush();
}
}
In my case it works only with two line of code. Test the below C# code:
String dirPath = "C:\myfolder\";
String imgName = "my_mage_name.bmp";
byte[] imgByteArray = Convert.FromBase64String("your_base64_string");
File.WriteAllBytes(dirPath + imgName, imgByteArray);
That's it. Kindly up vote if you really find this solution works for you. Thanks in advance.
In a similar scenario what worked for me was the following:
byte[] bytes = Convert.FromBase64String(Base64String);
ImageTagId.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(bytes);
ImageTagId is the ID of the ASP image tag.
If you have a string of binary data which is Base64 encoded, you should be able to do the following:
byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
You should be able to write the resulting array to a file.
public bool SaveBase64(string Dir, string FileName, string FileType, string Base64ImageString)
{
try
{
string folder = System.Web.HttpContext.Current.Server.MapPath("~/") + Dir;
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
string filePath = folder + "/" + FileName + "." + FileType;
File.WriteAllBytes(filePath, Convert.FromBase64String(Base64ImageString));
return true;
}
catch
{
return false;
}
}
Using MemoryStream is not a good idea and violates a specification in MSDN for Image.FromStream(), where it says
You must keep the stream open for the lifetime of the Image.
A better solution is using ImageConverter, e.g:
public Image ConvertBase64ToImage(string base64)
=> (Bitmap)new ImageConverter().ConvertFrom(Convert.FromBase64String(base64));
In NetCore 6.0, you can use HttpClient and the async methods in the new File class.
The implementation is very simple:
static async Task DownloadFile(string imageUrl, string pathToSave)
{
var content = await GetUrlContent(url);
if (content != null)
{
await File.WriteAllBytesAsync(pathToSave, content);
}
}
static async Task<byte[]?> GetUrlContent(string url)
{
using (var client = new HttpClient())
using (var result = await client.GetAsync(url))
return result.IsSuccessStatusCode ? await result.Content.ReadAsByteArrayAsync():null;
}
Usage:
await DownloadFile("https://example.com/image.jpg", #"c:\temp\image.jpg");

Calculate SHA-1 checksum of local html5 video file using JavaScript

When a video on my local storage—let's say it's currently located at file:///home/user/video.m4v—is opened by dragging it into a new tab in Chrome, how can I calculate the SHA-1 checksum for the file using JavaScript?
Purpose:
I am planning to write a Chrome extension which will store the calculated checksum of videos (files with extensions matching a pattern) as localStorage objects in order to save the playback position of video upon tab close and then restore it when the file is loaded again, even if the location or filename of the video is changed.
You need a crypto library for this. A well known one is Google CryptoJS.
I found this as an specific example for your task: https://gist.github.com/npcode/11282867
After including the crypto-js source:
function sha1sum() {
var oFile = document.getElementById('uploadFile').files[0];
var sha1 = CryptoJS.algo.SHA1.create();
var read = 0;
var unit = 1024 * 1024;
var blob;
var reader = new FileReader();
reader.readAsArrayBuffer(oFile.slice(read, read + unit));
reader.onload = function(e) {
var bytes = CryptoJS.lib.WordArray.create(e.target.result);
sha1.update(bytes);
read += unit;
if (read < oFile.size) {
blob = oFile.slice(read, read + unit);
reader.readAsArrayBuffer(blob);
} else {
var hash = sha1.finalize();
console.log(hash.toString(CryptoJS.enc.Hex)); // print the result
}
}
}
I wouldn't recommend to calculate a hash over the whole video file as it can be pretty resource consuming depending on the file size. Maybe you can use just the meta information or reconsider about the filename and filepath again?
Web APIs have progressed considerably since I asked this question. Calculating a hex digest is now possible using the built-in SubtleCrypto.digest().
TS Playground link
function u8ToHex (u8: number): string {
return u8.toString(16).padStart(2, '0');
}
/** Ref: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#supported_algorithms */
const supportedAlgorithms = [
'SHA-1',
'SHA-256',
'SHA-384',
'SHA-512',
] as const;
type SupportedAlgorithm = typeof supportedAlgorithms[number];
type Message = string | Blob | BufferSource;
async function hexDigest (
algorithm: SupportedAlgorithm,
message: Message,
): Promise<string> {
let buf: BufferSource;
if (typeof message === 'string') buf = new TextEncoder().encode(message);
else if (message instanceof Blob) buf = await message.arrayBuffer();
else buf = message;
const hash = await crypto.subtle.digest(algorithm, buf);
return [...new Uint8Array(hash)].map(u8ToHex).join('');
}

Can I use JS in silverlight app?

I have Silverlight app. For example I want add some JS script which can interact with SL app. For example I want add google map use JS api. Can I do this, But I must send some data from SL to JS to add pins on map, draw figures on map ect.
If you are using Windows Phone and you dont mind that part of the xaml to be a webview yo can.
First add a webview to the xaml
<phone:WebBrowser Name="webView" BorderThickness="0" BorderBrush="Transparent" IsScriptEnabled="True"
ScriptNotify="WebBrowser_ScriptNotify" />
Then you have to bind the webview with the load event and then saveg files to storage and load your html and js files
webView.Loaded += WebBrowser_OnLoaded;
private void WebBrowser_OnLoaded(object sender, RoutedEventArgs e)
{
SaveFilesToIsoStore();
chatView.Navigate(new Uri("Assets/HtmlContent/index.html", UriKind.Relative));
}
private void SaveFilesToIsoStore()
{
//These files must match what is included in the application package,
//or BinaryStream.Dispose below will throw an exception.
string[] files = {
"Assets/HtmlContent/index.html",
"Assets/HtmlContent/js/libs/jquery-1.11.0.min.js", "Assets/HtmlContent/js/pagejs.js", "Assets/HtmlContent/css/style.css"
};
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
if (false == isoStore.FileExists(files[0]))
{
foreach (string f in files)
{
StreamResourceInfo sr = Application.GetResourceStream(new Uri(f, UriKind.Relative));
using (BinaryReader br = new BinaryReader(sr.Stream))
{
byte[] data = br.ReadBytes((int)sr.Stream.Length);
SaveToIsoStore(f, data);
}
}
}
}
private void SaveToIsoStore(string fileName, byte[] data)
{
string strBaseDir = string.Empty;
string delimStr = "/";
char[] delimiter = delimStr.ToCharArray();
string[] dirsPath = fileName.Split(delimiter);
//Get the IsoStore.
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
//Re-create the directory structure.
for (int i = 0; i < dirsPath.Length - 1; i++)
{
strBaseDir = System.IO.Path.Combine(strBaseDir, dirsPath[i]);
isoStore.CreateDirectory(strBaseDir);
}
//Remove the existing file.
if (isoStore.FileExists(fileName))
{
isoStore.DeleteFile(fileName);
}
//Write the file.
using (BinaryWriter bw = new BinaryWriter(isoStore.CreateFile(fileName)))
{
bw.Write(data);
bw.Close();
So on the js you have to talk to the c# like this
function sendMessageToCodeBehind(someData) {
window.external.notify(JSON.stringify({ method: 'AddMessage', data: someData }));
}
On the code behind you would recibe the messages from the webview like this:
private void WebBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
var example = new { method = string.Empty, data = new object() };
var obj = JsonConvert.DeserializeAnonymousType(e.Value, example);
switch (obj.method) {
case "methodName":
}
}
And you would send back messages to the js like this
webView.InvokeScript("jsMethodName", JsonConvert.SerializeObject(new { Message = "some json message" }));

Categories