2014-06-13 115 views
4

背景:我正在使用返回MIME类型为audio/wav的数据的服务。我需要为此音频提供播放机制(当前构建为MVC应用程序)。举例来说,我的端点看起来像https://audio.fooservice.com/GetAudio?audioId=123将wav实时流式传输到mp3转换为mp3

音频是8kHz,1声道u律。

由于在使用HTML5 <audio>标签时,跨浏览器的格式支持不同,所以我无法使用原始的u-law wav,因为Internet Explorer不会播放它。

我建议的解决方案是做一个从源格式到mp3的实时转换。

我拼凑从这里各种其他问题,并在n音讯论坛部分工作的解决方案,但在下面的评论指出它抛出一个异常:

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(); 
        } 
       } 
      } 
     } 
    } 
} 

我一直戳在这一天的大部分时间里,我觉得我正在将不必要的复杂性引入似乎之类的东西,因为它应该相当简单。

任何帮助将不胜感激。

注意:我无法更改源格式,并且支持IE是必需的。

编辑:我解决了RIFF异常,并能够产生MP3流,但它只是白噪声。希望我能解决这个问题。我的新代码如下:

[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"); 
} 
+1

您必须将源的实际波形格式提供给'LameMP3FileWriter'构造函数。而不是'new WaveFormat()'使用'wav.WaveFormat',否则它会读取错误的数据。 – Corey

+0

谢谢Corey。我错误地认为'CreatePcmStream'方法将返回一个与默认的'WaveFormat'构造函数具有相同格式的流。事实证明,我的源码流的文档(和MIME类型)是不正确的,我花了一个星期摆弄这个没有。 – LiquidPony

回答

0

这适用于我(我需要做你想做的事)。希望这可以帮助别人。我使用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(); 
     }