feat: 動画のアップロード

This commit is contained in:
usbharu 2023-11-16 15:36:45 +09:00
parent 477d12fa61
commit f0a84e7fa1
4 changed files with 140 additions and 3 deletions

View File

@ -181,6 +181,7 @@ dependencies {
implementation("com.twelvemonkeys.imageio:imageio-webp:3.10.0")
implementation("org.apache.tika:tika-core:2.9.1")
implementation("net.coobird:thumbnailator:0.4.20")
implementation("org.bytedeco:javacv-platform:1.5.9")
implementation("io.ktor:ktor-client-logging-jvm:$ktor_version")

View File

@ -13,7 +13,7 @@ class MediaProcessServiceImpl(
private val thumbnailGenerateService: ThumbnailGenerateService
) : MediaProcessService {
override fun isSupport(mimeType: MimeType): Boolean {
TODO("Not yet implemented")
return false
}
override suspend fun process(

View File

@ -0,0 +1,132 @@
package dev.usbharu.hideout.core.service.media.converter.movie
import dev.usbharu.hideout.core.service.media.FileType
import dev.usbharu.hideout.core.service.media.MimeType
import dev.usbharu.hideout.core.service.media.ProcessedMedia
import dev.usbharu.hideout.core.service.media.ProcessedMediaPath
import dev.usbharu.hideout.core.service.media.converter.MediaProcessService
import org.bytedeco.ffmpeg.global.avcodec
import org.bytedeco.javacv.FFmpegFrameFilter
import org.bytedeco.javacv.FFmpegFrameGrabber
import org.bytedeco.javacv.FFmpegFrameRecorder
import org.bytedeco.javacv.Java2DFrameConverter
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import java.awt.image.BufferedImage
import java.nio.file.Files
import java.nio.file.Path
import javax.imageio.ImageIO
import kotlin.math.min
@Service
@Qualifier("video")
class MovieMediaProcessService : MediaProcessService {
override fun isSupport(mimeType: MimeType): Boolean {
return mimeType.type == "video"
}
override suspend fun process(
fileType: FileType,
contentType: String,
fileName: String,
file: ByteArray,
thumbnail: ByteArray?
): ProcessedMedia {
TODO("Not yet implemented")
}
override suspend fun process(
mimeType: MimeType,
fileName: String,
filePath: Path,
thumbnails: Path?
): ProcessedMediaPath {
val tempFile = Files.createTempFile("hideout-movie-processor-", ".tmp")
val thumbnailFile = Files.createTempFile("hideout-movie-thumbnail-generate-", ".tmp")
logger.info("START Convert Movie Media {}", fileName)
FFmpegFrameGrabber(filePath.toFile()).use { grabber ->
grabber.start()
val width = grabber.imageWidth
val height = grabber.imageHeight
val frameRate = 60.0
logger.debug("Movie Media Width {}, Height {}", width, height)
FFmpegFrameFilter(
"fps=fps=${frameRate.toInt()}",
"anull",
width,
height,
grabber.audioChannels
).use { filter ->
filter.sampleFormat = grabber.sampleFormat
filter.sampleRate = grabber.sampleRate
filter.pixelFormat = grabber.pixelFormat
filter.frameRate = grabber.frameRate
filter.start()
val videoBitRate = min(1300000, (width * height * frameRate * 1 * 0.07).toInt())
logger.debug("Movie Media BitRate {}", videoBitRate)
FFmpegFrameRecorder(tempFile.toFile(), width, height, grabber.audioChannels).use {
it.sampleRate = grabber.sampleRate
it.format = "mp4"
it.videoCodec = avcodec.AV_CODEC_ID_H264
it.audioCodec = avcodec.AV_CODEC_ID_AAC
it.audioChannels = grabber.audioChannels
it.videoQuality = 1.0
it.frameRate = frameRate
it.setVideoOption("preset", "ultrafast")
it.timestamp = 0
it.gopSize = frameRate.toInt()
it.videoBitrate = videoBitRate
it.start()
var bufferedImage: BufferedImage? = null
val frameConverter = Java2DFrameConverter()
while (true) {
val grab = grabber.grab() ?: break
if (bufferedImage == null) {
bufferedImage = frameConverter.convert(grab)
}
if (grab.image != null || grab.samples != null) {
filter.push(grab)
}
while (true) {
val frame = filter.pull() ?: break
it.record(frame)
}
}
if (bufferedImage != null) {
ImageIO.write(bufferedImage, "jpeg", thumbnailFile.toFile())
}
}
}
}
logger.info("SUCCESS Convert Movie Media {}", fileName)
return ProcessedMediaPath(
tempFile,
thumbnailFile,
MimeType("video", "mp4", FileType.Video),
MimeType("image", "jpeg", FileType.Image)
)
}
companion object {
private val logger = LoggerFactory.getLogger(MovieMediaProcessService::class.java)
}
}

View File

@ -30,7 +30,10 @@ spring:
database: hideout
# username: hideoutuser
# password: hideoutpass
servlet:
multipart:
max-file-size: 40MB
max-request-size: 40MB
h2:
console:
enabled: true
@ -42,5 +45,6 @@ server:
basedir: tomcat
accesslog:
enabled: true
max-http-form-post-size: 40MB
max-swallow-size: 40MB
port: 8081