0

我正在使用 NAudio 库实时流式传输 mp3。我已经准备了一个代码来做到这一点,它通常运行良好,除非另一个媒体正在另一个进程中播放(例如 Youtube、本地 mp3 播放器..),. 那个时候,mp3是口吃的。我不知道为什么会这样。如何解决这个问题呢?

在控制台应用程序中流式传输的代码。复制粘贴,你可以试试。

    static void Main(string[] args)
    {
        AcmMp3FrameDecompressor decompressor = null;
        BufferedWaveProvider provider = null;
        WaveFormat mp3format = null;
        WaveOut waveOut = new WaveOut();
        long size = 0;
        byte[] decbuffer = new byte[50 * 1024];

        //I am using mp3 links converted by listentoyoutube.com 
        //But links will be expired, so I didnt put any

        string url = "";
        string path = Path.Combine(Path.GetTempPath(), "test.mp3");

        CheckUrlandCreateTools(url, ref decompressor, ref mp3format, ref size);

        FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
        HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
        HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
        Stream remote = resp.GetResponseStream();
        Mp3Frame frame = null;
        MemoryStream ms = null;
        byte[] buffer = new byte[1024];
        int read = 0;
        long offset = 0;
        provider = new BufferedWaveProvider(decompressor.OutputFormat);
        provider.BufferDuration = TimeSpan.FromSeconds(20);
        waveOut.Init(provider);
        waveOut.Play();
        while (waveOut.PlaybackState == PlaybackState.Playing)
        {
            if((read = remote.Read(buffer, 0, buffer.Length)) > 0)
            fs.Write(buffer, 0, read);
            fs.Flush();
            ms = new MemoryStream(ReadStreamPartially(fs, offset, 100 * 1024));
            try
            {
                frame = Mp3Frame.LoadFromStream(ms);
                if (frame == null)
                    continue;
            }
            catch
            {
                continue;
            }

            offset += ms.Position;
            int decompressed = decompressor.DecompressFrame(frame, decbuffer, 0);
            provider.AddSamples(decbuffer, 0, decompressed);
            if (IsBufferNearlyFull(provider))
                Thread.Sleep(500);
        }
    }

    public static byte[] ReadStreamPartially(System.IO.FileStream stream,
                                        long offset, long count)
    {
        long originalPosition = stream.Position;
        stream.Position = offset;

        byte[] readBuffer = new byte[4096];
        byte[] total = new byte[count];
        int totalBytesRead = 0;
        int byteRead;

        while ((byteRead = stream.ReadByte()) != -1)
        {
            Buffer.SetByte(total, totalBytesRead, (byte)byteRead);
            totalBytesRead++;
            if (totalBytesRead == count)
                break;
        }
        if (totalBytesRead < count)
        {
            byte[] temp = new byte[totalBytesRead];
            Buffer.BlockCopy(total, 0, temp, 0, totalBytesRead);
            stream.Position = originalPosition;
            return temp;
        }
        stream.Position = originalPosition;
        return total;
    }
    public static bool IsBufferNearlyFull(BufferedWaveProvider bufferedWaveProvider)
    {
        return bufferedWaveProvider != null &&
               bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes
               < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4;
    }
    public static void CheckUrlandCreateTools(string url, ref AcmMp3FrameDecompressor decompressor,
        ref WaveFormat format, ref long size)
    {
        HttpWebRequest req = SendRequest(url, 0, 0);
        HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
        size = resp.ContentLength;
        Stream str = resp.GetResponseStream();
        byte[] buffer = new byte[1024];
        byte[] storer = new byte[1024 * 100];
        int bytesRead = 0;
        int total = 0;
        while ((bytesRead = str.Read(buffer, 0, buffer.Length)) > 0)
        {
            Buffer.BlockCopy(buffer, 0, storer, total, bytesRead);
            total += bytesRead;

            Mp3Frame frame = Mp3Frame.LoadFromStream(new MemoryStream(storer));
            if (frame == null) continue;

            format = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
            frame.FrameLength, frame.BitRate);
            decompressor = new AcmMp3FrameDecompressor(format);

            req.Abort();
            resp.Close();
            str.Close();

            break;
        }
    }

    public static HttpWebRequest SendRequest(string url, long from, long to)
    {
        HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
        req.Credentials = CredentialCache.DefaultCredentials;
        req.Accept = "*/*";
        req.KeepAlive = false;
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
        req.AllowAutoRedirect = true;
        if (to > 0)
            req.AddRange(from, to);
        return req;
    }
}
4

0 回答 0