1

.NET で TTS エンジンを開発しました。今、私はそれをウェブ上で公開したいと考えています。base64 文字列エンコーディングを使用して WAV 形式を転送しましたが、長いテキストを渡すと遅くなります。現在、WAV 形式の MemoryStream を MP3 ストリームに変換してクライアントに渡す MP3 ストリーミング (おそらく NAudio を使用) を構築することを検討しています。誰もこれについて経験がありますか?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 を使用すると、stdin から読み込んで stdout に書き込むことができるため、プロセスで標準の入出力をリダイレクトすると、その場で変換できます。

于 2012-11-14T17:07:14.700 に答える