2022-12-01-TIL
2022-12-01-TIL
Today I Learned
FFmpeg in Spring Boot
FFmpeg은 영상과 음성을 변환, 자르기, 인코딩, 스트리밍용으로 분할하는 커맨드라인 도구다. Java에는 FFmpeg을 대체할 만한 순수 라이브러리가 마땅치 않아서, Spring Boot 애플리케이션에서는 서버에 FFmpeg을 설치해 두고 ProcessBuilder로 명령을 실행하는 방식이 가장 흔하다.
springcloud.io의 예제가 이 구조를 보여 준다. 업로드된 영상을 FFmpeg으로 HLS 형식의 조각(.ts)으로 나누고(-hls_time으로 조각 길이 지정), AES로 암호화한 뒤 index.m3u8 재생 목록과 키, 커버 이미지를 만들어 돌려준다. 영상 정보는 ffprobe로 읽는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<String> cmd = List.of("ffmpeg", "-i", source.toString(),
"-c:v", "libx264", "-c:a", "aac",
"-hls_time", "10", "-hls_playlist_type", "vod",
target.resolve("index.m3u8").toString());
Process process = new ProcessBuilder(cmd)
.redirectErrorStream(true)
.start();
// 출력 스트림을 계속 읽어 주지 않으면 버퍼가 차서 프로세스가 멈출 수 있다
try (BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
r.lines().forEach(log::debug);
}
if (process.waitFor() != 0) {
throw new IllegalStateException("트랜스코딩 실패");
}
운영에서 주의할 점은 다음과 같다.
- 외부 프로세스의 표준 출력과 표준 에러를 읽어 주지 않으면 파이프 버퍼가 가득 차 프로세스가 멈출 수 있다.
ProcessJavadoc도 이 위험을 경고한다. - 트랜스코딩은 CPU를 오래 쓰므로 요청 스레드에서 동기로 돌리지 말고 작업 큐나 별도 워커로 넘긴다.
파일 이름 같은 사용자 입력을 명령 문자열에 이어 붙이지 말고, 위처럼 인자를 리스트로 넘긴다. 셸을 거치지 않으므로 명령 주입을 피할 수 있다.
- https://www.springcloud.io/post/2022-02/spring-boot-ffmpeg/#gsc.tab=0
- https://parkadd.tistory.com/126
- https://velog.io/@ace0390/Java-ffmpeg%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%8F%99%EC%98%81%EC%83%81-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0
- https://github.com/KevinBlandy/springboot-ffmpeg-demo
- https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ksw6169&logNo=221546693446
- https://dev.to/giboow/how-to-build-a-video-transcoder-with-springboot-and-ffmpeg-n7p
- https://swampwar.github.io/2020/07/02/java%EC%97%90%EC%84%9C-ffmpeg-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0.html
Spring Boot Media File Duration
업로드된 영상이나 음원의 재생 시간을 서버에서 확인하는 방법을 찾았다. 선택지는 형식에 따라 갈린다.
- WAV나 AIFF처럼 Java Sound API가 읽을 수 있는 형식은
AudioSystem.getAudioInputStream()으로 프레임 수와 초당 프레임 수를 얻어frameLength / frameRate로 계산한다. MP3나 MP4는 기본 Java Sound로 읽지 못한다. - MP4 같은 영상은 컨테이너 메타데이터를 읽는 라이브러리나, 앞의
ffprobe를 호출하는 방법이 확실하다.ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4는 재생 시간(초)만 출력한다. - 브라우저에서 업로드 전에
<video>요소의duration으로 미리 검사할 수도 있지만, 클라이언트 검사는 우회할 수 있으므로 서버 검증을 대신하지 못한다.
재생 시간 검사보다 먼저 걸리는 것이 업로드 크기 한도다. 영상은 Spring Boot의 기본 max-file-size(1MB)를 쉽게 넘으므로 spring.servlet.multipart.max-file-size, max-request-size를 함께 올려야 한다. 단계별 크기 한도는 6월 29일 TIL에 정리했다.
- https://www.baeldung.com/java-play-sound
- https://stackoverflow.com/questions/13528588/retrieving-resolution-duration-of-a-video-file-before-upload
- https://liferay.dev/ask/questions/development/how-to-get-duration-of-video-while-uploading-1
- https://github.com/EvgeniyZhukovets/uploading-mp4-with-duration-filter-and-checking-for-file-availability
- https://stackoverflow.com/questions/7319096/video-file-time-length-in-minute-while-uploading-to-server-in-spring-or-j2ee
- https://stackoverflow.com/questions/37540028/how-to-set-the-max-size-of-upload-file
- https://www.folkstalk.com/2022/10/spring-media-part-max-size-with-code-examples.html
- https://gainjavaknowledge.medium.com/spring-boot-file-upload-example-e5c516e681a9
- https://stackabuse.com/uploading-files-with-spring-boot/
- https://coderanch.com/t/581592/java/Calculating-video-file-duration
- https://stackoverflow.com/questions/3009908/how-do-i-get-a-sound-files-total-time-in-java
macOS Command
macOS에만 있는 커맨드라인 도구를 모은 글이다. 알아 두면 쓸 만한 것을 몇 개 고르면 다음과 같다.
caffeinate: 명령이 끝날 때까지 잠자기 모드를 막는다.caffeinate -i ./long-build.shpbcopy,pbpaste: 클립보드와 표준 입출력을 연결한다.cat key.pub | pbcopynetworkQuality: 인터넷 속도를 측정한다.sips: 이미지 크기 변경과 형식 변환을 한다.mdfind: Spotlight 색인으로 파일을 검색한다.say: 텍스트를 음성으로 읽는다. 긴 작업이 끝났을 때 알림으로 쓸 수 있다.- https://saurabhs.org/advanced-macos-commands
Links
- F-Lab 블로그의 “좋은 개발자가 되는 법”에 관한 글이다.
- Apple의 App Store Awards 페이지다. 2022년판을 보려고 저장했지만, 지금은 같은 주소가 최신 연도의 수상작 페이지를 보여 준다.
web.dev의 새 뷰포트 단위 글(2022년 11월 29일)은 모바일 브라우저의 동적 툴바 때문에
100vh가 화면을 넘치는 문제를 다룬다. 툴바가 펼쳐진 상태 기준인svh(small), 접힌 상태 기준인lvh(large), 툴바 상태에 따라 그 사이에서 변하는dvh(dynamic) 단위가 추가되었다(web.dev).- https://f-lab.kr/blog/how-to-be-good-developer
- https://developer.apple.com/app-store/app-store-awards-2022/
- https://web.dev/viewport-units/
댓글
아직 댓글이 없습니다