feat: メディアの変換処理を実装

This commit is contained in:
usbharu 2023-10-04 23:07:55 +09:00
parent bbf3249c45
commit 0fd620d16e
10 changed files with 83 additions and 11 deletions

View File

@ -118,6 +118,7 @@ dependencies {
implementation("org.springframework.security:spring-security-oauth2-jose") implementation("org.springframework.security:spring-security-oauth2-jose")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb") implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.jetbrains.exposed:exposed-spring-boot-starter:0.44.0") implementation("org.jetbrains.exposed:exposed-spring-boot-starter:0.44.0")
implementation("io.trbl:blurhash:1.0.0")
implementation("io.ktor:ktor-client-logging-jvm:$ktor_version") implementation("io.ktor:ktor-client-logging-jvm:$ktor_version")

View File

@ -1,10 +1,10 @@
package dev.usbharu.hideout.domain.model package dev.usbharu.hideout.domain.model
import java.io.InputStream import java.io.OutputStream
data class MediaSave( data class MediaSave(
val name: String, val name: String,
val prefix: String, val prefix: String,
val fileInputStream: InputStream, val fileInputStream: OutputStream,
val thumbnailInputStream: InputStream? val thumbnailInputStream: OutputStream?
) )

View File

@ -0,0 +1,10 @@
package dev.usbharu.hideout.service.media
import io.trbl.blurhash.BlurHash
import org.springframework.stereotype.Service
import java.awt.image.BufferedImage
@Service
class MediaBlurhashServiceImpl : MediaBlurhashService {
override fun generateBlurhash(bufferedImage: BufferedImage): String = BlurHash.encode(bufferedImage)
}

View File

@ -1,7 +1,10 @@
package dev.usbharu.hideout.service.media package dev.usbharu.hideout.service.media
import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream
interface ThumbnailGenerateService { interface ThumbnailGenerateService {
fun generate(bufferedImage: InputStream, width: Int, height: Int): InputStream fun generate(bufferedImage: InputStream, width: Int, height: Int): ByteArrayOutputStream
fun generate(outputStream: OutputStream, width: Int, height: Int): ByteArrayOutputStream
} }

View File

@ -0,0 +1,28 @@
package dev.usbharu.hideout.service.media
import org.springframework.stereotype.Service
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream
import javax.imageio.ImageIO
import javax.imageio.stream.MemoryCacheImageOutputStream
@Service
class ThumbnailGenerateServiceImpl : ThumbnailGenerateService {
override fun generate(bufferedImage: InputStream, width: Int, height: Int): ByteArrayOutputStream {
val image = ImageIO.read(bufferedImage)
return internalGenerate(image)
}
override fun generate(outputStream: OutputStream, width: Int, height: Int): ByteArrayOutputStream {
val image = ImageIO.read(MemoryCacheImageOutputStream(outputStream))
return internalGenerate(image)
}
private fun internalGenerate(image: BufferedImage): ByteArrayOutputStream {
val byteArrayOutputStream = ByteArrayOutputStream()
ImageIO.write(image, "webp", byteArrayOutputStream)
return byteArrayOutputStream
}
}

View File

@ -2,8 +2,9 @@ package dev.usbharu.hideout.service.media.converter
import dev.usbharu.hideout.domain.model.hideout.dto.FileType import dev.usbharu.hideout.domain.model.hideout.dto.FileType
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream
interface MediaConverter { interface MediaConverter {
fun isSupport(fileType: FileType): Boolean fun isSupport(fileType: FileType): Boolean
fun convert(inputStream: InputStream): InputStream fun convert(inputStream: InputStream): OutputStream
} }

View File

@ -2,7 +2,8 @@ package dev.usbharu.hideout.service.media.converter
import dev.usbharu.hideout.domain.model.hideout.dto.FileType import dev.usbharu.hideout.domain.model.hideout.dto.FileType
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream
interface MediaConverterRoot { interface MediaConverterRoot {
suspend fun convert(fileType: FileType, inputStream: InputStream): InputStream suspend fun convert(fileType: FileType, inputStream: InputStream): OutputStream
} }

View File

@ -0,0 +1,20 @@
package dev.usbharu.hideout.service.media.converter
import dev.usbharu.hideout.domain.model.hideout.dto.FileType
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream
@Service
class MediaConverterRootImpl(private val converters: List<MediaConverter>) : MediaConverterRoot {
override suspend fun convert(fileType: FileType, inputStream: InputStream): OutputStream {
return converters.find {
it.isSupport(fileType)
}?.convert(inputStream) ?: inputStream.let {
val byteArrayOutputStream = ByteArrayOutputStream()
it.transferTo(byteArrayOutputStream)
byteArrayOutputStream
}
}
}

View File

@ -2,7 +2,12 @@ package dev.usbharu.hideout.service.media.converter
import dev.usbharu.hideout.domain.model.hideout.dto.FileType import dev.usbharu.hideout.domain.model.hideout.dto.FileType
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream
interface MediaProcessService { interface MediaProcessService {
suspend fun process(fileType: FileType, file: InputStream, thumbnail: InputStream?): Pair<InputStream, InputStream> suspend fun process(
fileType: FileType,
file: InputStream,
thumbnail: InputStream?
): Pair<OutputStream, OutputStream>
} }

View File

@ -4,8 +4,11 @@ import dev.usbharu.hideout.domain.model.hideout.dto.FileType
import dev.usbharu.hideout.exception.media.MediaConvertException import dev.usbharu.hideout.exception.media.MediaConvertException
import dev.usbharu.hideout.service.media.ThumbnailGenerateService import dev.usbharu.hideout.service.media.ThumbnailGenerateService
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream
@Service
class MediaProcessServiceImpl( class MediaProcessServiceImpl(
private val mediaConverterRoot: MediaConverterRoot, private val mediaConverterRoot: MediaConverterRoot,
private val thumbnailGenerateService: ThumbnailGenerateService private val thumbnailGenerateService: ThumbnailGenerateService
@ -14,7 +17,7 @@ class MediaProcessServiceImpl(
fileType: FileType, fileType: FileType,
file: InputStream, file: InputStream,
thumbnail: InputStream? thumbnail: InputStream?
): Pair<InputStream, InputStream> { ): Pair<OutputStream, OutputStream> {
val fileInputStream = try { val fileInputStream = try {
mediaConverterRoot.convert(fileType, file) mediaConverterRoot.convert(fileType, file)
@ -28,11 +31,11 @@ class MediaProcessServiceImpl(
logger.warn("Failed convert thumbnail media.", e) logger.warn("Failed convert thumbnail media.", e)
null null
} }
return fileInputStream to (thumbnailInputStream ?: thumbnailGenerateService.generate( return fileInputStream to thumbnailGenerateService.generate(
fileInputStream, thumbnailInputStream ?: fileInputStream,
2048, 2048,
2048 2048
)) )
} }
companion object { companion object {