java - Android mediaPlayer 渐进式下载“通过 Peer 重置连接”
问题描述
我在使用 android MediaPlayer 时遇到问题,我首先在播放之前将整首歌曲缓存到内存中,然后我决定从我用 SparkJava 编写的 api 流式传输歌曲。所以现在它工作正常如果我试图寻找一个加载点,否则它就会停止。并在 API 服务器中生成:
org.eclipse.jetty.io.EofException
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:286)
at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:393)
at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:349)
at org.eclipse.jetty.io.ChannelEndPoint$3.run(ChannelEndPoint.java:133)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:295)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.io.IOException: Connection reset by peer
at java.base/sun.nio.ch.SocketDispatcher.write0(Native Method)
at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:54)
at java.base/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:113)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:79)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:50)
at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:484)
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:264)
这是 API 部分使用的代码:
public static Object postAudioResponse(Request request, Response response) {
try ( OutputStream os = response.raw().getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os))
{
File mp3 = new File("C:\\FTPServer\\" + request.queryParams("dir"));
String range = request.headers("Range");
if (range == null) {
response.status(200);
byte[] bytes = Files.readAllBytes(java.nio.file.Paths.get("C:\\FTPServer\\" + request.queryParams("dir")));
response.header("Content-Type", "audio/mpeg");
response.header("Content-Length", String.valueOf(bytes.length));
System.out.println(response.raw().toString());
HttpServletResponse raw = response.raw();
raw.getOutputStream().write(bytes);
raw.getOutputStream().flush();
raw.getOutputStream().close();
return raw;
}
int[] fromTo = fromTo(mp3, range);
int length = fromTo[1] - fromTo[0] + 1;
response.status(206);
response.raw().setContentType("audio/mpeg");
response.header("Accept-Ranges", "bytes");
response.header("Content-Range", contentRangeByteString(fromTo));
response.header("Content-Length", String.valueOf(length));
final RandomAccessFile raf = new RandomAccessFile(mp3, "r");
raf.seek(fromTo[0]);
writeAudioToOS(length, raf, bos);
raf.close();
bos.flush();
bos.close();
return response.raw();
} catch (IOException e) {
e.printStackTrace();
response.header("Content-Type", "application/json");
return gson.toJson(new StandardResponse(StatusResponse.ERROR, e.toString()));
}
}
这是我的 API HTTP 响应(字符串格式)
HTTP/1.1 206
Date: Wed, 04 Mar 2020 19:39:45 GMT
Content-Type: audio/mpeg
Accept-Ranges: bytes
Content-Range: bytes 4767443-4775635/8897707
Content-Length: 8193
我尝试了多种方法,更改标头,多次验证标头,尝试了 ExoPlayer,我什至检查了 HTTP 部分的 android 源代码,它似乎是正确的。
安卓代码:
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(Api.getSongSource(songName));
mediaPlayer.prepareAsync();
注意:异常发生在我发送具有特定范围内内容的新 HTTP 响应之前。谢谢。
* 更新 *
我在第一个答案中解决了这个问题。
解决方案
我通过执行以下操作修复了上述错误
*客户端我没有在android原生SDK中使用mediaPlayer,而是使用了ExoMedia(这是ExoPlayer的一个接口,但与mediaPlayer具有相同的功能)
*服务器端
使用 ExoMedia 后,我开始注意到一些事情,当我寻找一个尚未加载的点时,它从该部分播放了一小部分时间,可能是 50 毫秒,所以我开始四处挖掘并发现了以下内容。
当服务器接收到带有Range的请求时,服务器会查找 from,然后发送带有数据[From, From + Chunk]的响应。
我的 Chunk 等于 8192,在增加chunk 部分后,我可以注意到歌曲播放的时间更长。所以不要发送[From, From + Chunk]并等待ExoMedia请求下一部分。
我发送了整个 [From, End of song]。这解决了我的错误。.
推荐阅读
- office365 - Microsoft Graph 安全 API 提供 206,空“值”
- java - 如何等到进程完成 Java AWS Lambda
- c# - XAMARIN:如何刷新 WebView OnTabReselected?
- javascript - 如何在排序时设置反应表标题的样式
- r - 如何找到正确的坐标以将标签与条形图条对齐?
- regex - bash 中 --- (三连字符)的正则表达式
- python - 删除评论标签,但不包含 BeautifulSoup 的内容
- swift - UIScrollView 项目没有从后台移动
- javascript - ng-class 根据 ng-repeat 中的条件选择按钮
- android - 强制相机横向android