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

如何使用NAudio播放嵌入资源中的WAV文件?

解决嵌入WAV到EXE并使用NAudio播放的问题

我来帮你搞定这个嵌入音频到EXE的播放问题——你之前遇到的慢放混响、结束爆音,基本都是因为资源流的处理方式不对,咱们一步步来解决:

第一步:正确设置WAV文件的嵌入属性

首先确保你的sound_1.wav被正确标记为嵌入资源:

  • 在Visual Studio中,选中Resources文件夹里的sound_1.wav
  • 在属性窗口里,把生成操作改成Embedded Resource(默认可能是Resource,这两种资源的访问逻辑完全不同,一定要改)
  • 确认复制到输出目录设置为不复制,因为我们要把它嵌入到EXE里,不需要单独输出

第二步:用NAudio读取嵌入资源流(关键!WaveFileReader支持Stream)

你之前误以为WaveFileReader只能接受字符串路径,但其实它有WaveFileReader(Stream stream)的重载!这才是嵌入资源播放的正确打开方式。

完整代码示例(WPF环境)

下面是一个可直接用的播放方法,包含了资源清理逻辑(解决爆音的核心):

using NAudio.Wave;
using System.Reflection;
using System.Windows;

// 建议在窗口类中声明播放对象,方便管理生命周期
private WaveOutEvent? _audioPlayer;
private WaveFileReader? _waveReader;

private void PlayEmbeddedAudio()
{
    // 1. 获取当前程序集(包含嵌入资源的EXE/DLL)
    var currentAssembly = Assembly.GetExecutingAssembly();
    
    // 2. 嵌入资源的完整名称:格式是「项目命名空间.文件夹名.文件名」
    // 比如你的项目命名空间是WpfAudioPlayer,资源在Resources文件夹,那就是WpfAudioPlayer.Resources.sound_1.wav
    var resourceFullName = "YourProjectNamespace.Resources.sound_1.wav";

    // 3. 获取嵌入资源的流
    using var resourceStream = currentAssembly.GetManifestResourceStream(resourceFullName);
    if (resourceStream == null)
    {
        MessageBox.Show("找不到嵌入的音频资源,请检查资源名称是否正确");
        return;
    }

    // 4. 初始化播放器:注意不要用using包裹WaveFileReader,因为播放时需要流保持打开
    _waveReader = new WaveFileReader(resourceStream);
    _audioPlayer = new WaveOutEvent();
    _audioPlayer.Init(_waveReader);

    // 5. 绑定播放结束事件,清理资源(解决爆音的关键)
    _audioPlayer.PlaybackStopped += (sender, args) =>
    {
        _waveReader?.Dispose();
        _audioPlayer?.Dispose();
        _waveReader = null;
        _audioPlayer = null;
    };

    // 6. 开始播放
    _audioPlayer.Play();
}

为什么你之前的方案会出问题?

  • 慢放带混响:大概率是你把资源转成byte[]后用MemoryStream,但没有重置流的Position到0,或者错误地处理了流的编码格式,导致NAudio读取的音频参数(采样率、通道数)不正确,播放速度就会异常。
  • 结束时爆音:通常是因为播放结束后没有及时释放WaveOut和WaveFileReader的资源,或者流被提前关闭,导致音频设备的缓冲数据没有正确清空,就会出现刺耳的爆音。

额外注意事项

  • 如果你不确定资源的全名,可以用currentAssembly.GetManifestResourceNames()打印所有嵌入资源的名称,对照着找正确的名字。
  • 如果你需要更好的兼容性,可以用WasapiOut代替WaveOutEvent,尤其是在Windows 10/11的WPF应用中,Wasapi的音频处理更稳定。
  • 不要在UI线程执行长时间的音频操作,不过上面的代码里,播放是异步的,所以不会阻塞UI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:03:36