102 votes

Jouer de l'audio à partir d'un flux en utilisant C#

Existe-t-il un moyen en C# de lire un fichier audio (par exemple, MP3) directement à partir d'un fichier System.IO.Stream qui, par exemple, a été obtenue à partir d'une demande Web sans sauvegarder temporairement les données sur le disque ?


Solution avec NAudio

Avec l'aide de NAudio 1.3 il est possible de :

  1. Chargement d'un fichier MP3 à partir d'une URL dans un MemoryStream
  2. Convertir les données MP3 en données wave après leur chargement complet
  3. Lecture des données d'ondes à l'aide de NAudio La classe WaveOut

Il aurait été agréable de pouvoir lire un fichier MP3 à moitié chargé, mais cela semble impossible en raison de l'absence d'un système de gestion de l'information. NAudio la conception de la bibliothèque.

C'est cette fonction qui fera le travail :

    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 votes

Il est bon de voir que vous avez réussi à le faire fonctionner. Il n'y a pas beaucoup de travail à faire pour qu'il soit lu correctement pendant la diffusion en continu. Le principal problème est que le Mp3FileReader s'attend actuellement à connaître la longueur à l'avance. Je vais essayer d'ajouter une démo pour la prochaine version de NAudio.

0 votes

@Mark Heath as-tu déjà résolu le problème et ajouté la démo dans la version actuelle de NAudio ou est-elle toujours dans ta pipline ?

0 votes

J'ai peur que ce ne soit pas encore le cas, mais grâce aux changements apportés dans NAudio 1.3, il ne sera pas nécessaire de faire beaucoup d'ajustements pour que cela fonctionne.

1voto

MusiGenesis Points 49273

NAudio intègre l'API WaveOutXXXX. Je n'ai pas regardé la source, mais si NAudio expose la fonction waveOutWrite() d'une manière qui n'arrête pas automatiquement la lecture à chaque appel, alors vous devriez pouvoir faire ce que vous voulez vraiment, c'est-à-dire commencer à lire le flux audio avant d'avoir reçu toutes les données.

L'utilisation de la fonction waveOutWrite() vous permet de "lire à l'avance" et de déverser de plus petits morceaux d'audio dans la file d'attente de sortie - Windows jouera automatiquement les morceaux de manière transparente. Votre code devrait prendre le flux audio compressé et le convertir en petits morceaux d'audio WAV à la volée ; cette partie serait vraiment difficile - toutes les bibliothèques et tous les composants que j'ai vus convertissent les MP3 en WAV un fichier entier à la fois. Votre seule chance réaliste est probablement d'utiliser WMA au lieu de MP3, car vous pouvez écrire de simples wrappers C# autour du SDK multimédia.

1voto

Ramiro Berrelleza Points 1017

Je n'ai pas essayé de le faire à partir d'une WebRequest, mais tant la Lecteur Windows Media ActiveX et le MediaElement (de WPF ) sont capables de lire et de mettre en mémoire tampon des flux MP3.

Je l'utilise pour lire les données provenant d'un SHOUTcast et cela a très bien fonctionné. Cependant, je ne suis pas sûr que cela fonctionnera dans le scénario que vous proposez.

1voto

Daniel Mošmondor Points 10926

J'ai intégré la bibliothèque du décodeur MP3 et je l'ai mise à la disposition des utilisateurs. .NET les développeurs comme mpg123.net .

Sont inclus les échantillons permettant de convertir les fichiers MP3 en PCM et lire ID3 étiquettes.

0voto

milot Points 859

J'ai écrit une bibliothèque .NET en C# comme un wrapper pour MCI (Multimedia Controller Interface) P/Invokes, si quelqu'un en a besoin, laissez-moi un commentaire, je vous enverrai le code et l'assemblage.

0voto

romkyns Points 17295

J'ai toujours utilisé FMOD pour ce genre de choses parce qu'il est gratuit pour une utilisation non commerciale et qu'il fonctionne bien.

Cela dit, je passerais volontiers à quelque chose de plus petit (FMOD fait ~300k) et de libre. Super points bonus si c'est entièrement géré de sorte que je puisse le compiler / fusionner avec mon .exe et ne pas avoir à prendre des précautions supplémentaires pour obtenir la portabilité sur d'autres plates-formes...

(FMOD permet également la portabilité, mais il faut évidemment des binaires différents pour les différentes plates-formes).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X