You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Core 3.1 WPF应用中播放MixedReality-WebRTC接收的Unity音频

解决方案

问题解答

  • 如何确定数组的大小?

数组字节长度计算公式:字节长度 = sampleCount * channelCount * bitsPerSample / 8,除以8是将比特单位转换为字节单位,计算结果转换为Int32类型即可用于Marshal.Copy操作。

  • 如果获取到字节数组或者流,如何在实时语音通话场景下播放它?

推荐使用NAudio库实现实时音频播放,它是.NET平台轻量的音频处理库,支持原始PCM音频流的低延迟播放,适配WPF和.NET Core 3.1环境,直接在NuGet包管理器搜索安装即可。
实现逻辑为:首次收到音频帧时根据帧参数初始化播放格式和播放设备,后续收到帧后将数据写入缓存队列,播放组件自动从队列取数据播放,缓存大小可根据延迟和卡顿需求调整。

  • 播放音频是否真的需要从IntPtr中获取流或者字节数组?

不是必须,你可以直接调用底层Windows音频API对接IntPtr内存块避免拷贝,但对于新手来说转换为字节数组是最易维护、出错概率最低的方案,且单帧音频数据量极小(10ms帧通常仅几百字节),拷贝开销完全可以忽略,不会影响实时性。

  • 如果需要的话该如何实现?

参考下方完整示例代码即可。

完整示例代码

首先在你的WPF窗口类中定义成员变量:

using NAudio.Wave;
using System.Runtime.InteropServices;

// 类成员变量
private IWavePlayer _audioPlayer;
private BufferedWaveProvider _audioBuffer;
private WaveFormat _playFormat;
private readonly object _bufferLock = new object();

修改你的音频帧接收逻辑:

pc.AudioTrackAdded += (RemoteAudioTrack track) => 
{
    track.AudioFrameReady += (AudioFrame frame) => 
    {
        // 首次收到帧时初始化播放设备和格式
        if (_playFormat == null)
        {
            _playFormat = new WaveFormat(
                rate: (int)frame.sampleRate,
                bitsPerSample: (int)frame.bitsPerSample,
                channels: (int)frame.channelCount);
            
            _audioBuffer = new BufferedWaveProvider(_playFormat)
            {
                BufferDuration = TimeSpan.FromMilliseconds(500), // 缓存500ms数据,平衡延迟和抗卡顿能力
                DiscardOnBufferOverflow = true // 实时场景下缓存溢出时丢弃旧数据,避免延迟累积
            };

            _audioPlayer = new WaveOutEvent();
            _audioPlayer.Init(_audioBuffer);
            _audioPlayer.Play();
        }

        // 计算当前帧字节长度
        int frameByteLength = (int)(frame.sampleCount * frame.channelCount * frame.bitsPerSample / 8);
        // 从非托管内存拷贝到字节数组
        byte[] audioBuffer = new byte[frameByteLength];
        Marshal.Copy(frame.audioData, audioBuffer, 0, frameByteLength);

        // 线程安全写入播放缓存
        lock (_bufferLock)
        {
            if (_audioBuffer != null)
            {
                _audioBuffer.AddSamples(audioBuffer, 0, frameByteLength);
            }
        }
    };
};

最后在窗口关闭时释放资源,避免内存泄漏:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    lock (_bufferLock)
    {
        _audioPlayer?.Stop();
        _audioPlayer?.Dispose();
        _audioBuffer = null;
        _playFormat = null;
    }
}

常见问题排查

  • 播放出现杂音:检查字节长度计算是否正确,确认音频参数(采样率、位深、声道数)初始化和实际帧参数一致,WebRTC默认常用参数为16kHz采样率、16bit位深、单声道。
  • 播放卡顿:可适当调大BufferDuration到1000ms,降低丢包概率。
  • 延迟过高:可适当调小BufferDuration到200ms,减少缓存数据量。

内容的提问来源于stack exchange,提问作者macnmunasinghe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:39:00