Java Play Framework 2.3.x ByteChunks MP3流媒体没有播放功能,不是';可滚动';在浏览器中
使用Play Framework(版本Java Play Framework 2.3.x ByteChunks MP3流媒体没有播放功能,不是';可滚动';在浏览器中,java,audio,playframework,http-headers,streaming,Java,Audio,Playframework,Http Headers,Streaming,使用Play Framework(版本2.3.x)(Java风格),我试图向浏览器提供.mp3文件。由于它是一个“大”文件,我决定使用Play的ByteChunks对象,如下所示 @With(MP3Headers.class) public static Result test() { Chunks<byte[]> chunks = new ByteChunks() { public void onReady(Chunks.Out<byte[]>
2.3.x
)(Java风格),我试图向浏览器提供.mp3
文件。由于它是一个“大”文件,我决定使用Play的ByteChunks
对象,如下所示
@With(MP3Headers.class)
public static Result test() {
Chunks<byte[]> chunks = new ByteChunks() {
public void onReady(Chunks.Out<byte[]> out) {
try {
byte[] song = Files.readAllBytes(Paths.get("public/mp3/song.mp3"));
out.write(song);
} catch(Exception e) {
e.printStackTrace();
} finally {
out.close();
}
}
};
return ok(chunks);
}
为了完成,我的路由文件:
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# Home page
GET / controllers.Application.index()
GET /test controllers.Application.test()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
正如预期的那样,导航到localhost:9000/test
将呈现一个漂亮的HTML5
音频播放器(见图)
我的问题是音频播放器中的“滚动”不起作用。如果我滚动,音乐会暂停,当我放开时(当我在时间上“选择”一个位置时),音乐会在第一次暂停的地方继续
我希望我说的有道理,我希望你们对这件事了解得更多。提前感谢。您需要告诉您的浏览器您的服务器支持范围请求并实现范围响应(即仅提供浏览器需要的音乐部分)。您可以在中获得请求/响应周期的概述
@With(MP3Headers.class)
公共静态结果测试(){
最终整数开始,结束;
最终布尔值isRangeReq;
response().setHeader(“接受范围”、“字节”);
if(request().hashreader(“RANGE”)){
isRangeReq=true;
字符串[]range=request().getHeader(“range”).split(“=”[1]。split(“-”);
begin=Integer.parseInt(范围[0]);
如果(range.length>1){
end=Integer.parseInt(范围[1]);
}否则{
end=song.length-1;
}
response().setHeader(“内容范围”,String.format(“字节%d-%d/%d”,开始,结束,歌曲.length”);
}否则{
isRangeReq=false;
开始=0;
结束=宋体长度-1;
}
Chunks Chunks=new ByteChunks(){
public void onReady(Chunks.Out){
如果(isRangeReq){
out.write(Arrays.copyOfRange(歌曲、开始、结束));
}否则{
写出(歌曲);
}
out.close();
}
};
response().setHeader(“内容长度”(end-begin+1)+”);
如果(isRangeReq){
返回状态(206,块);
}否则{
返回状态(200,块);
}
}
请注意,在此代码中,歌曲已加载到song
。另外,范围
头的解析非常脏(你可以得到像范围:
这样的值)我发现这段代码很容易实现。
将以下操作及其私有助手方法放入控制器中
控制器动作
流辅助方法
此处有完整的示例链接谢谢!这很有帮助!好吧,我们最好通过解析范围
标题的变通方法来改进代码。这个答案很有帮助,谢谢。现在的问题是,流在整个音频中都有光点和缺陷。你有没有想过是什么原因造成的,或者如何修复?
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# Home page
GET / controllers.Application.index()
GET /test controllers.Application.test()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
@With(MP3Headers.class)
public static Result test() {
final int begin, end;
final boolean isRangeReq;
response().setHeader("Accept-Ranges", "bytes");
if (request().hasHeader("RANGE")) {
isRangeReq = true;
String[] range = request().getHeader("RANGE").split("=")[1].split("-");
begin = Integer.parseInt(range[0]);
if (range.length > 1) {
end = Integer.parseInt(range[1]);
} else {
end = song.length-1;
}
response().setHeader("Content-Range", String.format("bytes %d-%d/%d", begin, end, song.length));
} else {
isRangeReq = false;
begin = 0;
end = song.length - 1;
}
Chunks<byte[]> chunks = new ByteChunks() {
public void onReady(Chunks.Out<byte[]> out) {
if(isRangeReq) {
out.write(Arrays.copyOfRange(song, begin, end));
} else {
out.write(song);
}
out.close();
}
};
response().setHeader("Content-Length", (end - begin + 1) + "");
if (isRangeReq) {
return status(206, chunks);
} else {
return status(200, chunks);
}
}
public static Result file(Long id, String filename) throws IOException {
Item item = Item.fetch(id);
File file = item.getFile();
if(file== null || !file.exists()) {
Logger.error("File no longer exist item"+id+" filename:"+filename);
return notFound();
}
String rangeheader = request().getHeader(RANGE);
if(rangeheader != null) {
String[] split = rangeheader.substring("bytes=".length()).split("-");
if(Logger.isDebugEnabled()) { Logger.debug("Range header is:"+rangeheader); }
if(split.length == 1) {
long start = Long.parseLong(split[0]);
long length = file.length()-1l;
return stream(start, length, file);
} else {
long start = Long.parseLong(split[0]);
long length = Long.parseLong(split[1]);
return stream(start, length, file);
}
}
// if no streaming is required we simply return the file as a 200 OK
if(Play.isProd()) {
response().setHeader("Cache-Control", "max-age=3600, must-revalidate");
}
return ok(file);
}
private static Result stream(long start, long length, File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
fis.skip(start);
response().setContentType(MimeTypes.forExtension("mp4").get());
response().setHeader(CONTENT_LENGTH, ((length - start) +1l)+"");
response().setHeader(CONTENT_RANGE, String.format("bytes %d-%d/%d", start, length,file.length()));
response().setHeader(ACCEPT_RANGES, "bytes");
response().setHeader(CONNECTION, "keep-alive");
return status(PARTIAL_CONTENT, fis);
}