-
Notifications
You must be signed in to change notification settings - Fork 2
๐ ์จ๋ฒ ๋จ์๋ก ์คํธ๋ฆฌ๋ฐ ํ๊ธฐ (with HLS)
HLS๋ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ ํ๋กํ ์ฝ๋ก,
ํด๋ผ์ด์ธํธ๋ ๋ฏธ๋์ด์ ๋ํ playlist๋ฅผ ์์ฒญํ๊ณ , ์๋ฒ๋ ์ด๋ฅผ ๋ณด๋ด์ค๋ค.
ํด๋ผ์ด์ธํธ๋ ๋ฐ์ playlist๋ฅผ ์ฝ์ด ์๊ฐ์ ๋ง๋ ์ธ๊ทธ๋จผํธ๋ฅผ ์๋ฒ์ ์์ฒญํ๋ ๋ฐฉ์์ด๋ค.
์ฐ๋ฆฌ ํ๋ก์ ํธ๋ ์จ๋ฒ ๋จ์๋ก ์คํธ๋ฆฌ๋ฐํ๊ธฐ ๋๋ฌธ์, ์ฌ๋ฌ ๋ ธ๋๊ฐ ํ๋์ ์ธ์ ์์ ์คํธ๋ฆฌ๋ฐ ๋์ด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
- ์จ๋ฒ ๋
ธ๋ ์์๋ฅผ ๋ด์ master
m3u8
ํ์ผ์ ๋ง๋ค์ด์ ํด๋ผ์ด์ธํธ๊ฐ ํ์ฑํ๋ค- ํด๋ผ์ด์ธํธ๊ฐ master
m3u8
ํ์ผ์ ์์ฒญํ๋ค - ์๋ฒ๋ ์์ฒญ ๋ฐ์ ์๊ฐ์ ๋ง์ถฐ (์ง๋๊ฐ ๋
ธ๋๋ฅผ ์ ์ธํ) master
m3u8
ํ์ผ์ ๋ณด๋ธ๋ค - ํด๋ผ์ด์ธํธ๋ ํด๋น m3u8ํ์ผ์ ํ์ฑํด์ ์ฒซ๋ฒ์งธ ๋
ธ๋์ playlist
m3u8
์ ์์ฒญํ๋ค - ์๋ฒ๋ ์์ฒญ ๋ฐ์ ์๊ฐ์ ๋ง์ถฐ (์ง๋๊ฐ ์ธ๊ทธ๋จผํธ๋ฅผ ์ ์ธ) ์ธ๊ทธ๋จผํธ๋ฅผ ์ ์กํ๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ master
- ํด๋ผ์ด์ธํธ๊ฐ playlist๋ฅผ ์์ฒญํ๋ฉด, ์๋ฒ์์ ์ด ์จ๋ฒ ๊ธธ์ด์ ๋น๊ตํz์ฌ ์์ฒญ ์๊ฐ์ ํด๋นํ๋ ๊ณก์
m3u8
์ ๋ณด๋ธ๋ค.- ํด๋ผ์ด์ธํธ๊ฐ playlist๋ฅผ ์์ฒญํ๋ค
- ์๋ฒ๋ ์ด ์จ๋ฒ์ ์๊ฐ๊ณผ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ณด๋ธ ์๊ฐ์ ๊ณ์ฐํ์ฌ, ๋ช ๋ฒ์งธ, ๋ช ์ด์ฏค์ธ์ง ๊ณ์ฐํ๋ค
- ์๊ฐ์ ๋ง๋ ๋ ธ๋์ ์ง๋๊ฐ ์ธ๊ทธ๋จผํธ๋ฅผ ์ ์ธํ ์ธ๊ทธ๋จผํธ ํ์ผ์ ์ ์กํ๋ค.
1๋ฒ ๋ฐฉ๋ฒ์ ๊ฒฝ์ฐ,
- ํด๋ผ์ด์ธํธ๊ฐ ์ง์ ์คํธ๋ฆฌ๋ฐ ํ๋ฆ์ ์ ์ดํ ์ ์๋ค
- HlS.js master m3u8 ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค
- ํด๋ผ์ด์ธํธ ์ธก ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๋ค
- ํ์ฑ ๋ก์ง ๊ตฌํ์ ์ด๋ ค์์ด ์๋ค
- ํ์ฅ์ฑ์ด ์ ํ์ ์ด๋ค
2๋ฒ ๋ฐฉ๋ฒ์ ๊ฒฝ์ฐ,
- ์๋ฒ์์ ์ ์ฒด ์คํธ๋ฆฌ๋ฐ ํ๋ฆ์ ์ ์ดํ๋ค
- ํด๋ผ์ด์ธํธ ๊ตฌํ์ด ๋จ์ํํ๋ค.
- ํ์ฅ์ฑ์ด ๋๋ค
- ์๋ฒ์์ ์๊ฐ์ ๊ณ์ฐํจ์ผ๋ก ์ค๋ฒํค๋๊ฐ ์ฆ๊ฐํ๊ณ , ๋ก์ง์ด ๋ณต์กํด์ง๋ค
- ์ ํํ ์๊ฐ ๊ณ์ฐ ์๊ณ ๋ฆฌ์ฆ์ด ํ์ํ๋ค
โ ย 2๋ฒ ๋ฐฉ๋ฒ์ผ๋ก ์ ํ
2๋ฒ ๋ฐฉ๋ฒ์ด ์๋ฒ ์ค์ฌ์ผ๋ก ์ ์ดํจ์ผ๋ก, ์ฌ์ฉ์๋ค์๊ฒ ์ผ๊ด๋๊ฒ ๋ ธ๋๊ฐ ์ฌ์๋ ์ ์๋ค๋ ์ฅ์ ์ด ์์ด ์ ํํ๋ค.
๋, ํด๋ผ์ด์ธํธ์์์ ํ์ผ ํ์ฑ์ด ์๋ฌ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ๋ ๋๋ค๊ณ ํ๋จํ๋ค.
2๋ฒ ๋ฐฉ๋ฒ ์ ํ์ผ๋ก ํ๋ก ํธ์๋์์๋ playlist m3u8
์ ์์ฒญ๋ง ํ๋ฉด ๋๋ค.
ํ๋์ ๋ฌธ์ ๋ ๋ค์ ๋
ธ๋๋ก ๋์ด๊ฐ ๋, ๋ค์ m3u8
์ ์์ฒญํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
์ด ๋ฌธ์ ๋ audio
ํ๊ทธ์ ended
์ด๋ฒคํธ๋ฅผ ํตํด ์ฒ๋ฆฌํ๋ค.
- ์จ๋ฒ์ ๋ํ playlist url ๋ง๋ค๊ธฐ
const createStreamUrl = (roomId: string) =>`${import.meta.env.VITE_API_URL}/api/music/${roomId}/playlist.m3u8`;
- hls ์ฐ๊ฒฐ
const initializeHls = (audio: HTMLMediaElement, streamUrl: string) => {
destroyHls();
const hls = new Hls(DEFAULT_STREAMING_CONFIG);
hlsRef.current = hls;
hls.loadSource(streamUrl);
hls.attachMedia(audio);
hls.on(Hls.Events.MANIFEST_PARSED, () => setIsLoaded(true));
hls.on(Hls.Events.ERROR, (error) =>
console.error('Streaming error:', error),
);
};
- ๋ค์ ๋ ธ๋๋ก ๋์ด๊ฐ๊ฒ ์ฒ๋ฆฌ ( ended
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
const handleEnded = () => {
setIsLoaded(false);
if (songIndex + 1 > totalSongs) {
setSongIndex(1);
...
return;
}
setSongIndex((prev) => prev + 1);
playStream();
};
audio.addEventListener('ended', handleEnded);
return () => {
audio.removeEventListener('ended', handleEnded);
};
}, [songIndex, totalSongs]);
๐ ffmpeg๋ stderr๋ก ๋๋ฒ๊น
์ ํ๋ ์ด์
๐ HLS ํ๋กํ ์ฝ์ ๊ดํ ์ ๋ฆฌ ๋ฐ FFmpeg ์ฌ์ฉ๊ธฐ
๐ ๋นํธ๋ tsconfig.json์ด ์ธ ๊ฐ?
๐ NestJS ๊ธฐ๋ณธ ๊ฐ๋
- Modules
๐ Socket.io ์ต(๊ฐ)์ ํ
๐ ๋์ปค์ nginx์ ์ฌ์ฉ๊ธฐ
๐ ๋ถํํ
์คํธ๋ฅผ ํด๋ณด์
๐ FSD ์ฌ์ฉ๊ธฐ, ๊ทผ๋ฐ ์ด์ ๋๋ง์ ๊ท์น์ ๊ณ๋ค์ธ
๐ CICD ๊ตฌ์กฐ ์์
๐ ์จ๋ฒ ๋จ์๋ก ์คํธ๋ฆฌ๋ฐ ํ๊ธฐ (with HLS)
๐ HLS๋ก ์์
์ฃผ๊ณ ๋ฐ๊ธฐ
๐ vite + react + typescript ํ๊ฒฝ์์ path alias ์ค์
๐ React Scan์ด ๋ญ์ฃ ?
๐ ๋ก์ปฌ ํ๊ฒฝ ๊ฐ๋ฐ ๋ชจ๋ ๋ฐฐํฌ
๐ ์จ๋ฒ ์ ์ฒด๋ฅผ ์คํธ๋ฆฌ๋ฐํ๋ค๊ณ ? (with HLS)
๐ ์ฝ๋์ ์์ ์ฑ์ ๋์ด๊ธฐ ์ํด ํ
์คํธ์ฝ๋๋ฅผ ์์ฑํด๋ณด์
๐ ์๋ก๊ณ ์นจ ์ HLS ERROR
๐ input ํ๊ทธ์ ํ๊ธ ์
๋ ฅ ํ, Enter๋ฅผ ๋๋ฅด๋ฉด ํจ์๊ฐ ๋๋ฒ ํธ์ถ๋๋ ์ค๋ฅ
๐ nginx proxy pass๋ฅผ ๋ฐ๊ฟจ๋๋ ์๊ธด ์๋ฌ - ์ค์จ๊ฑฐ ์ธ์ ๋ฌธ์
๐ ๋ฐฐํฌ ํ๊ฒฝ์์ ํด๋ผ์ด์ธํธ-์๋ฒ WS handshake
๐ ๋ ๋๋ง ๋ฒ์ธ์ ํ๋!
๐ ๊ทธ๋ผ์ด๋ ๋ฃฐ
๐ฅ ํ์ ์๊ฐ
๐ ์ฝ๋ & ๊น ์ปจ๋ฒค์
๐ณ ๊น branch ์ ๋ต
๐ ๋
ธ์
๋ฌธ์ ์ ์ฅ์
๐จ ํผ๊ทธ๋ง
๐งโ๐ป ๊ธฐํ ๊ณต์ ๋ฐํ ์๋ฃ
๐ค 2์ฃผ์ฐจ ๋ฐํ ์๋ฃ
๐ ๋ฐฑ๋ก๊ทธ
๐ 1์ฃผ์ฐจ
๐ 2์ฃผ์ฐจ
๐ 3์ฃผ์ฐจ
๐ 4์ฃผ์ฐจ
๐ 5์ฃผ์ฐจ
๐๏ธ 1์ฃผ์ฐจ
๐๏ธ 2์ฃผ์ฐจ
๐๏ธ 3์ฃผ์ฐจ
๐๏ธ 4์ฃผ์ฐจ
๐๏ธ 5์ฃผ์ฐจ
โจ 1์ฃผ์ฐจ
โจ 2์ฃผ์ฐจ
โจ 3์ฃผ์ฐจ
โจ 4์ฃผ์ฐจ