背景:我正在使用返回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");
}
您必须将源的实际波形格式提供给'LameMP3FileWriter'构造函数。而不是'new WaveFormat()'使用'wav.WaveFormat',否则它会读取错误的数据。 – Corey
谢谢Corey。我错误地认为'CreatePcmStream'方法将返回一个与默认的'WaveFormat'构造函数具有相同格式的流。事实证明,我的源码流的文档(和MIME类型)是不正确的,我花了一个星期摆弄这个没有。 – LiquidPony