来自 NAudio 的原始音频

Raw Audio from NAudio

我想通过 NAudio 记录来自 WASAPI 环回的原始音频,并通过管道传输到 FFmpeg 以通过内存流进行流式传输。从这个 document 开始,FFmpeg 可以获取 Raw 输入但是,我得到的结果速度是 8~10 倍! 这是我的代码:

waveInput = new WasapiLoopbackCapture();
waveInput.DataAvailable += new EventHandler<WaveInEventArgs>((object sender, WaveInEventArgs e) => 
{
    lock (e.Buffer)
    {
        if (waveInput == null)
            return;
        try
        {
            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
            {
                memoryStream.Write(e.Buffer, 0, e.Buffer.Length);
                memoryStream.WriteTo(ffmpeg.StandardInput.BaseStream);
            }
        }
        catch (Exception)
        {
            throw;
        }
    }
});
waveInput.StartRecording();

FFmpeg 参数:

ffmpegProcess.StartInfo.Arguments = String.Format("-f s16le -i pipe:0 -y output.wav");

1。有人可以解释一下这种情况并给我一个解决方案吗?
2. 我是否应该将 Wav header 添加到内存流,然后以 Wav 格式通过管道传输到 FFmpeg?

工作解决方案

waveInput = new WasapiLoopbackCapture();
waveInput.DataAvailable += new EventHandler<WaveInEventArgs>((object sender, WaveInEventArgs e) => 
{
    lock (e.Buffer)
    {
        if (waveInput == null)
            return;
        try
        {
            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
            {
                memoryStream.Write(e.Buffer, 0, e.BytesRecorded);
                memoryStream.WriteTo(ffmpeg.StandardInput.BaseStream);
            }
        }
        catch (Exception)
        {
            throw;
        }
    }
});
waveInput.StartRecording();

FFMpeg 参数:

ffmpegProcess.StartInfo.Arguments = string.Format("-f f32le -ac 2 -ar 44.1k -i pipe:0 -c:a copy -y output.wav");

确保将正确的 waveformat 参数传递给 FFMpeg。您将检查 FFmpeg documentation 以了解详细信息。 WASAPI 捕获将是立体声 IEEE 浮点数(32 位),可能是 44.1kHz 或 48kHz。你也应该使用 e.BytesRecorded 而不是 e.Buffer.Length.

FFmpeg 原始 PCM 音频解复用器需要提供适当数量的通道(-channels,默认值为 1)和采样率(-sample_rate,默认值为 44100)。

选项的顺序很重要:紧接在输入之前的选项应用到输入,紧接在输出之前的选项应用到输出。

ffmpeg cli 示例:

ffmpeg -f s32le -channels 2 -sample_rate 44100 -i pipe:0 -c copy output.wav

您的代码示例:

ffmpegProcess.StartInfo.Arguments = String.Format("-y -f s32le -channels 2 -sample_rate 44100 -i pipe:0 -c copy output.wav");

使用 WasapiLoopbackCapture,这是对我有用的完整命令,没有失真或减速:

string command = $"-f f32le -channels {wasapiLoopbackCapture.WaveFormat.Channels} -sample_rate {wasapiLoopbackCapture.WaveFormat.SampleRate} -i {pipePrefix}{pipeName} ffmpegtest.wav";