如何使用临时文件流mp3文件? [英] How to stream an mp3 file using a temporary file?

查看:65
本文介绍了如何使用临时文件流mp3文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在播放Mp3流媒体.要从url流mp3文件,我想使用一个临时文件.但是尝试读取和写入相同的文件会为File.ReadAllBytes抛出IOException,因为该文件正在使用中.我该如何解决这个问题?

I am working an Mp3 streamer. To stream mp3 file from url, I want to use a temporary file. But trying to read and write the same file throws IOException for File.ReadAllBytes because the file is in use. How can I get throught this problem?

long pos = 0;
string path = pathtothetempfile;
MemoryStream ms = new MemoryStream();
FileStream fs = new FileStream(path, FileMode.Create, 
                              FileAccess.ReadWrite, FileShare.ReadWrite);

do
{
   bytesRead = responseStream.Read(buffer, 0, buffer.Length);

   fs.Write(buffer, 0, bytesRead);
   fs.Flush();

   byte[] tempBuffer = File.ReadAllBytes(path);

   pos = ms.Position;
   ms = new MemoryStream(tempBuffer);
   ms.Position = pos;

   frame = Mp3Frame.LoadFromStream(ms);

   //....codes....
}
while(bytesRead > 0)

推荐答案

我通过大量搜索找到了答案.该答案包含用于控制Mp3的NAudio,并且通过部分读取流来实现RAM友好.我将它分享给其他有相同问题的人.

I have found an answer by myself by searching so much. This answer contains NAudio to control the Mp3 and it is RAM friendly by reading stream partially. I am sharing it for other people who has the same problem.

    WaveOut waveOut;
    AcmMp3FrameDecompressor decompressor;
    BufferedWaveProvider provider;
    bool firstPlay = true;

    public void Play()
    {
        Task.Run(() =>
        {

            #region WebRequest creator
            HttpWebResponse response = null;
            if (avgbytes < 0)
            {
                HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
                req.AllowAutoRedirect = true;
                req.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0";
                response = req.GetResponse() as HttpWebResponse;
                contentLength = response.ContentLength;
            }
            else
                response = Helper.CreateAudioWebRequest(url, currentTime, avgbytes)
                                 .GetResponse() as HttpWebResponse;

            Stream responseStream = response.GetResponseStream();
            #endregion

            #region Local Variables
            byte[] buffer = new byte[17 * 1024];
            byte[] bigBuffer = new byte[response.ContentLength];
            int bytesRead = 0;
            long pos = 0;
            long postotal = 0;
            string path = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".mp3";
            #endregion

            Mp3Frame frame;
            FileStream fs = new FileStream(path,
                FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
            do
            {
                bytesRead = responseStream.Read(buffer, 0, buffer.Length);
                fs.Write(buffer, 0, bytesRead);
                fs.Flush();
                using (MemoryStream ms = new MemoryStream(ReadPartial(fs, postotal, 1024 * 10)))
                {
                    ms.Position = 0;
                    frame = Mp3Frame.LoadFromStream(ms);
                    if (frame == null)
                    {
                        continue;
                    }
                    pos = ms.Position;
                    postotal += pos;
                }


                #region First Play
                if (firstPlay)
                {
                    avgbytes = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
                frame.FrameLength, frame.BitRate).AverageBytesPerSecond;
                    duration = (int)(response.ContentLength * 1d / avgbytes);
                    firstPlay = false;
                }
                #endregion

                #region Decompress Frame
                if (decompressor == null)
                {
                    decompressor = CreateFrameDecompressor(frame) as AcmMp3FrameDecompressor;
                    provider = new BufferedWaveProvider(decompressor.OutputFormat);
                    provider.BufferDuration = TimeSpan.FromSeconds(20);
                }
                int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
                #endregion

                #region BufferedWaveProvider Area
                if (IsBufferNearlyFull(provider))
                {
                    Thread.Sleep(500);
                }
                provider.AddSamples(buffer, 0, decompressed);
                #endregion


                if (provider.BufferedDuration.TotalSeconds >= 2 && waveOut == null)
                {
                    waveOut = new WaveOut();
                    waveOut.Init(provider);
                    waveOut.Play();
                }
            }
            while (postotal != contentLength || bytesRead > 0 || waveOut==null || 
                        (waveOut != null && waveOut.PlaybackState == PlaybackState.Playing));

        });
    }

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

        if (stream.CanSeek)
        {
            originalPosition = stream.Position;
            stream.Position = offset;
        }

        try
        {
            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)
                {
                    stream.Position = originalPosition;
                    break;
                }
            }
            if (totalBytesRead < count)
            {
                byte[] temp = new byte[totalBytesRead];
                Buffer.BlockCopy(total, 0, temp, 0, totalBytesRead);
                stream.Position = originalPosition;
                return temp;
            }
            return total;
        }
        finally
        {
            if (stream.CanSeek)
            {
                stream.Position = originalPosition;
            }
        }
    }

    private bool IsBufferNearlyFull(BufferedWaveProvider bufferedWaveProvider)
    {
        return bufferedWaveProvider != null &&
               bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes
               < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4;
    }
    private static IMp3FrameDecompressor CreateFrameDecompressor(Mp3Frame frame)
    {
        WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
            frame.FrameLength, frame.BitRate);
        return new AcmMp3FrameDecompressor(waveFormat);
    }

这篇关于如何使用临时文件流mp3文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆