用 NAudio 录制音频让我无法接受

Posted

技术标签:

【中文标题】用 NAudio 录制音频让我无法接受【英文标题】:Recording audio with NAudio cuts me off 【发布时间】:2020-03-29 23:22:45 【问题描述】:

我正在录制音频以将其发送到 Google 语音到文本,但是当我使用 naudio 制作音频时,它只记录了我 5 秒,然后停止录制。我复制了C#中的代码,这是我第一次使用这个API,但我不知道为什么它会打断我,如果我按下保存按钮时它应该停止录制,应用程序是一个带有2个按钮的简单表单,一个用于录制,另一个用于停止。

namespace WindowsFormsApp1

    public partial class Form1 : Form
    
        private BufferedWaveProvider bwp;
        WaveIn waveIn;
        WaveOut waveOut;
        WaveFileWriter writer;
        WaveFileReader reader;
        string output = "audio.raw";
        public Form1()
        
            InitializeComponent();
            waveOut = new WaveOut();
            waveIn = new WaveIn();

            waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
            waveIn.WaveFormat = new NAudio.Wave.WaveFormat(16000, 1);
            bwp = new BufferedWaveProvider(waveIn.WaveFormat);
            bwp.DiscardOnBufferOverflow = true;

            btnRecordVoice.Enabled = true;
            btnSave.Enabled = false;
            //btnSpeechInfo.Enabled = false;
        

        private void btnRecordVoice_Click(object sender, EventArgs e)
        
            if (NAudio.Wave.WaveIn.DeviceCount < 1)
            
                Console.WriteLine("No se encuentra un microfono!");
                return;
            

            waveIn.StartRecording();

            btnRecordVoice.Enabled = false;
            btnSave.Enabled = true;
        

        private void btnSave_Click(object sender, EventArgs e)
        
            waveIn.StopRecording();

            if (File.Exists("audio.raw"))
                File.Delete("audio.raw");

            writer = new WaveFileWriter(output, waveIn.WaveFormat);

            btnRecordVoice.Enabled = false;
            btnSave.Enabled = false;

            byte[] buffer = new byte[bwp.BufferLength];
            int offset = 0;
            int count = bwp.BufferLength;

            var read = bwp.Read(buffer, offset, count);
            if (count > 0)
            
                writer.Write(buffer, offset, read);
            

            waveIn.Dispose();
            waveIn = null;
            writer.Close();
            writer = null;

            reader = new WaveFileReader("audio.raw"); // (new MemoryStream(bytes));
            waveOut.Init(reader);
            waveOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(waveOut_PlaybackStopped);
            waveOut.Play();
        

        void waveIn_DataAvailable(object sender, WaveInEventArgs e)
        
            bwp.AddSamples(e.Buffer, 0, e.BytesRecorded);

        

        private void waveOut_PlaybackStopped(object sender, StoppedEventArgs e)
        
            waveOut.Stop();
            reader.Close();
            reader = null;
        
    

【问题讨论】:

Stack Overflow 仅支持英语。我已经使用谷歌翻译编辑了你的问题,请检查它以确保它没问题 btnSave_Click() 中的代码从BufferedWaveProvider 复制到WaveFileWriter 是...奇怪。您将bwp.Read() 的结果存储在read 中,然后检查count,它是bwp.Read() 的参数(上限)。此外,通常那些Read(byte[], int, int) 方法不能保证读取所有请求的数据,因此您需要一个循环,而不是if。试试int read; while ((read = bwp.Read(buffer, 0, buffer.Length)) &gt; 0) writer.Write(buffer, 0, read); 【参考方案1】:

您获得一个 5 秒的音频剪辑不仅是因为您从 BufferedWaveProvider 中读取了一次性的 BufferLength...

int count = bwp.BufferLength;

var read = bwp.Read(buffer, offset, count);

...5 秒是default value of that property,但因为BufferedWaveProvider uses a circular buffer,所以BufferLength 是它可用的所有数据。

对我有用的是跳过BufferedWaveProvider,并在新数据可用时立即将新数据写入WaveFileWriter...

void waveIn_DataAvailable(object sender, WaveInEventArgs e)

    writer.Write(e.Buffer, 0, e.BytesRecorded);

为了支持该更改,按钮事件处理程序更改为以下...

private void btnRecordVoice_Click(object sender, EventArgs e)

    if (NAudio.Wave.WaveIn.DeviceCount < 1)
    
        Console.WriteLine("No se encuentra un microfono!");
        return;
    

    writer = new WaveFileWriter(output, waveIn.WaveFormat);
    waveIn.StartRecording();

    btnRecordVoice.Enabled = false;
    btnSave.Enabled = true;


private void btnSave_Click(object sender, EventArgs e)

    waveIn.StopRecording();
    writer.Close();
    writer = null;

    btnRecordVoice.Enabled = false;
    btnSave.Enabled = false;

    reader = new WaveFileReader("audio.raw"); // (new MemoryStream(bytes));
    waveOut.Init(reader);
    waveOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(waveOut_PlaybackStopped);
    waveOut.Play();

这似乎与Recording a WAV file in a WinForms app with WaveIn 中使用的方法相同。

【讨论】:

以上是关于用 NAudio 录制音频让我无法接受的主要内容,如果未能解决你的问题,请参考以下文章

使用 naudio 录制特定的应用程序音频

使用 NAudio 录制和播放音频

NAudio : 保留最后一个 ex: 5s 录制的音频并随时保存

在 WPF C# 中使用 NAudio 录制音频

错误的 .wav 格式录制音频 NAudio 库

NAudio:使用 ASIO 录制音频并用吉他输出