Existe-t-il un moyen en C # de lire de l'audio (par exemple, MP3) directement à partir d'un System.IO.Stream qui, par exemple, a été renvoyé à partir d'un WebRequest sans enregistrer temporairement les données sur le disque?
Solution avec NAudio
Avec l'aide de NAudio 1.3, il est possible de:
- Charger un fichier MP3 depuis une URL dans un MemoryStream
- Convertissez les données MP3 en données wave après leur chargement complet
- La lecture des données d'onde en utilisant NAudio classe WaveOut s »
Cela aurait été bien de pouvoir même lire un fichier MP3 à moitié chargé, mais cela semble impossible en raison de la conception de la bibliothèque NAudio .
Et c'est la 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);
}
}
}
}
}
Réponses:
Edit: Réponse mise à jour pour refléter les changements dans les versions récentes de NAudio
C'est possible en utilisant la bibliothèque audio open source .NET NAudio que j'ai écrite. Il recherche un codec ACM sur votre PC pour effectuer la conversion. Le Mp3FileReader fourni avec NAudio s'attend actuellement à pouvoir se repositionner dans le flux source (il crée un index des images MP3 à l'avant), il n'est donc pas approprié pour le streaming sur le réseau. Cependant, vous pouvez toujours utiliser les classes
MP3Frame
etAcmMp3FrameDecompressor
dans NAudio pour décompresser le MP3 diffusé à la volée.J'ai publié un article sur mon blog expliquant comment lire un flux MP3 à l'aide de NAudio . Essentiellement, vous avez un thread qui télécharge des images MP3, les décompresse et les stocke dans un fichier
BufferedWaveProvider
. Un autre thread est ensuite lu en utilisant leBufferedWaveProvider
comme entrée.la source
La classe SoundPlayer peut le faire. Il semble que tout ce que vous avez à faire est de définir sa propriété Stream sur le flux, puis d'appeler
Play
.edit
Je ne pense pas qu'il puisse lire les fichiers MP3 cependant; il semble limité à .wav. Je ne suis pas certain qu'il y ait quelque chose dans le cadre qui puisse lire directement un fichier MP3. Tout ce que je trouve à ce sujet implique l'utilisation d'un contrôle WMP ou l'interaction avec DirectX.
la source
La basse peut faire exactement cela. Lecture à partir de l'octet [] en mémoire ou d'un fichier à travers les délégués où vous renvoyez les données, de sorte que vous pouvez jouer dès que vous avez suffisamment de données pour démarrer la lecture.
la source
J'ai légèrement modifié la source de démarrage de la rubrique, afin qu'elle puisse maintenant lire un fichier pas entièrement chargé. Le voici (notez que ce n'est qu'un exemple et qu'il s'agit d'un point de départ; vous devez faire une gestion des exceptions et des erreurs ici):
la source
J'ai modifié la source publiée dans la question pour autoriser l'utilisation avec l'API TTS de Google afin de répondre à la question ici :
Invoquer avec:
Terminer avec:
Notez que j'utilise le
ParameterizedThreadDelegate
dans le code ci-dessus et que le fil est démarré avecplayThread.Start(10000);
. Le 10000 représente un maximum de 10 secondes d'audio à lire, il devra donc être modifié si votre flux prend plus de temps à jouer. Cela est nécessaire car la version actuelle de NAudio (v1.5.4.0) semble avoir un problème pour déterminer quand le flux est terminé. Il peut être corrigé dans une version ultérieure ou peut-être y a-t-il une solution de contournement que je n'ai pas pris le temps de trouver.la source
NAudio encapsule 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 à jouer le flux audio avant que vous ayez reçu toutes les données.
L'utilisation de la fonction waveOutWrite () vous permet de «lire à l'avance» et de vider de plus petits morceaux d'audio dans la file d'attente de sortie - Windows lira 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 jamais vus effectuent une conversion MP3 en WAV un fichier entier à la fois. Votre seule chance réaliste est probablement de le faire en utilisant WMA au lieu de MP3, car vous pouvez écrire de simples wrappers C # autour du SDK multimédia.
la source
J'ai enveloppé la bibliothèque de décodeurs MP3 et l'ai rendue disponible pour les développeurs .NET sous le nom mpg123.net .
Les exemples pour convertir les fichiers MP3 en PCM et lire les balises ID3 sont inclus .
la source
Je ne l'ai pas essayé à partir d'un WebRequest, mais à la fois le Windows Media Player ActiveX et le MediaElement (de WPF composants ) sont capables de lire et de mettre en mémoire tampon les flux MP3.
Je l'utilise pour lire des données provenant d'un flux 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.
la source
J'ai toujours utilisé FMOD pour des choses comme celle-ci car il est gratuit pour un usage non commercial et fonctionne bien.
Cela dit, je passerais volontiers à quelque chose de plus petit (le FMOD est ~ 300k) et open-source. Super points bonus s'il est entièrement géré afin que je puisse le compiler / fusionner avec mon .exe et ne pas avoir à faire très attention pour obtenir la portabilité vers d'autres plates-formes ...
(FMOD fait aussi la portabilité, mais vous auriez évidemment besoin de différents binaires pour différentes plates-formes)
la source