Cтриминг видео на Kotlin
Пишу бэкенд приложение на Kotlin+Ktor. Задача состоит в том что с html формы пользователь отправляет видео, которое необходимо сохранить в MinIO. Затем по запросу от пользователя необходимо достать это видео из хранилище и запустить его стрим на хтмл страничке. Но столкнулся с проблемой при получении видео из хранилища (видео беру чанками). Вылетает следующая ошибка:
DEBUG Application - 206 Partial Content: GET - /video/21e57ab6-3275-47e0-9e27-8b522d7f21a9. Exception class io.ktor.util.cio.ChannelWriteException: Cannot write to a channel
Caused by: [CIRCULAR REFERENCE: io.ktor.util.cio.ChannelWriteException: Cannot write to a channel]Caused by: java.io.IOException: Broken pipe
Код контроллера
get("/{uuid}") {
val uuid = UUID.fromString(call.parameters["uuid"])
val range = call.request.headers["Range"]
val parsedRange = Range.parseHttpRangeString(range, defaultChunkSize)
val chunkWithMetadata = videoService.fetchChunk(uuid, parsedRange)
call.response.header("Content-Type", chunkWithMetadata.metadata.`httpContentType`)
call.response.header("Accept-Ranges", "bytes")
call.response.header(
"Content-Length",
calculateContentLengthHeader(parsedRange, chunkWithMetadata.metadata.size)
)
call.response.header(
"Content-Range",
constructContentRangeHeader(parsedRange, chunkWithMetadata.metadata.size)
)
call.respondOutputStream(
status = HttpStatusCode.PartialContent,
contentType = ContentType(
contentType = chunkWithMetadata.metadata.httpContentType,
contentSubtype = chunkWithMetadata.metadata.httpContentType
),
введите сюда кодcontentLength = calculateContentLengthHeader(parsedRange, chunkWithMetadata.metadata.size).toLong(),
) {
val output = this
output.write(chunkWithMetadata.chunk)
}
}
Код сервиса:
override suspend fun fetchChunk(uuid: UUID, range: Range): ChunkWithMetadata {
val fileMetadata = fileMetadataDAOFacade.findById(uuid)
return ChunkWithMetadata(fileMetadata!!, readChunk(uuid, range, fileMetadata.size))
}
private fun readChunk(uuid: UUID, range: Range, fileSize: Long): ByteArray {
val startPosition = range.getRangeStart()
val endPosition = range.getRangeEnd(fileSize)
val chunkSize = (endPosition - startPosition + 1)
try {
storageService.getInputStream(uuid, startPosition, chunkSize).use { inputStream ->
return inputStream.readAllBytes()
}
} catch (exception: Exception) {
throw StorageException(exception)
}
}
data class ChunkWithMetadata(
val metadata: FileMetadataEntity,
val chunk: ByteArray
)
Подскажите, пожалуйста, с чем может быть проблема