流式传输到 Android MediaPlayer

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2511045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:07:44  来源:igfitidea点击:

Streaming to the Android MediaPlayer

androidhttpstreammedia-playerandroid-mediaplayer

提问by Rob Szumlakowski

I'm trying to write a light-weight HTTPserver in my app to feeddynamically generated MP3data to the built-in AndroidMediaPlayer. I am not permitted to store my content on the SD card.

我正在尝试HTTP在我的应用程序中编写一个轻量级服务器来feed动态生成的MP3数据到内置的AndroidMediaPlayer. 我不允许将我的内容存储在SD card.

My input data is essentially of an infinite length. I tell MediaPlayerthat its data source should basically be something like "http://localhost/myfile.mp3". I've a simple server set up that waits for MediaPlayerto make this request. However, MediaPlayerisn't very cooperative. At first, it makes an HTTP GETand tries to grab the whole file. It times out if we try and simply dump data into the socketso we tried using the HTTPRange header to write data in chunks. MediaPlayerdoesn't like this and doesn't keep requesting the subsequent chunks.

我的输入数据本质上是无限长的。我告诉MediaPlayer它的数据源基本上应该是这样的"http://localhost/myfile.mp3"。我有一个简单的服务器设置,等待MediaPlayer发出此请求。然而,MediaPlayer不是很合作。首先,它创建一个HTTP GET并尝试获取整个文件。如果我们尝试简单地将数据转储到 中,它会超时,socket因此我们尝试使用HTTPRange 标头以块的形式写入数据。 MediaPlayer不喜欢这样并且不会继续请求后续块。

Has anyone had any success streaming data directly into MediaPlayer? Do I need to implement an RTSPor Shoutcastserver instead? Am I simply missing a critical HTTP header? What strategy should I use here?

有没有人成功地将数据直接导入MediaPlayer?我需要实现一个RTSPShoutcast服务器吗?我只是错过了一个关键HTTP header吗?我应该在这里使用什么策略?

回答by Robert Harvey

The HTTPServer was indeed hosted on the phone itself. It was very simple: just a threadlistening on a socket for an HTTP GETrequest. When it got the HTTPrequest, it would one a new socket, write back some HTTPheaders and start dumping the MP3audio data back to the socket. This HTTPserver didn't do anything else.

The Android Media Playerwas playing the music as I was streaming to it. The Media Playerbehaved very poorly if its playback bufferwas emptied while it was playing audio. It was very important for me to make sure my HTTPserver kept writing data into that socket. I moved bytes into the socket in small chunks (10 kB). The headers on my HTTPresponse ended up looking like this:

// Build response headers
StringBuilder sb = new StringBuilder();
sb.append( "HTTP/1.1 200 OK\r\n");
sb.append( "Content-Type: audio/mpeg\r\n");
sb.append( "Connection: close\r\n" );
sb.append( "Accept-Ranges: bytes\r\n" );
sb.append( "Content-Length: " + totalFileSize + "\r\n" );
sb.append( "Content-Disposition: inline; filename=xxxxx.mp3\r\n\r\n");

As long as I kept the pipe stoked, the Android Media Playerkept consuming it without complaint. Playing audio only required one request and response. It ended up working pretty well.

HTTP服务器确实举办了手机本身。这很简单:只是thread在套接字上侦听HTTP GET请求。当它收到HTTP请求时,它会发出一个 a new socket,写回一些HTTP标头并开始将MP3音频数据转储回socket. 该HTTP服务器没有做任何其他事情。

Android Media Player是播放音乐,因为我是流给它。该Media Player如果回放表现很差buffer它播放音频,而被掏空。确保我的HTTP服务器不断向其中写入数据对我来说非常重要socket。我将字节以小块 (10 kB) 的形式移动到套接字中。我HTTP回复的标题 最终看起来像这样:

// Build response headers
StringBuilder sb = new StringBuilder();
sb.append( "HTTP/1.1 200 OK\r\n");
sb.append( "Content-Type: audio/mpeg\r\n");
sb.append( "Connection: close\r\n" );
sb.append( "Accept-Ranges: bytes\r\n" );
sb.append( "Content-Length: " + totalFileSize + "\r\n" );
sb.append( "Content-Disposition: inline; filename=xxxxx.mp3\r\n\r\n");

只要我一直在点燃管道,Android Media Player人们就会毫无怨言地继续消费。播放音频只需要一个请求和响应。它最终工作得很好。