이전 방식은 mp4 파일을 HTML5 video 태그를 이용하여 영상을 재생했다.
이번엔 스트리밍에 자주 사용되는 apple에서 개발한 HLS 프로토콜을 이용해 영상을 재생해보자.
application/x-mpegURL
이다.
- ffmpeg wrapper 사용
implementation 'net.bramp.ffmpeg:ffmpeg:0.7.0'
FFmpegConfig
ffmpeg
, ffprobe
를 빈으로 등록@Slf4j
@Configuration
public class FFmpegConfig {
@Value("${ffmpeg.path}")
private String ffmpegPath;
@Value("${ffprobe.path}")
private String ffprobePath;
@Bean
public FFmpeg ffMpeg() throws IOException {
return new FFmpeg(ffmpegPath);
}
@Bean
public FFprobe ffProbe() throws IOException {
return new FFprobe(ffprobePath);
}
}
ConvertController
@RestController
@RequiredArgsConstructor
public class ConvertController {
private final ConvertService convertService;
@ResponseBody
@PostMapping("/convert/hls/{date}/{filename}")
public String convertToHls(
@PathVariable String date,
@PathVariable String filename
) {
convertService.convertToHls(date, filename);
return "success";
}
}
ConvertService
@Slf4j
@Service
@RequiredArgsConstructor
public class ConvertService {
private final FFmpeg fFmpeg;
private final FFprobe fFprobe;
@Value("${tus.save.path}")
private String savedPath;
@Value("${tus.output.path.hls}")
private String hlsOutputPath;
@Value("${tus.output.path.mp4}")
private String mp4OutputPath;
public void convertToHls(String date, String filename) {
String path = savedPath + "/" + date + "/" + filename;
File output = new File(hlsOutputPath + "/" + filename.split("\\.")[0]);
if (!output.exists()) {
output.mkdirs();
}
FFmpegBuilder builder = new FFmpegBuilder()
.setInput(path) // 입력 소스
.overrideOutputFiles(true)
.addOutput(output.getAbsolutePath() + "/master.m3u8") // 출력 위치
.setFormat("hls")
.addExtraArgs("-hls_time", "10") // 10초
.addExtraArgs("-hls_list_size", "0")
.addExtraArgs("-hls_segment_filename", output.getAbsolutePath() + "/master_%08d.ts") // 청크 파일 이름
.done();
run(builder);
}
private void run(FFmpegBuilder builder) {
FFmpegExecutor executor = new FFmpegExecutor(fFmpeg, fFprobe);
executor
.createJob(builder, progress -> {
log.info("progress ==> {}", progress);
if (progress.status.equals(Progress.Status.END)) {
log.info("================================= JOB FINISHED =================================");
}
})
.run();
}
}
POST http://localhost:8080/convert/hls/{date}/{filename}
HlsController
application/x-mpegURL
로 설정하여 내려준다.@Controller
@RequiredArgsConstructor
public class HlsController {
private final HlsService hlsService;
@ResponseBody
@RequestMapping("/hls/{key}/{filename}")
public ResponseEntity<InputStreamResource> getHlsFile(
@PathVariable String key,
@PathVariable String filename
) throws FileNotFoundException {
File file = hlsService.getHlsFile(key, filename);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/x-mpegURL"))
.body(resource);
}
}
HlsService
@Service
@RequiredArgsConstructor
public class HlsService {
@Value("${tus.output.path.hls}")
private String outputPath;
public File getHlsFile(String key, String filename) {
return new File(outputPath + "/" + key + "/" + filename);
}
}
http://localhost:8080/hls/dfb2effa54b843ec97e6dae71c845615/master.m3u8
hls_player.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Uploaded vod</title>
<link href="https://vjs.zencdn.net/7.14.3/video-js.css" rel="stylesheet" />
<script src="https://vjs.zencdn.net/7.14.3/video.min.js"></script>
</head>
<body>
<video id="my-video" class="video-js" controls preload="auto" width="720" height="480">
<source src="http://localhost:8080/hls/dfb2effa54b843ec97e6dae71c845615/master.m3u8" type="application/x-mpegURL">
</video>
<script>
var player = videojs('my-video');
player.play();
</script>
</body>
</html>
CORS 에러 발생시
CORS 설정
WebConfig
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*"); } }
필요했던 내용입니다 감사합니다.