Raw Audio from NAudio
Asked Answered
O

3

6

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");
Octopus answered 19/2, 2017 at 15:46 Comment(0)
I
1

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.

Issiah answered 19/2, 2017 at 19:14 Comment(5)
I used this -f s32le -i pipe:0 -ar 44100 -ac 2 -sample_fmt s32 -c:a copy -y output.wav. but got 2x speed. The FFMpeg said: Guessed Channel Layout for Input Stream #0.0 : mono. Stream #0:0: Audio: pcm_s32le, 44100 Hz, mono, s32, 1411 kb/sOctopus
I changed the above to: -f s32le -ac 2 -ar 44100 -i pipe:0 -sample_fmt s32 -c:a copy -y output.wav, and got result: stereo and speed decreasing from 3x to 1x in the first 4 mins, and 1x constantly onward. It brought interference and noise in the entire audio, but I could recognize the sound. What should I do to deal with this? Your information helped me a lot. Thank you.Octopus
I don't think s32 is right. You want to specify float (not sure what the flag is for that). Can't explain the speed increase I'm decrease though - that's very strangeIssiah
I though I have tried all the format, and s32le is the closest one. But I was wrong, the correct format is f32le. The resulting audio is just fast a bit for the first 2,3 mins, hard to notice that different. I got stuck at here since yesterday. You saved my life Mark. You are awesome!Octopus
I'm late to the party, but changing your sample format to 48000 got the speed recording normally.Bennettbenni
M
0

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");
Malamute answered 20/2, 2017 at 6:59 Comment(1)
I did that just around 30 minutes before your answer, appreciate your help. But my next problem is the output audio is not clear. It has a lot of interference and noise.Octopus
B
0

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";
Bennettbenni answered 21/4, 2021 at 13:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.