문제

C#에는 오디오를 재생하는 방법이 있습니까 (예 : MP3)는 System.io.stream 예를 들어 데이터를 일시적으로 디스크에 저장하지 않고 WebRequest에서 계속 유지 되었습니까?


솔루션 나우 디오

의 도움으로 나우 디오 1.3 가능합니다.

  1. URL에서 MP3 파일을 MemoryStream에로드합니다.
  2. MP3 데이터가 완전히로드 된 후 파동 데이터로 변환
  3. 사용중인 웨이브 데이터를 재생합니다 나우 디오의 웨이브 클래스

절반로드 된 MP3 파일을 재생할 수있어서 좋았을 것입니다. 그러나 이것은 이로 인해 불가능한 것 같습니다. 나우 디오 도서관 디자인.

그리고 이것은 작업을 수행 할 기능입니다.

    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);
                    }
                }
            }
        }
    }
도움이 되었습니까?

해결책

편집 : 최근 버전의 Naudio의 변경 사항을 반영하도록 답변 업데이트

그것을 사용하는 것이 가능합니다 나우 디오 오픈 소스 .NET 오디오 라이브러리가 작성한. PC에서 변환을 수행하기 위해 ACM 코덱을 찾습니다. Naudio와 함께 제공된 MP3Filereader는 현재 소스 스트림 내에서 재배치 할 수있을 것으로 기대하고 있습니다 (MP3 프레임의 인덱스를 전면에 구축 함). 그러나 여전히 사용할 수 있습니다 MP3Frame 그리고 AcmMp3FrameDecompressor Naudio의 클래스는 MP3를 즉석에서 스트리밍했습니다.

내 블로그 설명에 기사를 게시했습니다 Naudio를 사용하여 MP3 스트림을 재생하는 방법. 본질적으로 당신은 하나의 스레드가 MP3 프레임을 다운로드하고, 압축을 눌러 저장하고 있습니다. BufferedWaveProvider. 그런 다음 다른 스레드는 다시 사용합니다 BufferedWaveProvider 입력으로.

다른 팁

그만큼 사운드 플레이어 수업은 이것을 할 수 있습니다. 당신이해야 할 일은 개울 스트림에 속성을 한 다음 전화하십시오 Play.

편집하다
그래도 MP3 파일을 재생할 수 있다고 생각하지 않습니다. .wav로 제한됩니다. 프레임 워크에 MP3 파일을 직접 재생할 수있는 것이 있는지 확실하지 않습니다. 내가 찾은 모든 것은 WMP 컨트롤을 사용하거나 DirectX와 상호 작용하는 것과 관련이 있습니다.

베이스 이것 만 할 수 있습니다. 데이터를 반환하는 메모리 또는 파일 대의원에서 바이트 []에서 재생하므로 재생을 시작하기에 충분한 데이터가있는 즉시 재생할 수 있습니다.

주제 스타터 소스를 약간 수정 했으므로 이제로드되지 않은 파일을 재생할 수 있습니다. 여기에 있습니다 (샘플 일 뿐이며 시작해야 할 시점입니다. 여기에서 예외 및 오류 처리를해야합니다).

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);
            }
        }
    }
}

Naudio는 WaveOutXXXX API를 감싸고 있습니다. 나는 소스를 보지 못했지만 Naudio가 각 통화에서 자동으로 재생을 중지하지 않는 방식으로 WaveOutWrite () 함수를 노출하면 실제로 원하는 것을 수행 할 수 있어야합니다. 모든 데이터를 받기 전에 오디오 스트림.

WaveOutWrite () 함수를 사용하면 "앞서 읽고"더 작은 오디오 덩어리를 출력 큐에 버릴 수 있습니다. Windows는 청크를 자동으로 재생합니다. 코드는 압축 오디오 스트림을 가져 와서 작은 wav 오디오 덩어리로 변환해야합니다. 이 부분은 정말 어려울 것입니다. 내가 본 모든 라이브러리와 구성 요소는 한 번에 전체 파일을 MP3-to-Wav 변환을 수행합니다. 아마도 당신의 유일한 현실적인 기회는 MP3 대신 WMA를 사용하여 이것을하는 것입니다. 멀티미디어 SDK 주위에 간단한 c# 랩퍼를 쓸 수 있기 때문입니다.

질문에 답하기 위해 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)의 현재 버전이 스트림이 재생되는시기를 결정하는 데 문제가있는 것처럼 보이기 때문에 이것은 필요합니다. 이후 버전으로 고정 될 수 있거나 아마도 시간을 내지 못한 해결 방법이있을 수 있습니다.

나는 MP3 디코더 라이브러리를 감싸고 그것을 사용할 수있게했다. .그물 개발자 mpg123.net.

MP3 파일을 변환 할 샘플이 포함되어 있습니다 PCM, 그리고 읽습니다 ID3 태그.

나는 비상업적 사용이 무료이며 잘 작동하기 때문에 항상 이와 같은 것에 FMOD를 사용했습니다.

즉, 나는 더 작은 것으로 전환하고 (fmod는 ~ 300k) 오픈 소스로 기꺼이 전환 할 것입니다. 슈퍼 보너스 포인트가 완전히 관리되면 .exe와 컴파일 / 합병 할 수 있고 다른 플랫폼에 대한 휴대 성을 얻기 위해 추가주의를 기울일 필요가 없습니다 ...

(FMOD는 휴대 성을 수행하지만 다른 플랫폼에 대해 다른 바이너리가 필요합니다)

나는 WebRequest에서 그것을 시도하지 않았지만 둘 다 윈도우 미디어 플레이어 ActiveX 그리고 미디어 요소 (에서 WPF) 구성 요소는 MP3 스트림을 재생하고 버퍼링 할 수 있습니다.

나는 그것을 사용하여 a에서 나오는 데이터를 재생합니다 외침 스트림과 그것은 훌륭하게 작동했습니다. 그러나 제안하는 시나리오에서 작동하는지 확실하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top