Как стримить видео, на основе 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 на фронт.


Ответы (0 шт):