1

我在 .NET 中开发了 TTS 引擎。现在我想通过网络公开它。我使用 base64 字符串编码来传输 WAV 格式,但是当我传递较长的文本时速度很慢。现在我正在考虑构建一些 MP3 流(可能使用 NAudio),我将在其中将 WAV 格式的 MemoryStream 转换为 MP3 流并将其传递给客户端。有没有人有这方面的经验?有谁有经验如何将带有 NAudio 的 WAV MemoryStream 转换为 MP3 MemoryStream?

4

2 回答 2

2
public class MP3StreamingPanel2 : UserControl
{

enum StreamingPlaybackState
{
    Stopped,
    Playing,
    Buffering,
    Paused
}

private BufferedWaveProvider bufferedWaveProvider;
private IWavePlayer waveOut;
private volatile StreamingPlaybackState playbackState;
private volatile bool fullyDownloaded;
private HttpWebRequest webRequest;

public void StreamMP32(string url)
{

    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    SettingsSection section = (SettingsSection)config.GetSection("system.net/settings");
    section.HttpWebRequest.UseUnsafeHeaderParsing = true;
    config.Save();

    this.fullyDownloaded = false;

    webRequest = (HttpWebRequest)WebRequest.Create(url);

    int metaInt = 0; // blocksize of mp3 data

    webRequest.Headers.Clear();
    webRequest.Headers.Add("GET", "/ HTTP/1.0");
    // needed to receive metadata informations
    webRequest.Headers.Add("Icy-MetaData", "1");
    webRequest.UserAgent = "WinampMPEG/5.09";

    HttpWebResponse resp = null;
    try
    {
        resp = (HttpWebResponse)webRequest.GetResponse();
    }
    catch (WebException e)
    {
        if (e.Status != WebExceptionStatus.RequestCanceled)
        {
            //ShowError(e.Message);
        }
        return;
    }
    byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame

    try
    {
        // read blocksize to find metadata block
        metaInt = Convert.ToInt32(resp.GetResponseHeader("icy-metaint"));

    }
    catch
    {
    }

    IMp3FrameDecompressor decompressor = null;
    try
    {
        using (var responseStream = resp.GetResponseStream())
        {
            var readFullyStream = new ReadFullyStream(responseStream);
            readFullyStream.metaInt = metaInt;
            do
            {
                if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4)
                {
                    Debug.WriteLine("Buffer getting full, taking a break");
                    Thread.Sleep(500);
                }
                else
                {
                    Mp3Frame frame = null;
                    try
                    {
                        frame = Mp3Frame.LoadFromStream(readFullyStream, true);
                    }
                    catch (EndOfStreamException)
                    {
                        this.fullyDownloaded = true;
                        // reached the end of the MP3 file / stream
                        break;
                    }
                    catch (WebException)
                    {
                        // probably we have aborted download from the GUI thread
                        break;
                    }
                    if (decompressor == null)
                    {
                        // don't think these details matter too much - just help ACM select the right codec
                        // however, the buffered provider doesn't know what sample rate it is working at
                        // until we have a frame
                        WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
                        decompressor = new AcmMp3FrameDecompressor(waveFormat);
                        this.bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);
                        this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // allow us to get well ahead of ourselves
                        //this.bufferedWaveProvider.BufferedDuration = 250;
                    }
                    int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
                    //Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed));
                    bufferedWaveProvider.AddSamples(buffer, 0, decompressed);
                }

            } while (playbackState != StreamingPlaybackState.Stopped);
            Debug.WriteLine("Exiting");
            // was doing this in a finally block, but for some reason
            // we are hanging on response stream .Dispose so never get there
            decompressor.Dispose();
        }
    }
    finally
    {
        if (decompressor != null)
        {
            decompressor.Dispose();
        }
    }
}
}
于 2013-03-12T17:03:53.863 回答
0

NAudio 不包含 MP3 编码器。当我需要对 MP3 进行编码时,我使用lame.exe。如果您不想通过文件,lame.exe 允许您从标准输入读取并写入标准输出,因此如果您在进程中重定向标准输入和输出,您可以即时转换。

于 2012-11-14T17:07:14.700 回答