Existe uma maneira em C # de reproduzir áudio (por exemplo, MP3) diretamente de um System.IO.Stream que, por exemplo, foi retornado de um WebRequest sem salvar os dados temporariamente no disco?
Solução com NAudio
Com a ajuda do NAudio 1.3 é possível:
- Carregue um arquivo MP3 de um URL em um MemoryStream
- Converta dados de MP3 em dados de onda depois de carregados completamente
- Reproduzir os dados de ondas usando NAudio classe WaveOut 's
Seria bom poder tocar até mesmo um arquivo MP3 carregado pela metade, mas isso parece impossível devido ao design da biblioteca do NAudio .
E esta é a função que fará o trabalho:
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);
}
}
}
}
}
Respostas:
Editar: Resposta atualizada para refletir as mudanças nas versões recentes do NAudio
É possível usar a biblioteca de áudio .NET de código aberto NAudio que escrevi. Ele procura um codec ACM em seu PC para fazer a conversão. O Mp3FileReader fornecido com o NAudio atualmente espera ser capaz de se reposicionar dentro do stream de origem (ele cria um índice de quadros MP3 antecipadamente), portanto, não é apropriado para streaming pela rede. No entanto, você ainda pode usar as classes
MP3Frame
eAcmMp3FrameDecompressor
no NAudio para descompactar MP3 transmitido instantaneamente.Publiquei um artigo no meu blog explicando como reproduzir um fluxo de MP3 usando o NAudio . Basicamente, você tem um thread baixando quadros de MP3, descompactando-os e armazenando-os em um arquivo
BufferedWaveProvider
. Outro thread é reproduzido usando oBufferedWaveProvider
como entrada.fonte
A classe SoundPlayer pode fazer isso. Parece que tudo o que você precisa fazer é definir sua propriedade Stream para o stream e chamar
Play
.editar
Eu não acho que ele possa tocar arquivos MP3; parece limitado a .wav. Não tenho certeza se há algo na estrutura que pode reproduzir um arquivo MP3 diretamente. Tudo o que descobri sobre isso envolve o uso de um controle WMP ou a interação com o DirectX.
fonte
Bass pode fazer exatamente isso. Jogue a partir do Byte [] na memória ou através de delegados de arquivo onde você retorna os dados, para que possa jogar assim que tiver dados suficientes para iniciar a reprodução.
fonte
Modifiquei ligeiramente a fonte do tópico inicial, para que agora possa reproduzir um arquivo não totalmente carregado. Aqui está (observe que é apenas uma amostra e um ponto de partida; você precisa fazer alguma exceção e tratamento de erros aqui):
fonte
Eu ajustei a fonte postada na pergunta para permitir o uso com a API TTS do Google, a fim de responder à pergunta aqui :
Invoque com:
Terminar com:
Observe que estou usando
ParameterizedThreadDelegate
no código acima e o thread é iniciado complayThread.Start(10000);
. O 10000 representa um máximo de 10 segundos de áudio a ser reproduzido, portanto, será necessário ajustá-lo se a transmissão demorar mais do que isso para ser reproduzida. Isso é necessário porque a versão atual do NAudio (v1.5.4.0) parece ter um problema para determinar quando a reprodução do stream termina. Pode ser corrigido em uma versão posterior ou talvez haja uma solução alternativa que eu não tive tempo para encontrar.fonte
NAudio envolve a API WaveOutXXXX. Eu não olhei para a fonte, mas se o NAudio expõe a função waveOutWrite () de uma forma que não interrompe automaticamente a reprodução em cada chamada, então você deve ser capaz de fazer o que realmente deseja, que é começar a reproduzir o fluxo de áudio antes de você receber todos os dados.
O uso da função waveOutWrite () permite que você "leia adiante" e despeje pedaços menores de áudio na fila de saída - o Windows reproduzirá os pedaços automaticamente. Seu código teria que pegar o fluxo de áudio compactado e convertê-lo em pequenos pedaços de áudio WAV imediatamente; esta parte seria realmente difícil - todas as bibliotecas e componentes que eu já vi fazem a conversão de MP3 em WAV um arquivo inteiro de cada vez. Provavelmente, sua única chance realista é fazer isso usando WMA em vez de MP3, porque você pode escrever invólucros C # simples em torno do SDK de multimídia.
fonte
Eu envolvi a biblioteca do decodificador de MP3 e a disponibilizei para desenvolvedores .NET como mpg123.net .
Estão incluídos os exemplos para converter arquivos MP3 em PCM e ler tags ID3 .
fonte
Eu não tentei de um WebRequest, mas os componentes ActiveX do Windows Media Player e MediaElement (do WPF ) são capazes de reproduzir e armazenar em buffer streams MP3.
Eu o uso para reproduzir dados provenientes de um fluxo de SHOUTcast e funcionou muito bem. No entanto, não tenho certeza se funcionará no cenário que você propõe.
fonte
Sempre usei FMOD para coisas assim porque é gratuito para uso não comercial e funciona bem.
Dito isso, eu ficaria feliz em mudar para algo menor (FMOD é ~ 300k) e de código aberto. Super pontos de bônus se for totalmente gerenciado para que eu possa compilá-lo / mesclá-lo com meu .exe e não ter que tomar cuidado extra para obter portabilidade para outras plataformas ...
(FMOD também oferece portabilidade, mas você obviamente precisa de binários diferentes para plataformas diferentes)
fonte