More correctly handle stream ranges

When transcoding, always use chunked transfers and report that ranges
are not supported. When not transcoding, support returning ranges but
only if requested.
master
Peter Marheine 5 years ago
parent 3e97186043
commit 9be2a8892f
  1. 47
      airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java

@ -153,28 +153,45 @@ public class StreamController {
playQueue.addFiles(true, file); playQueue.addFiles(true, file);
player.setPlayQueue(playQueue); player.setPlayQueue(playQueue);
if (settingsService.isEnableSeek() && !file.isVideo()) {
response.setIntHeader("ETag", file.getId());
response.setHeader("Accept-Ranges", "bytes");
}
TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate, TranscodingService.Parameters parameters = transcodingService.getParameters(file, player, maxBitRate,
preferredTargetFormat, null); preferredTargetFormat, null);
long fileLength = getFileLength(parameters);
boolean isConversion = parameters.isDownsample() || parameters.isTranscode(); boolean isConversion = parameters.isDownsample() || parameters.isTranscode();
boolean estimateContentLength = ServletRequestUtils.getBooleanParameter(request, boolean estimateContentLength = ServletRequestUtils.getBooleanParameter(request,
"estimateContentLength", false); "estimateContentLength", false);
boolean isHls = ServletRequestUtils.getBooleanParameter(request, "hls", false); boolean isHls = ServletRequestUtils.getBooleanParameter(request, "hls", false);
range = getRange(request, file); // Wrangle response length and ranges.
if (settingsService.isEnableSeek() && range != null && !file.isVideo()) { //
LOG.info("{}: Got HTTP range: {}", request.getRemoteAddr(), range); // Support ranges as long as we're not transcoding; video is always assumed to transcode
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); if (isConversion || file.isVideo()) {
Util.setContentLength(response, range.isClosed() ? range.size() : fileLength - range.getFirstBytePos()); // Use chunked transfer; do not accept range requests
long lastBytePos = range.getLastBytePos() != null ? range.getLastBytePos() : fileLength - 1; response.setStatus(HttpServletResponse.SC_OK);
response.setHeader("Content-Range", "bytes " + range.getFirstBytePos() + "-" + lastBytePos + "/" + fileLength); response.setHeader("Accept-Ranges", "none");
} else if (!isHls && (!isConversion || estimateContentLength)) { } else {
Util.setContentLength(response, fileLength); // Not transcoding, partial content permitted because we know the final size
long contentLength;
// If range was requested, respond in kind
range = getRange(request, file);
if (range != null) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setHeader("Accept-Ranges", "bytes");
// Both ends are inclusive
long startByte = range.getFirstBytePos();
long endByte = range.isClosed() ? range.getLastBytePos() : file.getFileSize() - 1;
response.setHeader("Content-Range",
String.format("bytes %d-%d/%d", startByte, endByte, file.getFileSize()));
contentLength = endByte + 1 - startByte;
} else {
// No range was requested, give back the whole file
response.setStatus(HttpServletResponse.SC_OK);
contentLength = file.getFileSize();
}
response.setIntHeader("ETag", file.getId());
Util.setContentLength(response, contentLength);
} }
// Set content type of response // Set content type of response

Loading…
Cancel
Save