【问题标题】:Blazor and the Superpowered Web Audio SDK, how to return the arrayBuffer to C#Blazor 和 Superpowered Web Audio SDK,如何将 arrayBuffer 返回到 C#
【发布时间】:2021-07-16 04:12:13
【问题描述】:

首先,对于这样一个悬而未决的问题,我们深表歉意。我认为这个问题源于对 WASM 和 .Net 中 JSInterop 的本质缺乏了解。

我只是想联系在 Blazor 中使用过 Superpowered Web Audio SDK 的任何人,并了解他们是如何使用它的框架。

我已经设置了一个带有 C# 类的 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 端?或者只是更改我的设计/方法和框架以支持 Superpowered 库。

【问题讨论】:

  • 看起来很有趣的框架。我过去做过录制,包括录制到缓冲区,在 JavaScript 中转换为 .mp3,然后通过我网站的 FTP 服务器上传。我非常渴望找到一个可以在 Blazor 中运行的良好录制解决方案,尤其是现在 Apple 终于支持 MediaRecorder API。你签过stackoverflow.com/questions/64803155/…
  • 是的,我尝试使用未编组调用来获取音频缓冲区,但似乎所有未编组调用都是同步的,并且超级功能“downloadAndDecode”需要回调来检索缓冲区。因此,任何等待该回调并将其发回的尝试都行不通。我会再试一次,因为它确实是最好的方法,我会尝试更有创意地使用 Promise 并将 resolve() 函数作为回调传递。
  • 我不完全了解您的用例,但以下内容对我来说似乎很有希望:docs.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/…。很高兴看到 MS 在 .net 进程中全速前进!
  • 是的,看起来很有希望,我打开了 .NET 6 preview 5 博客,看看这是否是计划中的更改。我会安装它,看看效果如何。
  • 做到了。我在当前项目上尝试了 .NET 6 preview 6,它表现得很奇怪,最终在返回 byte[] 时出错。但是创建一个基于 .net 6 preview 6 的新项目并重新设置它,一切正常,速度也很快。谢谢@Bennyboy1973,非常感谢您的宝贵时间!

标签: blazor superpowered


【解决方案1】:

安装 .net 6 preview 6 并再次创建我的项目提供了一种在 Blazor 和 JavaScript 之间传递大字节 [] 的快速有效的方法。如果不创建新项目,它会在返回/发送 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);
    });
}

【讨论】:

  • 不确定它是否会让您接受自己的答案作为新的贡献者。但是,如果可以的话,请这样做,这样人们就可以看到有解决方案。
  • 看来我可以在 23 小时内完成,明天我一定会做到的。
猜你喜欢
  • 2016-02-22
  • 1970-01-01
  • 2020-02-28
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
相关资源
最近更新 更多