Blazor 和 Superpowered Web Audio SDK,如何 return arrayBuffer 到 C#
Blazor and the Superpowered Web Audio SDK, how to return the arrayBuffer to C#
首先,对于这样一个悬而未决的问题,我们深表歉意。我认为这个问题来自于对 WASM 和 .Net 中 JSInterop 的本质缺乏理解。
我只是想联系任何在 Blazor 中使用过 Superpowered Web Audio SDK 的人,了解他们是如何使用它的,因为我正在为 JSInterop 苦苦挣扎,我觉得我没有让事情变得更难使用基于 Javascript 的框架。
我已经使用 C# class 设置了一个 Blazor 客户端 Web 程序集项目,它作为一个非常简单的 Javascript 文件的接口来下载和解码音频文件:
public class AudioTest
{
[Inject]
IJSRuntime js;
DotNetObjectReference<AudioTest> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async void DownloadAndDecode(string url)
{
byte[] buffer = await superpoweredModule.InvokeAsync<byte[]>("downloadAndDecode", url, objRef);
Console.WriteLine(buffer.Length);
}
[JSInvokable]
public void ReceiveDecodedBuffer(string url, byte[] buffer)
{
Console.WriteLine(buffer);
}
}
调用 C# 方法 DownloadAndDecode() 时,它将自身的引用传递给 javascript 函数 downloadAndDecode() 以在缓冲区准备就绪时用于回调:
import { SuperpoweredTrackLoader } from '/superpowered/SuperpoweredTrackLoaderModule.js';
export async function downloadAndDecode(url, dotNetRef) {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
await dotNetRef.invokeMethodAsync('ReceiveDecodedBuffer', url, message.SuperpoweredLoaded.buffer);
});
}
但是,这会导致在转换 base64 缓冲区时出现运行时错误。我试过在发送之前从 base64 转换音频缓冲区(这太慢了)。我还尝试了未编组的 Javascript 调用,但它们仅支持同步调用。在 C#、JS 之间传递时必须转换缓冲区,反之亦然。
我计划在 C# 和 JS 上处理音频缓冲区。但感觉我应该离开 JS 端并在那里管理缓冲区。有人对此有建议吗?或者我应该把它留在 Javascript 一边吗?或者简单地更改我的 design/approach 和框架以支持 Superpowered 库。
安装 .net 6 preview 6 并再次创建我的项目提供了一种在 Blazor 和 JavaScript 之间传递大字节 [] 的快速有效方法。在不创建新项目的情况下,当 returning/sending byte[] .
时会导致奇怪的行为
这是我的源代码示例。该代码需要 Superpowered Web Audio 库。
ByteArrayTest.razor
<h3>ByteArrayTest</h3>
<button @onclick="SendNetBytes">Send bytes to javascript</button>
<button @onclick="GetJavaBytes">Get bytes from javascript</button>
<button @onclick="DownloadAndDecode">Download And Decode .mp3</button>
<button @onclick="DownloadAndDecodeUsingCallback">Download And Decode .mp3 Using Callback</button>
@code {
[Inject]
IJSRuntime jsRuntime { get; set; }
IJSObjectReference module;
DotNetObjectReference<ByteArrayTest> objRef;
protected override async Task OnInitializedAsync()
{
objRef = DotNetObjectReference.Create(this);
module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "/byteArray.js");
}
public async ValueTask DisposeAsync()
{
objRef.Dispose();
await module.DisposeAsync();
}
public async void SendNetBytes()
{
byte[] bytes = new byte[] { 1, 5, 7 };
await module.InvokeVoidAsync("getNetBytes", bytes);
}
public async void GetJavaBytes()
{
byte[] buffer = await module.InvokeAsync<byte[]>("getJavaBytes");
Console.WriteLine(buffer.Length);
foreach (byte b in buffer)
{
Console.WriteLine(b);
}
}
public async void DownloadAndDecode()
{
byte[] buffer = await module.InvokeAsync<byte[]>("downloadAndDecode", "/track.mp3");
Console.WriteLine(buffer.Length);
await module.InvokeVoidAsync("getNetBytes", buffer);
}
public async void DownloadAndDecodeUsingCallback()
{
await module.InvokeVoidAsync("downloadAndDecodeUsingCallback", "/track.mp3", objRef);
}
[JSInvokable]
public async void ReceiveDecodedBuffer(byte[] buffer)
{
Console.WriteLine("Got buffer!");
Console.WriteLine(buffer.Length);
await module.InvokeVoidAsync("getNetBytes", buffer);
}
}
wwwroot/byteArray.js
export function getNetBytes(bytes) {
console.log(bytes);
}
export function getJavaBytes() {
return new Uint8Array([1, 2, 3, 4, 5]);
}
import { SuperpoweredTrackLoader } from '/superpowered/SuperpoweredTrackLoaderModule.js';
export async function downloadAndDecode(url) {
const promise = new Promise((resolve) => {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
const buffer = new Uint8Array(message.SuperpoweredLoaded.buffer);
resolve(buffer);
});
});
const buffer = await promise;
return buffer;
}
export function downloadAndDecodeUsingCallback(url, dotNetRef) {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
const buffer = new Uint8Array(message.SuperpoweredLoaded.buffer);
await dotNetRef.invokeMethodAsync('ReceiveDecodedBuffer', buffer);
});
}
首先,对于这样一个悬而未决的问题,我们深表歉意。我认为这个问题来自于对 WASM 和 .Net 中 JSInterop 的本质缺乏理解。
我只是想联系任何在 Blazor 中使用过 Superpowered Web Audio SDK 的人,了解他们是如何使用它的,因为我正在为 JSInterop 苦苦挣扎,我觉得我没有让事情变得更难使用基于 Javascript 的框架。
我已经使用 C# class 设置了一个 Blazor 客户端 Web 程序集项目,它作为一个非常简单的 Javascript 文件的接口来下载和解码音频文件:
public class AudioTest
{
[Inject]
IJSRuntime js;
DotNetObjectReference<AudioTest> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async void DownloadAndDecode(string url)
{
byte[] buffer = await superpoweredModule.InvokeAsync<byte[]>("downloadAndDecode", url, objRef);
Console.WriteLine(buffer.Length);
}
[JSInvokable]
public void ReceiveDecodedBuffer(string url, byte[] buffer)
{
Console.WriteLine(buffer);
}
}
调用 C# 方法 DownloadAndDecode() 时,它将自身的引用传递给 javascript 函数 downloadAndDecode() 以在缓冲区准备就绪时用于回调:
import { SuperpoweredTrackLoader } from '/superpowered/SuperpoweredTrackLoaderModule.js';
export async function downloadAndDecode(url, dotNetRef) {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
await dotNetRef.invokeMethodAsync('ReceiveDecodedBuffer', url, message.SuperpoweredLoaded.buffer);
});
}
但是,这会导致在转换 base64 缓冲区时出现运行时错误。我试过在发送之前从 base64 转换音频缓冲区(这太慢了)。我还尝试了未编组的 Javascript 调用,但它们仅支持同步调用。在 C#、JS 之间传递时必须转换缓冲区,反之亦然。
我计划在 C# 和 JS 上处理音频缓冲区。但感觉我应该离开 JS 端并在那里管理缓冲区。有人对此有建议吗?或者我应该把它留在 Javascript 一边吗?或者简单地更改我的 design/approach 和框架以支持 Superpowered 库。
安装 .net 6 preview 6 并再次创建我的项目提供了一种在 Blazor 和 JavaScript 之间传递大字节 [] 的快速有效方法。在不创建新项目的情况下,当 returning/sending byte[] .
时会导致奇怪的行为这是我的源代码示例。该代码需要 Superpowered Web Audio 库。 ByteArrayTest.razor
<h3>ByteArrayTest</h3>
<button @onclick="SendNetBytes">Send bytes to javascript</button>
<button @onclick="GetJavaBytes">Get bytes from javascript</button>
<button @onclick="DownloadAndDecode">Download And Decode .mp3</button>
<button @onclick="DownloadAndDecodeUsingCallback">Download And Decode .mp3 Using Callback</button>
@code {
[Inject]
IJSRuntime jsRuntime { get; set; }
IJSObjectReference module;
DotNetObjectReference<ByteArrayTest> objRef;
protected override async Task OnInitializedAsync()
{
objRef = DotNetObjectReference.Create(this);
module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "/byteArray.js");
}
public async ValueTask DisposeAsync()
{
objRef.Dispose();
await module.DisposeAsync();
}
public async void SendNetBytes()
{
byte[] bytes = new byte[] { 1, 5, 7 };
await module.InvokeVoidAsync("getNetBytes", bytes);
}
public async void GetJavaBytes()
{
byte[] buffer = await module.InvokeAsync<byte[]>("getJavaBytes");
Console.WriteLine(buffer.Length);
foreach (byte b in buffer)
{
Console.WriteLine(b);
}
}
public async void DownloadAndDecode()
{
byte[] buffer = await module.InvokeAsync<byte[]>("downloadAndDecode", "/track.mp3");
Console.WriteLine(buffer.Length);
await module.InvokeVoidAsync("getNetBytes", buffer);
}
public async void DownloadAndDecodeUsingCallback()
{
await module.InvokeVoidAsync("downloadAndDecodeUsingCallback", "/track.mp3", objRef);
}
[JSInvokable]
public async void ReceiveDecodedBuffer(byte[] buffer)
{
Console.WriteLine("Got buffer!");
Console.WriteLine(buffer.Length);
await module.InvokeVoidAsync("getNetBytes", buffer);
}
}
wwwroot/byteArray.js
export function getNetBytes(bytes) {
console.log(bytes);
}
export function getJavaBytes() {
return new Uint8Array([1, 2, 3, 4, 5]);
}
import { SuperpoweredTrackLoader } from '/superpowered/SuperpoweredTrackLoaderModule.js';
export async function downloadAndDecode(url) {
const promise = new Promise((resolve) => {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
const buffer = new Uint8Array(message.SuperpoweredLoaded.buffer);
resolve(buffer);
});
});
const buffer = await promise;
return buffer;
}
export function downloadAndDecodeUsingCallback(url, dotNetRef) {
SuperpoweredTrackLoader.downloadAndDecode(url, async (message) => {
const buffer = new Uint8Array(message.SuperpoweredLoaded.buffer);
await dotNetRef.invokeMethodAsync('ReceiveDecodedBuffer', buffer);
});
}