Воспроизведение аудио из потока с помощью C #

Есть ли способ в C # воспроизводить аудио (например, MP3) непосредственно с System.IO.Stream , который, например, был восстановлен из WebRequest без временного сохранения данных на диск?


Решение с помощью NAudio

С помощью NAudio 1.3 можно:

  1. Загрузить файл MP3 из URL-адреса в MemoryStream
  2. Преобразование данных MP3 в волновые данные после их полной загрузки.
  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);
                    }
                }
            }
        }
    }
90 голосов | спросил Martin 9 +04002008-10-09T00:19:23+04:00312008bEurope/MoscowThu, 09 Oct 2008 00:19:23 +0400 2008, 00:19:23

9 ответов


0

Изменить. Ответ обновлен с учетом изменений в последних версиях NAudio

Это возможно с помощью NAudio библиотеки аудио с открытым исходным кодом .NET, которую я написал. Он ищет кодек ACM на вашем компьютере, чтобы сделать преобразование. Mp3FileReader, поставляемый с NAudio, в настоящее время ожидает возможности изменения положения в исходном потоке (он создает индекс кадров MP3 заранее), поэтому он не подходит для потоковой передачи по сети. Однако вы все равно можете использовать MP3Frame и AcmMp3FrameDecompressor классы в NAudio для распаковки потокового MP3 на лету.

Я разместил в своем блоге статью, объясняющую как воспроизвести поток MP3 с помощью NAudio . По сути, у вас есть один поток, загружающий фреймы MP3, распаковывающий их и сохраняющий их в BufferedWaveProvider. Затем другой поток воспроизводится с использованием BufferedWaveProvider в качестве входных данных.

ответил Mark Heath 9 +04002008-10-09T01:44:46+04:00312008bEurope/MoscowThu, 09 Oct 2008 01:44:46 +0400 2008, 01:44:46
0

SoundPlayer может это сделать. Похоже, все, что вам нужно сделать, это установить его свойство Stream для потока, а затем вызвать Play.

изменить
Я не думаю, что он может воспроизводить файлы MP3, хотя; кажется ограниченным .wav. Я не уверен, есть ли что-то в рамках, которое может воспроизводить файл MP3 напрямую. Все, что я нахожу об этом, включает использование элемента управления WMP или взаимодействие с DirectX.

ответил OwenP 9 +04002008-10-09T00:42:06+04:00312008bEurope/MoscowThu, 09 Oct 2008 00:42:06 +0400 2008, 00:42:06
0

Бас может сделать это. Воспроизведение с байта [] в памяти или сквозных файловых делегатов, куда вы возвращаете данные, так что вы можете воспроизводить их, как только у вас будет достаточно данных, чтобы начать воспроизведение.

ответил 22 +04002008-10-22T14:59:39+04:00312008bEurope/MoscowWed, 22 Oct 2008 14:59:39 +0400 2008, 14:59:39
0

Я немного изменил исходный источник темы, чтобы теперь он мог воспроизводить не полностью загруженный файл. Вот оно (обратите внимание, что это всего лишь пример, с которого нужно начинать; здесь нужно сделать некоторые исключения и обработать ошибки):

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);
            }
        }
    }
}
ответил ReVolly 22 FebruaryEurope/MoscowbTue, 22 Feb 2011 19:50:36 +0300000000pmTue, 22 Feb 2011 19:50:36 +030011 2011, 19:50:36
0

NAudio оборачивает API-интерфейс WaveOutXXXX. Я не смотрел на источник, но если NAudio предоставляет функцию waveOutWrite () таким образом, что она не останавливает воспроизведение автоматически при каждом вызове, то вы сможете делать то, что вам действительно нужно, то есть начинать воспроизведение аудиопоток до того, как вы получили все данные.

Использование функции waveOutWrite () позволяет вам «читать вперед» и выгружать меньшие порции аудио в очередь вывода - Windows автоматически автоматически воспроизводит порции. Ваш код должен принимать сжатый аудиопоток и преобразовывать его в небольшие фрагменты WAV-аудио на лету; эта часть была бы действительно трудной - все библиотеки и компоненты, которые я когда-либо видел, делают преобразование MP3 в WAV целый файл за один раз. Вероятно, ваш единственный реальный шанс - сделать это, используя WMA вместо MP3, потому что вы можете написать простые обертки C # вокруг мультимедийного SDK.

ответил MusiGenesis 20 +04002008-10-20T02:25:02+04:00312008bEurope/MoscowMon, 20 Oct 2008 02:25:02 +0400 2008, 02:25:02
0

Я настроил источник, размещенный в вопросе, чтобы разрешить использование с Google TTS API, чтобы ответить на вопрос здесь :

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), похоже, имеет проблемы с определением, когда закончится воспроизведение потока. Это может быть исправлено в более поздней версии или, возможно, есть обходной путь, который я не нашел времени.

ответил M.Babcock 12 FebruaryEurope/MoscowbSun, 12 Feb 2012 03:52:20 +0400000000amSun, 12 Feb 2012 03:52:20 +040012 2012, 03:52:20
0

Я обернул библиотеку MP3-декодеров и сделал ее доступной для .NET разработчиков как mpg123.net .

Прилагаются примеры преобразования файлов MP3 в PCM и чтения теги ID3 .

ответил Daniel Mošmondor 24 PM000000110000005131 2010, 23:42:51
0

Я всегда использовал FMOD для подобных вещей, потому что он бесплатный для некоммерческого использования и хорошо работает.

Тем не менее, я бы с радостью переключился на что-то меньшее (FMOD ~ 300k) и с открытым исходным кодом. Супер бонусные баллы, если они полностью управляются так, что я могу скомпилировать /объединить их с моим .exe и не нужно прилагать дополнительные усилия для переносимости на другие платформы ...

(FMOD тоже переносит, но вам, очевидно, потребуются разные двоичные файлы для разных платформ)

ответил Roman Starkov 7 62009vEurope/Moscow11bEurope/MoscowSat, 07 Nov 2009 12:16:25 +0300 2009, 12:16:25
0

Я не пробовал его из веб-запроса, но оба проигрыватель Windows Media ActiveX и MediaElement (из WPF ) способны воспроизводить и буферизовать потоки MP3.

Я использую его для воспроизведения данных, поступающих из SHOUTcast потока, и это отлично работает. Однако я не уверен, что это сработает в предложенном вами сценарии.

ответил Ramiro Berrelleza 12 32008vEurope/Moscow11bEurope/MoscowWed, 12 Nov 2008 23:18:25 +0300 2008, 23:18:25

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132