audiostream缓冲

我需要播放现场audiostream,实际上是收音机。 问题是我还需要pipe理20分钟的stream缓冲区。 据我了解,用android来实现并不容易。

首先我检查了MediaPlayer,但是它没有提供任何缓冲区pipe理的方法。 实际上你甚至不能直接设置缓冲区大小。

其次,我尝试使用本地文件pipe理缓冲区:逐步将stream下载到临时文件并切换它们。 但是当你想切换到下面的文件(改变MediaPlayer中的数据源)时,audio不会连续播放。 你可以听到短暂的中断。

最后的想法是使用stream代理。 通常用于播放Android版本低于8的stream。在stream代理中,您将创buildServerSocket,从audiostream中读取并写入播放器。 所以实际上我可以在那里pipe理缓冲。 我可以cachingstream,并写任何我想要的MediaPlayer。 但。 它不适用于Android 8。

我得到exception:由对等java.net.SocketException重置连接:由对等重置连接。 MediaPlayer 8不想从套接字读取数据。

因此我有两个问题:1)实现stream缓冲的其他方法是什么? 2)如何适应android 8的StreamProxy?

任何想法都表示赞赏。

谢谢

Solutions Collecting From Web of "audiostream缓冲"

我使用与NPR项目相同的StreamProxy – https://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java

所以它得到原始的audiostream:

String url = request.getRequestLine().getUri(); HttpResponse realResponse = download(url); ... InputStream data = realResponse.getEntity().getContent(); 

并从这个stream写入客户端套接字:

  byte[] buff = new byte[1024 * 50]; while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) { client.getOutputStream().write(buff, 0, readBytes); } 

(您可以从上面的链接获得完整的代码。)

最后,他们如何初始化播放器(PlaybackService):

  if (stream && sdkVersion < 8) { if (proxy == null) { proxy = new StreamProxy(); proxy.init(); proxy.start(); } String proxyUrl = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), url); playUrl = proxyUrl; } ... mediaPlayer.setDataSource(playUrl); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.prepareAsync(); 

所以他们检查SDK版本。 但是,如果我省略这个检查,并使用代理SDK 8以及我得到一个例外。 MediaPlayer甚至不会尝试读取stream是很奇怪的:

 12-30 15:09:41.576: DEBUG/StreamProxy(266): downloading... 12-30 15:09:41.597: DEBUG/StreamProxy(266): reading headers 12-30 15:09:41.597: DEBUG/StreamProxy(266): headers done 12-30 15:09:41.647: DEBUG/StreamProxy(266): writing to client 12-30 15:09:41.857: INFO/AwesomePlayer(34): mConnectingDataSource->connect() returned - 1007 12-30 15:09:41.857: ERROR/MediaPlayer(266): error (1, -1007) 12-30 15:09:41.867: ERROR/MediaPlayer(266): Error (1,-1007) 12-30 15:09:41.867: WARN/AudioService(266): onError(1, -1007) 12-30 15:09:41.867: WARN/AudioService(266): MediaPlayer refused to play current item. Bailing on prepare. 12-30 15:09:41.867: WARN/AudioService(266): onComplete() 12-30 15:09:42.097: ERROR/StreamProxy(266): Connection reset by peer java.net.SocketException: Connection reset by peer at org.apache.harmony.luni.platform.OSNetworkSystem.writeSocketImpl(Native Method) at org.apache.harmony.luni.platform.OSNetworkSystem.write(OSNetworkSystem.java:723) at org.apache.harmony.luni.net.PlainSocketImpl.write(PlainSocketImpl.java:578) at org.apache.harmony.luni.net.SocketOutputStream.write(SocketOutputStream.java:59) at com.skyblue.service.media.StreamProxy.processRequest(StreamProxy.java:204) at com.skyblue.service.media.StreamProxy.run(StreamProxy.java:103) at java.lang.Thread.run(Thread.java:1096) 

MediaPlayer似乎变得更聪明了。 如果我传递这样的url"http://127.0.0.1:%d/%s"它不仅要获得字节,而且要获得“完整的”http响应。

另外我想知道是否有其他的方法来实现缓冲? 据我所知,MediaPlayer只消费文件和url。 解决scheme与文件不起作用。 所以我必须使用套接字进行stream传输。

谢谢

我只是testing了下面的修复,它的工作原理。 这个问题是由StreamProxyprocessRequest()方法头文件中使用的“\ n”造成的。 将其更改为“\ r \ n”应使错误消失。

至于实现自定义stream媒体,我过去曾经使用过这个,尽pipe它似乎主要用于无限制的stream媒体广播。 http://blog.pocketjourney.com/2009/12/27/android-streaming-mediaplayer-tutorial-updated-to-v1-5-cupcake/

当您寻找或跳过或连接丢失,MediaPlayer不断重新连接到代理服务器时,必须在获取客户端的请求和范围(int)后,使用状态206发送此响应。

 String headers += "HTTP/1.1 206 Partial Content\r\n"; headers += "Content-Type: audio/mpeg\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Content-Length: " + (fileSize-range) + "\r\n"; headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n"; headers += "\r\n"; 

当你从MediaPlayer接收到一个HTTP头中不包含Range的请求时,它会请求一个新的stream文件,在这种情况下,你的响应头应该是这样的:

 String headers = "HTTP/1.1 200 OK\r\n"; headers += "Content-Type: audio/mpeg\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Content-Length: " + fileSize + "\r\n"; headers += "\r\n"; 

请享用!

来自SDK 8的Mediaplayer将无法读取代理url。 但基于我目前的工作,这是不同的设备。 在我的三星ACE(SDK 8)的代理连接工作正常,但在我的HTC Incredible S,代理连接会给你一样的问题,你有。 直接连接到audiostream可以正常工作,但是这会导致某些设备(如冲刺中的EVO)出现闪烁和嗡嗡声。

你有没有得到这个问题的决议? 你是怎么处理的?

-Hari

我意识到这个问题就像5岁,但万一其他人在stream浪:ExoPlayer是来自谷歌的图书馆,让你更多的控制缓冲区大小的选项。

  //DefaultUriDataSource – For playing media that can be either local or loaded over the network. DefaultUriDataSource dataSource = new DefaultUriDataSource(WgtechApplication.getAppContext(), Util.getUserAgent(WgtechApplication.getAppContext(), WgtechApplication.class.getSimpleName())); Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE); //ExtractorSampleSource – For formats such as MP3, M4A, MP4, WebM, MPEG-TS and AAC. ExtractorSampleSource sampleSource = new ExtractorSampleSource(Uri.parse(RADIO_STREAMING_URL), dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE); player.prepare(new MediaCodecAudioTrackRenderer(sampleSource)); 

这是我创build的一个小项目,用来学习如何使用它。 https://github.com/feresr/MyMediaPlayer

http://developer.android.com/guide/topics/media/exoplayer.html https://github.com/google/ExoPlayer