๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Javascript

Hls.js ์‚ฌ์šฉ

by frontChoi 2023. 6. 14.
๋ฐ˜์‘ํ˜•

๐Ÿ“บ HLS(Http Live Streaming)

HLS(HTTP ๋ผ์ด๋ธŒ ์ŠคํŠธ๋ฆฌ๋ฐ)์€ ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋น„๋””์˜ค ์ŠคํŠธ๋ฆฌ๋ฐ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค. HTTP "๋ผ์ด๋ธŒ" ์ŠคํŠธ๋ฆฌ๋ฐ์ด๋ผ ๋ถˆ๋ฆฌ์ง€๋งŒ ์ฃผ๋ฌธํ˜• ์ŠคํŠธ๋ฆฌ๋ฐ์ด์ž ๋™์‹œ์— ๋ผ์ด๋ธŒ ์ŠคํŠธ๋ฆฌ๋ฐ์ž…๋‹ˆ๋‹ค. HLS๋Š” ๋น„๋””์˜ค ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” HTTP ํŒŒ์ผ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ„๊ณ  HTTP ํ”„๋กœํ† ์ฝœ์„ ์ด์šฉํ•˜์—ฌ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์žฅ์น˜๋Š” ์ด๋Ÿฌํ•œ HTTP ํŒŒ์ผ์„ ๋กœ๋“œํ•œ ํ›„ ๋น„๋””์˜ค๋กœ ์žฌ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ”‹ Hls.js

Hls.js๋Š” http live streaming์„ ๊ตฌํ˜„ํ•˜๋Š” javascript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.  
ios/safari ๊ฐ™์€ ๊ฒฝ์šฐ ๋นŒํŠธ์ธ์ด ๋˜์–ด์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ง€์›ํ•˜์ง€๋Š” ์•Š๊ณ , ๋‹ค๋ฅธ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” Hls.js๋ฅผ ํ†ตํ•ด์„œ ์ŠคํŠธ๋ฆฌ๋ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ’ฐ Hls.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ

cdn ๋ฐฉ์‹์œผ๋กœ hls๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<!-- ######### hls ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ cdn ๋ฐฉ์‹์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.######### -->
	<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
	<script src="https://vjs.zencdn.net/8.3.0/video.min.js"></script>
	<title>Hls Practice</title>
	<style>
		video {
			max-width: 500px;
			width: 100%;
			max-height: 500px;
			height: 100%;
			object-fit: fill;
		}
	</style>
</head>

<body>
	<!--
		controls : ์‚ฌ์šฉ์ž๊ฐ€ ๋น„๋””์˜ค ์ปจํŠธ๋กค์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค
		playsinline : ์ „์ฒด ํ™”๋ฉด ๋ฐฉ์ง€์ด๋‹ค
		autoplay : ์ž๋™์žฌ์ƒ์ด๋ฉฐ , ์ •์ฑ…์ƒ ์Œ์†Œ๊ฑฐ ์ƒํƒœ์—์„œ ๊ฐ€๋Šฅํ•˜๋‹ค.
	-->
	<video id="video" controls playsinline autoplay></video>

</body>

</html>

 

๋‹ค์Œ์œผ๋กœ ์ƒ˜ํ”Œ m3u8 url๋ฅผ ์ค€๋น„ํ•˜๊ณ , video๋ฅผ ์ดˆ๊ธฐํ™” ์‹œํ‚ต๋‹ˆ๋‹ค.

<script>
    /* video Element */
    let video = null;
    /* ์ƒ˜ํ”Œ m3u8 url */
    let videoSrc = 'https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8'

    /* initVideo */
    const initVideo = () => {
        video = document.querySelector('#video')
    }

    /* DOMContentLoaded ๋กœ๋“œ๋ฅผ ํ†ตํ•ด video Element ๋‹ด๊ธฐ*/
    window.addEventListener("DOMContentLoaded", () => {
        initVideo();
    })
</script>

 

์ธ์ œ hls.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐํ™” ์‹œํ‚ต๋‹ˆ๋‹ค.

"initHls" ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด hls๋ฅผ ์ดˆ๊ธฐํ™” ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์—ฌ๊ธฐ์„œ Hls๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ ๊ทธ๊ฑด ios/safari ์ด๋‹ค. ios/safari๋Š” hls๊ฐ€ built-in์ด ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

<script>
    /* video Element */
    let video = null;
    /* ์ƒ˜ํ”Œ m3u8 url */
    let videoSrc = 'https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8'

    /* initVideo */
    const initVideo = () => {
        video = document.querySelector('#video')
    }

    /* initHls : hls๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ํ•จ์ˆ˜ */
    const initHls = () => {
        if (Hls.isSupported()) {
            hls = new Hls({
                autoStartLoad: false,
            });
            hls.loadSource(videoSrc);
            hls.attachMedia(video);
            hls.startLoad();
        }
        /* ios/safari ๊ฐ™์€ ๊ฒฝ์šฐ์— hls๊ฐ€ built-in ๋˜์–ด์žˆ๋‹ค.*/
        else {
            video.src = videoSrc;	
        }
    }

    /* DOMContentLoaded ๋กœ๋“œ๋ฅผ ํ†ตํ•ด video Element ๋‹ด๊ธฐ*/
    window.addEventListener("DOMContentLoaded", () => {
        initVideo();
        initHls();
    })

</script>

์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๋ฉด ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 

๋‹ค์Œ์—๋Š” video "์ž๋™์žฌ์ƒ" ์‹œํ‚ค๊ธฐ๋ฅผ ํ•ด๋ณผ์˜ˆ์ •์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  hls.js ๋Œ€ํ•œ config์€ https://github.com/video-dev/hls.js/blob/master/docs/API.md ์—์„œ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€