5
votes

I want to record raw audio from WASAPI loopback by NAudio and pipe to FFmpeg for streaming via memory stream. As from this document, FFmpeg can get input as Raw However, I got result speed at 8~10x! Here is my code:

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 Arguments:

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

1. Can someone please explain this situation and give me a solution?
2. Should I add Wav header to the Memory Stream then pipe to FFmpeg as Wav format?

The Working Solution

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 Arguments:

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

3 Answers

1
votes

make sure you pass the correct waveformat parameters to FFMpeg. You'll to check the FFmpeg documentation for details of this. WASAPI capture is going to be stereo IEEE float (32 bit), and probably 44.1kHz or 48kHz. Also you should use e.BytesRecorded not e.Buffer.Length.

0
votes

The FFmpeg raw PCM audio demuxers need to be supplied with the proper number of channels (-channels, default value is 1) and the sample rate (-sample_rate, default value is 44100).

The order of options is important: options immediately before the input get applied to the input, and options immediately before the output get applied to the output.

ffmpeg cli example:

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

Your code example:

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

Using WasapiLoopbackCapture, here is the full command that worked for me without distortion or slowdown:

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