102

データを一時的にディスクに保存せずに、たとえばWebRequest から返されたSystem.IO.Streamからオーディオ (MP3 など) を直接再生する方法は C# にありますか?


NAudioを使用したソリューション

NAudio 1.3を使用すると、次のことが可能になります。

  1. URL から MP3 ファイルを MemoryStream にロードする
  2. MP3 データの読み込みが完了したら、Wave データに変換します。
  3. NAudioの WaveOut クラスを使用してウェーブ データを再生する

半分ロードされた MP3 ファイルを再生できればよかったのですが、 NAudioライブラリの設計上、これは不可能のようです。

そして、これは仕事をする関数です:

    public static void PlayMp3FromUrl(string url)
    {
        using (Stream ms = new MemoryStream())
        {
            using (Stream stream = WebRequest.Create(url)
                .GetResponse().GetResponseStream())
            {
                byte[] buffer = new byte[32768];
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
            }

            ms.Position = 0;
            using (WaveStream blockAlignedStream =
                new BlockAlignReductionStream(
                    WaveFormatConversionStream.CreatePcmStream(
                        new Mp3FileReader(ms))))
            {
                using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
                {
                    waveOut.Init(blockAlignedStream);
                    waveOut.Play();                        
                    while (waveOut.PlaybackState == PlaybackState.Playing )                        
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                }
            }
        }
    }
4

9 に答える 9

58

編集:最近のバージョンのNAudioの変更を反映するように回答が更新されました

私が作成したNAudioオープン ソース .NET オーディオ ライブラリを使用することは可能です。PC 上の ACM コーデックを探して変換を行います。NAudio で提供される Mp3FileReader は現在、ソース ストリーム内で再配置できることを想定しているため (前もって MP3 フレームのインデックスを作成します)、ネットワーク経由のストリーミングには適していません。MP3Frameただし、NAudio のおよびクラスを引き続き使用して、AcmMp3FrameDecompressorストリーミングされた MP3 をオンザフライで解凍できます。

NAudio を使用して MP3 ストリームを再生する方法を説明する記事をブログに投稿しました。基本的に、MP3 フレームをダウンロードし、解凍し、BufferedWaveProvider. 次に、別のスレッドが を入力として使用して再生しBufferedWaveProviderます。

于 2008-10-08T21:44:46.523 に答える
10

これは、SoundPlayerクラスで実行できます。Streamプロパティをストリームに設定してから、 を呼び出すだけPlayです。

編集
MP3 ファイルは再生できないと思います。.wavに限定されているようです。フレームワークに MP3 ファイルを直接再生できるものがあるかどうかはわかりません。私が見つけたすべてのことには、WMP コントロールの使用または DirectX との対話が含まれます。

于 2008-10-08T20:42:06.133 に答える
5

低音はまさにこれを行うことができます。メモリ内のByte[]から再生するか、データを返すファイルデリゲートを介して再生します。これにより、再生を開始するのに十分なデータが得られたらすぐに再生できます。

于 2008-10-22T10:59:39.223 に答える
2

ここで質問に答えるために、質問に投稿されたソースを調整して、GoogleのTTSAPIで使用できるようにしました。

bool waiting = false;
AutoResetEvent stop = new AutoResetEvent(false);
public void PlayMp3FromUrl(string url, int timeout)
{
    using (Stream ms = new MemoryStream())
    {
        using (Stream stream = WebRequest.Create(url)
            .GetResponse().GetResponseStream())
        {
            byte[] buffer = new byte[32768];
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
        }
        ms.Position = 0;
        using (WaveStream blockAlignedStream =
            new BlockAlignReductionStream(
                WaveFormatConversionStream.CreatePcmStream(
                    new Mp3FileReader(ms))))
        {
            using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
            {
                waveOut.Init(blockAlignedStream);
                waveOut.PlaybackStopped += (sender, e) =>
                {
                    waveOut.Stop();
                };
                waveOut.Play();
                waiting = true;
                stop.WaitOne(timeout);
                waiting = false;
            }
        }
    }
}

で呼び出す:

var playThread = new Thread(timeout => PlayMp3FromUrl("http://translate.google.com/translate_tts?q=" + HttpUtility.UrlEncode(relatedLabel.Text), (int)timeout));
playThread.IsBackground = true;
playThread.Start(10000);

終了:

if (waiting)
    stop.Set();

ParameterizedThreadDelegate上記のコードでを使用しており、スレッドは。で開始されていることに注意してくださいplayThread.Start(10000);。10000は、再生されるオーディオの最大10秒を表すため、ストリームの再生にそれより長い時間がかかる場合は、微調整する必要があります。これが必要なのは、現在のバージョンのNAudio(v1.5.4.0)では、ストリームの再生がいつ完了するかを判断するのに問題があるように思われるためです。それは後のバージョンで修正されるかもしれません、あるいはおそらく私が見つけるのに時間がかからなかった回避策があります。

于 2012-02-11T23:52:20.863 に答える
2

トピックのスターター ソースを少し変更したので、完全に読み込まれていないファイルを再生できるようになりました。これは次のとおりです (これは単なるサンプルであり、開始点であることに注意してください。ここでいくつかの例外とエラー処理を行う必要があります)。

private Stream ms = new MemoryStream();
public void PlayMp3FromUrl(string url)
{
    new Thread(delegate(object o)
    {
        var response = WebRequest.Create(url).GetResponse();
        using (var stream = response.GetResponseStream())
        {
            byte[] buffer = new byte[65536]; // 64KB chunks
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                var pos = ms.Position;
                ms.Position = ms.Length;
                ms.Write(buffer, 0, read);
                ms.Position = pos;
            }
        }
    }).Start();

    // Pre-buffering some data to allow NAudio to start playing
    while (ms.Length < 65536*10)
        Thread.Sleep(1000);

    ms.Position = 0;
    using (WaveStream blockAlignedStream = new BlockAlignReductionStream(WaveFormatConversionStream.CreatePcmStream(new Mp3FileReader(ms))))
    {
        using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
        {
            waveOut.Init(blockAlignedStream);
            waveOut.Play();
            while (waveOut.PlaybackState == PlaybackState.Playing)
            {
                System.Threading.Thread.Sleep(100);
            }
        }
    }
}
于 2011-02-22T16:50:36.623 に答える
1

NAudio は WaveOutXXXX API をラップします。私はソースを見ていませんが、NAudio が waveOutWrite() 関数を呼び出しのたびに再生を自動的に停止しない方法で公開している場合、本当にやりたいことができるはずです。すべてのデータを受信する前にオーディオ ストリームを受信します。

waveOutWrite() 関数を使用すると、「先読み」して、オーディオの小さなチャンクを出力キューにダンプできます。Windows はチャンクを自動的にシームレスに再生します。コードは、圧縮されたオーディオ ストリームを取得し、その場で WAV オーディオの小さなチャンクに変換する必要があります。この部分は非常に困難です。私が今まで見たすべてのライブラリとコンポーネントは、一度にファイル全体を MP3 から WAV に変換します。おそらく唯一の現実的な可能性は、MP3 の代わりに WMA を使用してこれを行うことです。これは、マルチメディア SDK の周りに単純な C# ラッパーを記述できるためです。

于 2008-10-19T22:25:02.227 に答える
1

MP3 デコーダー ライブラリをラップし、.NET開発者がmpg123.netとして利用できるようにしました。

MP3 ファイルをPCMに変換し、 ID3タグを読み取るサンプルが含まれています。

于 2010-08-24T19:42:51.923 に答える
1

WebRequest から試したことはありませんが、Windows Media Player ActiveXコンポーネントと MediaElement ( WPFから) コンポーネントの両方で、MP3 ストリームの再生とバッファリングが可能です。

SHOUTcastストリームからのデータを再生するために使用しましたが、うまくいきました。ただし、提案されたシナリオで機能するかどうかはわかりません。

于 2008-11-12T20:18:25.783 に答える