-
Notifications
You must be signed in to change notification settings - Fork 2
๐ HLS ํ๋กํ ์ฝ์ ๊ดํ ์ ๋ฆฌ ๋ฐ FFmpeg ์ฌ์ฉ๊ธฐ
- Apple์์ ๋ง๋ HTTP protocol ์์ ๋์ํ๋ ๋น๋์ค ์คํธ๋ฆฌ๋ฐ ํ๋กํ ์ฝ
- HTTP์ ํน์ง๋ค (ex: caching)์ ์ฌ์ฉํ ์ ๊ฐ ์์
- ๋คํธ์ํฌ ์ํ์ ๋์ ์ผ๋ก ๋ฐ์ํ์ฌ ๋์ ๊ธฐ๋ฅ์ adaptiveํ๊ฒ ๋ง์ถ์ด์ค
์ถ์ฒ: https://developer.apple.com/streaming/
ํ๋กํ ์ฝ | ์ง์ฐ์๊ฐ | ํ์ฅ์ฑ | CDN ํธํ์ฑ | ์ ์ํ ์คํธ๋ฆฌ๋ฐ | ๋๋ฐ์ด์ค ํธํ์ฑ |
---|---|---|---|---|---|
HLS | ์ค๊ฐ(2-30์ด) | ๋งค์ฐ ๋์ | ๋งค์ฐ ์ข์ | ์ง์ | ๋งค์ฐ ๋์ |
DASH | ์ค๊ฐ(2-30์ด) | ๋์ | ์ข์ | ์ง์ | ๋์ |
RTMP | ๋ฎ์(1-5์ด) | ๋ฎ์ | ์ ํ์ | ๋ฏธ์ง์ | ์ ํ์ |
์ฅ์ | ์ค๋ช |
---|---|
HTTP ๊ธฐ๋ฐ ์ ์ก | - ๊ธฐ์กด ์น ์ธํ๋ผ ํ์ฉ ๊ฐ๋ฅ - ๋ฐฉํ๋ฒฝ ํต๊ณผ ์ฉ์ด - CDN ํ์ฅ์ฑ ์ฐ์ |
์ ์ํ ์คํธ๋ฆฌ๋ฐ | - ๋คํธ์ํฌ ์ํ์ ๋ฐ๋ผ ํ์ง ์๋ ์กฐ์ - ๋ค์ํ ๋์ญํญ ํ๊ฒฝ ์ง์ |
๋์ ์์ ์ฑ | - ์ธ๊ทธ๋จผํธ ๊ธฐ๋ฐ ์ ์ก์ผ๋ก ์ค๋ฅ ๋ณต์ ์ฉ์ด - ๋ฒํผ๋ง ์ต์ํ |
๋๋ฐ์ด์ค ํธํ์ฑ | - iOS/Android ๋ชจ๋ ๋ค์ดํฐ๋ธ ์ง์ - ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ์ง์ |
ํ์ฅ์ฑ | - ์๋ง ๋ช
์ ๋์ ์์ฒญ์ ์ฒ๋ฆฌ ๊ฐ๋ฅ - CDN ํ์ฉ์ผ๋ก ๊ธ๋ก๋ฒ ์๋น์ค ์ฉ์ด |
File extension์ ๊ดํ ์ ๋ฆฌ
-
.m3u8
: Segmented file์ ๊ดํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ ์ธ๋ฑ์ค ํ์ผ์ extension. ์ฃผ์ ๋ด์ฉ์ผ๋ก๋ ๋ค์๊ณผ ๊ฐ๋ค- ๊ฐ
.ts
ํ์ผ์ URL โ m3u8์ ํด๋ผ์ด์ธํธ๊ฐ ์ฝ๊ณ ts ํ์ผ์ ๊ดํ ์์ฒญ์ ์งํํจ์ผ๋ก ํด๋น ๋ด์ฉ์ ํ์์ !!! - ์์ ํ์ง/ํด์๋ ์ ๋ณด
- ๋์ญํญ ์ ๋ณด
- ๊ฐ
-
.ts
: ๋๋์ด์ง content๋ฅผ ๊ฐ์ ์ ์ฅํ๋ ํ์ผ- ๋ณดํต ๋ช ์ด ๋จ์๋ก ๋ถํ ๋จ(์ผ๋ฐ์ ์ผ๋ก 5-10์ด)
- ๋ ๋ฆฝ์ ์ผ๋ก ์ฌ์ ๊ฐ๋ฅ
- ๋คํธ์ํฌ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ง์ ์กฐ๊ฐ์ผ๋ก ์ ํ ๊ฐ๋ฅ
- ๋ฒํผ๋ง ์์ด ๋๊น ์๋ ์ฌ์ ๊ฐ๋ฅ
Express์์ ํ์ํ ํจํค์ง ์ ๋ฆฌ
yarn install fluent-ffmpeg @ffmpeg-installer/ffmpeg
yarn install hls-server
ffmpeg
๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก HLS ํ์์ผ๋ก ๋ณํ ๋ฐ index file ์์ฑ์ ์ง์. ffmpeg
์ญํ :
- ์๋ณธ ๋น๋์ค/์ค๋์ค๋ฅผ HLS ํฌ๋งท์ผ๋ก ๋ณํ
- .ts ์ธ๊ทธ๋จผํธ ํ์ผ๋ค๋ก ๋ถํ
- .m3u8 ์ฌ์๋ชฉ๋ก ํ์ผ ์์ฑ
- ํ์์ ์ปจํ ์ธ ์ํธํ
ํ ์คํธ ์งํ ๋ชฉ์
- ์๋ฒ์์ ์ ์ฅํ ์์ ํ์ผ์ HLS ์์์ ๋ง๊ฒ encryption์ ์งํํ๊ณ ๋ฒ์์ ๋ง๋ segmentation์ ์งํํ๋์ง ํ์ธํ๊ธฐ ์ํด
- ํด๋ผ์ด์ธํธ์์ ์์ฒญ์์ ์๋ฒ๊ฐ ๋ฐํ์ ๋ฌธ์ ์์ด ํ๋์ง ํ์ธํ๊ธฐ ์ํด
FfmpegService
async convertToHLS(inputPath: string, outputPath: string): Promise<void> {
return new Promise((resolve, reject) => {
ffmpeg(inputPath, { timeout: 432000 })
.addOptions([
'-c:a aac',
'-b:a 128k',
'-hls_time 10',
'-hls_list_size 0',
'-f hls',
])
.output(outputPath)
.on('progress', (progress) => {
console.log('Processing: ', progress.percent, '% done');
})
.on('start', (commandLine) => {
console.log('FFmpeg command:', commandLine);
})
.on('stderr', (stderrLine) => {
console.log('FFmpeg stderr:', stderrLine);
})
.on('end', () => {
console.log('Processing finished successfully');
resolve();
})
.on('error', (err, stdout, stderr) => {
console.error('FFmpeg Error:', err);
console.error('FFmpeg stdout:', stdout);
console.error('FFmpeg stderr:', stderr);
reject(err);
})
.run();
});
}
-
-c:a aac
: audio codec AAC๋ก ์ค์ -
-b:a 128k
: bit rate๋ฅผ 128k๋ก ์ค์ -
-hls_time 10
: hls segment duration์ 10์ด๋ก ์ค์ -
-hls_list_size 0
: maximum number of playlist entries๋ฅผ ์ค์ (0์ ๋ฆฌ๋ฐ์ด ์๋ค๋ ๋ป) -
-f hls
: ์์
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.008778,
output0.ts
#EXTINF:10.008778,
output1.ts
#EXTINF:9.985556,
output2.ts
#EXTINF:10.008778,
output3.ts
#EXTINF:10.008778,
output4.ts
#EXTINF:9.985556,
output5.ts
#EXTINF:10.008778,
output6.ts
#EXTINF:10.008778,
output7.ts
#EXTINF:9.985556,
output8.ts
#EXTINF:8.061011,
output9.ts
#EXT-X-ENDLIST
-
EXTM3U
: extended m3u file์์ ๋ํ๋ -
EXT-X-VERSION
: ํ๋ ์ด๋ฆฌ์คํธ ํ์ผ์ compatibility version์ ์๋ ค์ค -
EXT-X-TARGETDURATION
: ๊ฐ ๋ฏธ๋์ด ํ์ผ์ duration ์ง์ -
EXT-X-MEDIA-SEQUENCE
:- ์ฒซ segment์ sequence number ํ์
- VOD๋ 0์ผ๋ก ํ์
#EXT-X-ENDLIST
: ํ๋ ์ด๋ฆฌ์คํธ ์ข ๋ฃ๋ฅผ ๋ํ๋
์์ฑ๋ ํ์ผ format:
๐ 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์ฃผ์ฐจ