Как стримить видео, на основе inputStream
У меня есть InputStream, в котором я получаю видео ролик, источник этого InputStream физически на другом сервере(на CMS). Мой сервис проксирует этот поток, и передает на фронт. Хотелось сделать управлением ползунком в плеере, чтобы если передвигаешь ползунок, видео начиналось грузиться с того места, куда выставлен ползунок.
Самое лучшее, что у меня вышло из всех моих попыток, это:
@GetMapping(value = "/{videoId}", produces = "video/mp4")
public ResponseEntity<InputStreamResource> getSome(@PathVariable String videoId) {
final InputStream videoStream = cmsClient.getVideoStream(videoId);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("video/mp4"))
.body(new InputStreamResource(videoStream));
}
Однако отсутствует возможность как-то управлять ползунком в видео плеере, его не передвинуть, он движется сам по себе, и его можно только сбросить на начало. Как я понимаю, получилось что-то типо потокового стрима.
Чтобы грузить видео частями, с возможностью передвигать ползунок, пользуются хедером "Range". Вот я хотел написать, что-то подобное:
@GetMapping(value = "/{videoId}", produces = "video/mp4")
public ResponseEntity<ResourceRegion> getSome(@PathVariable String videoId, @RequestHeader HttpHeaders headers) throws IOException {
final ResourceRegion video = getVideo(videoId, headers);
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
.contentType(MediaTypeFactory
.getMediaType("video/mp4")
.orElse(MediaType.APPLICATION_OCTET_STREAM))
.body(video);
}
private ResourceRegion getVideo(String videoId, HttpHeaders headers) throws IOException {
final InputStream stream = cmsClient.getStream(videoId);
InputStreamResource inputStreamResource = new InputStreamResource(stream);
final long contentLength = inputStreamResource.contentLength();
final HttpRange httpRange = headers.getRange().get(0);
if (httpRange != null) {
long start = httpRange.getRangeStart(contentLength);
long end = httpRange.getRangeEnd(contentLength);
long rangeLength = Math.min(1 * 1024 * 1024, end - start + 1);
return new ResourceRegion(inputStreamResource, start, rangeLength);
} else {
long rangeLength = Math.min(1 * 1024 * 1024, contentLength);
return new ResourceRegion(inputStreamResource, 0, rangeLength);
}
}
И тут я уже получаю ошибку:
java.lang.IllegalStateException: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times
at org.springframework.core.io.InputStreamResource.getInputStream(InputStreamResource.java:97) ~[spring-core-5.3.12.jar:5.3.12]
at org.springframework.core.io.AbstractResource.contentLength(AbstractResource.java:162) ~[spring-core-5.3.12.jar:5.3.12]
at org.springframework.http.converter.ResourceRegionHttpMessageConverter.writeResourceRegion(ResourceRegionHttpMessageConverter.java:151) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.http.converter.ResourceRegionHttpMessageConverter.writeInternal(ResourceRegionHttpMessageConverter.java:131) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104) ~[spring-web-5.3.12.jar:5.3.12]
Подскажите, есть ли у вас решения, как транслировать видео на основе InputStream, с возможностью переставлять ползунок в плеере, чтобы видео грузилось с того места, куда был поставлен ползунок. Если бы я имел видео файл физически на диске рядом со своим сервисом, то проблем бы не было. Проблема в том, что видео файл скачивать не хочется, хочется просто проксировать inputStream на фронт.
