mirror of https://github.com/usbharu/Hideout.git
feat: 動画のアップロード
This commit is contained in:
parent
79b6e65005
commit
f206ee312d
|
@ -181,6 +181,7 @@ dependencies {
|
||||||
implementation("com.twelvemonkeys.imageio:imageio-webp:3.10.0")
|
implementation("com.twelvemonkeys.imageio:imageio-webp:3.10.0")
|
||||||
implementation("org.apache.tika:tika-core:2.9.1")
|
implementation("org.apache.tika:tika-core:2.9.1")
|
||||||
implementation("net.coobird:thumbnailator:0.4.20")
|
implementation("net.coobird:thumbnailator:0.4.20")
|
||||||
|
implementation("org.bytedeco:javacv-platform:1.5.9")
|
||||||
|
|
||||||
implementation("io.ktor:ktor-client-logging-jvm:$ktor_version")
|
implementation("io.ktor:ktor-client-logging-jvm:$ktor_version")
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class MediaProcessServiceImpl(
|
||||||
private val thumbnailGenerateService: ThumbnailGenerateService
|
private val thumbnailGenerateService: ThumbnailGenerateService
|
||||||
) : MediaProcessService {
|
) : MediaProcessService {
|
||||||
override fun isSupport(mimeType: MimeType): Boolean {
|
override fun isSupport(mimeType: MimeType): Boolean {
|
||||||
TODO("Not yet implemented")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun process(
|
override suspend fun process(
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,10 @@ spring:
|
||||||
database: hideout
|
database: hideout
|
||||||
# username: hideoutuser
|
# username: hideoutuser
|
||||||
# password: hideoutpass
|
# password: hideoutpass
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 40MB
|
||||||
|
max-request-size: 40MB
|
||||||
h2:
|
h2:
|
||||||
console:
|
console:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -42,5 +45,6 @@ server:
|
||||||
basedir: tomcat
|
basedir: tomcat
|
||||||
accesslog:
|
accesslog:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
max-http-form-post-size: 40MB
|
||||||
|
max-swallow-size: 40MB
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
Loading…
Reference in New Issue