naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.37k stars 1.09k forks source link

WasapiLoopbackCapture Http Live Stream #1146

Open 4hera opened 3 months ago

4hera commented 3 months ago

Hi, I want to capture the audio going to my computer's default audio output with WasapiLoopbackCapture and broadcast it over http. Just like a radio broadcast. I tried the following parts but I was not successful. Where am I making a mistake? AudioStreamService.cs

    public class AudioStreamService
    {
        private readonly WasapiLoopbackCapture _loopbackCapture;
        private readonly MemoryStream _memoryStream;
        private readonly MMDeviceEnumerator MMDE;
        private readonly MMDevice masterDevice;
        private readonly WaveFormat waveFormat;
        public AudioStreamService()
        {
            MMDE = new MMDeviceEnumerator();
            masterDevice = MMDE.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
            _loopbackCapture = new WasapiLoopbackCapture(masterDevice);
            _loopbackCapture.DataAvailable += LoopbackCapture_DataAvailable;
            _memoryStream = new MemoryStream();
        }

        private void LoopbackCapture_DataAvailable(object sender, WaveInEventArgs e)
        {
            _memoryStream.Write(e.Buffer, 0, e.BytesRecorded);
        }

        public void StartAudioCapture()
        {
            if (_loopbackCapture.CaptureState == NAudio.CoreAudioApi.CaptureState.Stopped ||
                _loopbackCapture.CaptureState == NAudio.CoreAudioApi.CaptureState.Stopping)
            {
                _loopbackCapture.StartRecording();
            }
        }

        public void StopAudioCapture()
        {
            _loopbackCapture.StopRecording();
        }

        public byte[] GetAudioData()
        {
            var audioData = _memoryStream.ToArray();
            _memoryStream.SetLength(0);
            return audioData;
        }
        public string GetState()
        {
            return _loopbackCapture.CaptureState.ToString();
        }
    }

Startup.cs

          app.UseRouting();

          app.UseEndpoints(endpoints =>
          {
              endpoints.MapControllers();
              endpoints.MapGet("/stream", async context =>
              {
                  var audioStreamService = context.RequestServices.GetService<AudioStreamService>();

                  context.Response.Headers.Add("Content-Type", "audio/mpeg");

                  while (audioStreamService.GetState() == "Capturing")
                  {
                      var audioData = audioStreamService.GetAudioData();

                      if (audioData.Length > 0)
                      {
                          await context.Response.Body.WriteAsync(audioData, 0, audioData.Length);
                          await context.Response.Body.FlushAsync();
                      }
                  }
              });
          });
markheath commented 2 months ago

You're saying that the content-type is audio/mpeg, but WASAPI is capturing uncompressed IEEE floating point audio. You'd want something else encoding it to MP4 on the fly to support this kind of setup, which is unfortunately not easy to achieve with NAudio, as the MediaFoundationEncoder works best with whole files

4hera commented 2 months ago

Thanks for your answer. I am developing websocket based soft kvm software. I transfer the image to the browser. Additionally, I wanted to transfer the sound. Is there a source or code block you can recommend for the encoding process you mentioned?