'AWS로 구현하는 MAS와 컨테이너 오캐스트레이션' 강의를
블로그를 통해 구매하시는 분들에게만 10%할인 중입니다.
이미지를 클릭하면 강의로 이동할 수 있습니다.
아래 쿠폰번호를 입력해 주세요!
16861-259843d6c2d7
영상 인코딩
영상 데이터를 압축하고 표준화된 형식으로 변환하는 과정
인코딩을 할땐 코덱이 사용되며, 원본 영상 데이터의 크기를 줄이고 호환성을 높이는 역할을 한다.
이로 인해 네트워크 전송 시 빠르게 전송되고 저장곤간을 절약할 수 있다.
코덱
코덱은 영상 데이터를 압축하고 해석하는데 사용되는 소프트웨어이다.
압축률, 품질, 호환성 등 다양한 측면에서 차이가 있으며 H.264, H.265, VP8, VP9 등이 대표적인 예이다.
컨테이너
컨테이너는 영상, 오디오, 메타데이터 등 다양한 데이터를 하나의 파일로 묶어 호환성과 재생을 보장하는 역할
MP4, AVI, MKV, MOV 등의 포멧이 있다.
영상 인코딩 및 최적화를 하는 이유
- 품질 유지 - 원본 영상의 품질을 최대한 보존하면서 효율적인 포맥으로 변환이 가능하여 사용자들의 사용에 편의성을 줄 수 있다.
- 전송 속도 - 영상 파일 크기를 줄여, 데이터 전송 속도가 향상된다.
- 저장 공간 절약 - 영상 파일의 크기를 최소화하여 저장 공간을 절약하여 서버 운영 비용을 줄일 수 있다.
- 호환성 향상 - 영상을 다양한 기기 및 브라우저에서 재생 가능하도록 코덱과 컨테이너 포멧을 통해 인코딩할 수 있다.
FFmpeg
오픈소스 프로젝트로 다양한 기능을 제공하는 미디어 처리 라이브러리이다.
주로 비디오, 오디오, 스트림 데이터를 처리하는데 사용되며, 다양한 포맷간의 변환, 인코딩, 디코딩, 필터링, 스트리밍 등 여러 작업을 지원한다.
크로스 플랫폼을 지원하여 대부분의 운영체제에서 사용가능하다.
FFmpeg 주요 구성요소
- libavcode - 다양한 코덱을 제공하여 비디오 및 오디오 데이터의 인코딩과 디코딩을 처리한다. (H.264, H.265, VP8, VP9, AAC, MP3)
- libavformat - 다양한 미디어 컨테이너 포맷을 지원하며, 비디오와 오디오 데이터를 저장하고 전송할 때 사용되는 파일 포맷을 처리한다. (MP4, AVI, MKV, MOV, FLV)
- libavfilter - 비디오 및 오디오 데이터에 다양한 필터링 기능을 적용할 수 있게 해준다. 예를 들어 영상의 크기를 변경, 회전, 자르기, 노이즈 제거, 오디오 볼륨조절 등
- libavutil - FFmpeg 프로젝트에서 공통으로 사용되는 기능을 제공. 예를 들어 수학 계산, 메모리 관리, 데이터 구조 등
- libswscale - 비디오 데이터의 크기를 변경하거나 색상 형식을 변환하는 작업을 처리
- ffmpeg - 위의 요소들을 이용하여 다양한 미디어 처리작업을 수행하는 CLI 도구. 사용자는 이 도구를 통해 영상 인코딩, 변환, 필터링 등의 작업을 실행할 수 있다.
Spring boot에서 FFmpeg를 사용해 영상 인코딩 작업 하는 방법
1. FFmpeg 설치 (Ubuntu)
sudo apt-get update
sudo apt-get install ffmpeg
먼저 FFmpeg가 설치되어있어야 하므로 명령어를 통해 설치
2. FFmpeg 래퍼 라이브러리 종속성 추가
implementation("ws.schild:jave-core:3.3.1")
FFmpeg를 사용하기위해 java용 FFmpeg 래퍼 라이브러리 종속성을 추가
* 최신버전 확인
https://mvnrepository.com/artifact/ws.schild/jave-core
3. 영상 인코딩 로직 구현
@RestController
@RequestMapping("/api/video")
class VideoTestController {
// 로컬에 ffmpeg 경로 지정, which ffmpeg 명령어를 통해 경로를 찾을 수 있다.
private val ffmpegExecutablePath = "/usr/local/bin/ffmpeg"
@PostMapping("/upload")
fun uploadVideo(@RequestParam("file") file: MultipartFile): ResponseEntity<String?>? {
return try {
// multipart file 로 입력받은 파일을 임시파일로 로컬에 저장
val inputFile = File.createTempFile("input", file.originalFilename)
file.transferTo(inputFile)
// 출력 받을 파일 객체 생성
val outputFile = File.createTempFile("output", ".mp4")
// 영상 파일 인코딩
encodeVideo(inputFile, outputFile)
// 인코딩 된 파일 경로 반환
ResponseEntity.ok(outputFile.absolutePath)
} catch (e: Exception) {
e.printStackTrace()
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to process video");
}
}
fun encodeVideo(input: File, output: File) {
// FFmpeg 실행 파일의 경로를 지정하고, 라이브러리가 FFmpeg을 찾을 수 있게 해줌
val locator = FFMPEGLocatorCustom(ffmpegExecutablePath)
// 비디오 파일의 메타데이터와 인코딩 작업을 수행하는 데 필요한 정보를 제공
val multimediaObject = MultimediaObject(input, locator)
val audio = AudioAttributes()
audio.setCodec("aac") // 오디오 코덱 설정
audio.setBitRate(128000) // 비트레이트 설정
audio.setChannels(2) // 채널 수
audio.setSamplingRate(44100) // 샘플링 레이트
// 비디오의 사이즈를 가져와 1000픽셀로 이하로 비율을 조절
val videoInfo = multimediaObject.info.video
val originalWidth = videoInfo.size.width ?: 0
val originalHeight = videoInfo.size.height ?: 0
val scaleFactor = 1000.0 / max(originalWidth, originalHeight)
// 조절된 width, height 값
val newWidth = (originalWidth * scaleFactor).toInt()
val newHeight = (originalHeight * scaleFactor).toInt()
val video = VideoAttributes()
video.setCodec("libx264") // 비디오 코덱 설정
video.setBitRate(320000) // 비트레이트 설정
video.setFrameRate(30) // 프레임 레이트 설정
video.setSize(VideoSize(newWidth, newHeight)) // 비디오 크기 설정
val attrs = EncodingAttributes()
attrs.setOutputFormat("mp4") // 출력 형식
attrs.setAudioAttributes(audio) // 오디오 속성 설정
attrs.setVideoAttributes(video) // 비디오 속성 설정
// 인코딩 작업을 수행 및 예외 처리
val encoder = Encoder(locator)
try {
encoder.encode(multimediaObject, output, attrs)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: EncoderException) {
e.printStackTrace()
}
}
}
class FFMPEGLocatorCustom(private val ffmpegExecutablePath: String) : DefaultFFMPEGLocator() {
override fun getExecutablePath(): String {
return ffmpegExecutablePath
}
override fun createExecutor(): ProcessWrapper {
return FFMPEGProcess(executablePath)
}
}
Spring boot에서 FFmpeg를 사용해 영상 인코딩 결과
인코딩을 수행할 영상 파일 정보
재생시간이 43초밖에 되지 않지만 용량이 391MB 로 상당히 큰 영상 파일이다.
인코딩 수행 시간 및 결과
영상 파일의 용량이 커서 그런지 총 인코딩 시간은 15.5초가 걸렸다.
인코딩 수행된 영상 파일 정보
인용량은 99% 이상 줄어들었다.
수행 시간이 길었던 만큼 굉장히 많이 줄어들었고 그만큼 화질이 안 좋아진거는 어쩔 수 없는것같다.
원본 영상 정보와는 달리 추가정보란에 데이터가 없는데 이 부분은 메타데이터 입력을 통해 추가살 수 있다.
attrs.isMapMetaData = true
'성능 개선' 카테고리의 다른 글
JMeter를 활용하여 댓글 조회 기능 성능 개선 (with Spring Boot) (0) | 2022.03.22 |
---|---|
[JMeter] JMeter를 이용하여 성능 테스트 (with Spring Boot) (0) | 2022.03.22 |