Convert HTTP to mp3 wav in real time

Background . I am using a service that returns data with a MIME type audio/wav. I need to provide a playback mechanism for this sound (currently created as an MVC application). As an example, my endpoint looks something likehttps://audio.fooservice.com/GetAudio?audioId=123

The sound has 8 kHz, 1-channel u-law.

Due to the support of various formats in browsers when using the HTML5 tag, <audio>I can not use the original w-law wav, because Internet Explorer will not play it.

My suggested solution is to do a real-time conversion from the original format to mp3.

I have compiled a partially working solution from various other questions here and on the NAudio forums, but it throws an exception, as indicated in the comments below:

private void NAudioTest(string url)
{
    Stream outStream = new MemoryStream();
    var format = WaveFormat.CreateMuLawFormat(8000, 1);

    using (Stream ms = new MemoryStream())
    {
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.KeepAlive = false;
        request.ProtocolVersion = HttpVersion.Version10;

        using (Stream stream = request.GetResponse().GetResponseStream())
        {
            using (var reader = new RawSourceWaveStream(stream, format))
            {
                // reader is not seekable; we need to convert to a byte array to seek
                var bytes = reader.ToByteArray();

                // create a new stream from the byte aray
                var seekableStream = new MemoryStream(bytes);

                // instantiating a WaveFileReader as follows will throw an exception:
                // "System.FormatException: Not a WAVE file - no RIFF header"
                using (var waveReader = new WaveFileReader(seekableStream))
                {
                    using (var pcmStream = WaveFormatConversionStream.CreatePcmStream(waveReader))
                    {
                        var pcmBytes = pcmStream.ToByteArray();
                        var mp3 = pcmBytes.ToMp3();
                    }
                }
            }
        }
    }
}

public static class StreamExtensions
{
    public static byte[] ToByteArray(this Stream stream)
    {
        var ms = new MemoryStream();
        var buffer = new byte[1024];
        int bytes = 0;

        while ((bytes = stream.Read(buffer, 0, buffer.Length)) > 0)
            ms.Write(buffer, 0, bytes);

        return ms.ToArray();
    }
}

public static class ByteExtensions
{
    public static byte[] ToMp3(this byte[] bytes)
    {
        using (var outStream = new MemoryStream())
        {
            using (var ms = new MemoryStream(bytes))
            {
                using (var reader = new WaveFileReader(ms))
                {
                    using (var writer = new LameMP3FileWriter(outStream, reader.WaveFormat, 64))
                    {
                        reader.CopyTo(writer);
                        return outStream.ToArray();
                    }
                }
            }
        }
    }
}

For most of the day, I thought a lot about this, and it seems to me that I am presenting too much complexity in something that seems should be pretty simple.

Any help would be greatly appreciated.

Note . I cannot change the original format, and IE support is a requirement.

EDIT : I resolved the RIFF exception and can create an MP3 stream, but this is nothing but white noise. I hope I can solve it too. My new code is as follows:

[HttpGet]
public ActionResult GetMp3(string url)
{
    if (String.IsNullOrWhiteSpace(url))
        return null;

    var muLawFormat = WaveFormat.CreateMuLawFormat(8000, 1);
    var compressedStream = new MemoryStream();

    using (var ms = new MemoryStream())
    {
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.KeepAlive = false;
        request.ProtocolVersion = HttpVersion.Version10;

        using (Stream webStream = request.GetResponse().GetResponseStream())
        {
            var buffer = new byte[4096];
            int read;
            while (webStream != null && (read = webStream.Read(buffer, 0, buffer.Length)) > 0)
                ms.Write(buffer, 0, read);
        }

        ms.Position = 0;

        using (WaveStream wav = WaveFormatConversionStream.CreatePcmStream(new RawSourceWaveStream(ms, muLawFormat)))
        using (var mp3 = new LameMP3FileWriter(compressedStream, new WaveFormat(), LAMEPreset.MEDIUM_FAST))
            wav.CopyTo(mp3);
    }

    compressedStream.Seek(0, 0);
    return new FileStreamResult(compressedStream, "audio/mpeg");
}
+4
source share
1 answer

( , ). , - . NAudio LAME.

, libmp3lamexx.dll BIN - - % PATH%, .

        string sq = /* URL of WAV file (http://foo.com/blah.wav) */

        Response.ContentType = "audio/mpeg";

        using (WebClient wc = new WebClient())
        {
            if (!sq.ToLower().EndsWith(".wav"))
            {
                byte[] rawFile = wc.DownloadData(sq.Trim());
                Response.OutputStream.Write(rawFile, 0, rawFile.Length);
            }
            else
            {
                using (var wavReader = new WaveFileReader(new MemoryStream(wc.DownloadData(sq.Trim()))))
                {
                    try
                    {
                        using (var wavWriter = new LameMP3FileWriter(Response.OutputStream, wavReader.WaveFormat, LAMEPreset.ABR_128))
                        {
                            wavReader.CopyTo(wavWriter);
                        }
                    }
                    catch (ArgumentException)
                    {
                        var newFormat = new WaveFormat(wavReader.WaveFormat.SampleRate, 16, 2);

                        using (var pcmStream = new WaveFormatConversionStream(newFormat, wavReader))
                        {
                            using (var wavWriter = new LameMP3FileWriter(Response.OutputStream, pcmStream.WaveFormat, LAMEPreset.ABR_128))
                            {
                                pcmStream.CopyTo(wavWriter);
                            }
                        }
                    }
                }
            }

            Response.Flush();
            Response.End();
        }
0

Source: https://habr.com/ru/post/1544513/


All Articles