๋ธ๋ผ์ฐ์ ์์ ๊ณ ํ์ง ๋น๋์ค ์คํธ๋ฆฌ๋ฐ์ ๊ตฌํํ์ธ์. WebCodecs API์ VideoFrame ์กฐ์์ ์ฌ์ฉํ์ฌ ๋ ธ์ด์ฆ ๊ฐ์๋ฅผ ์ํ ๊ณ ๊ธ ์๊ฐ์ ํํฐ๋ง ๊ตฌํ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
WebCodecs ๋ง์คํฐํ๊ธฐ: ์๊ฐ์ ๋ ธ์ด์ฆ ๊ฐ์๋ฅผ ํตํ ๋น๋์ค ํ์ง ํฅ์
์น ๊ธฐ๋ฐ ๋น๋์ค ํต์ , ์คํธ๋ฆฌ๋ฐ, ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ธ๊ณ์์๋ ํ์ง์ด ๊ฐ์ฅ ์ค์ํฉ๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์๋ค์ ๋น์ฆ๋์ค ๋ฏธํ , ๋ผ์ด๋ธ ์ด๋ฒคํธ ์์ฒญ, ์๊ฒฉ ์๋น์ค์์ ์ํธ์์ฉ ๋ฑ ์ด๋ค ์ํฉ์์๋ ์ ๋ช ํ๊ณ ๊นจ๋ํ ๋น๋์ค๋ฅผ ๊ธฐ๋ํฉ๋๋ค. ํ์ง๋ง ๋น๋์ค ์คํธ๋ฆผ์ ์ข ์ข ๋ ธ์ด์ฆ๋ผ๋ ์ง์์ ์ด๊ณ ๋ฐฉํด๋๋ ์ธ๊ณต๋ฌผ(artifact)๋ก ์ธํด ์ด๋ ค์์ ๊ฒช์ต๋๋ค. ๊ฑฐ์น ๊ฑฐ๋ ์ ์ ์ธ ์ง๊ฐ์ผ๋ก ๋ณด์ด๋ ์ด ๋์งํธ ๋ ธ์ด์ฆ๋ ์์ฒญ ๊ฒฝํ์ ์ ํ์ํค๊ณ , ๋๋๊ฒ๋ ๋์ญํญ ์๋น๋ฅผ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค. ๋คํํ๋, WebCodecs๋ผ๋ ๊ฐ๋ ฅํ ๋ธ๋ผ์ฐ์ API๋ ๊ฐ๋ฐ์์๊ฒ ์ด ๋ฌธ์ ๋ฅผ ์ ๋ฉด์ผ๋ก ํด๊ฒฐํ ์ ์๋ ์ ๋ก ์๋ ๋ก์ฐ-๋ ๋ฒจ(low-level) ์ ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
์ด ์ข
ํฉ ๊ฐ์ด๋๋ ํน์ ํ๋ฉด์๋ ์ํฅ๋ ฅ์ด ํฐ ๋น๋์ค ์ฒ๋ฆฌ ๊ธฐ์ ์ธ ์๊ฐ์ ๋
ธ์ด์ฆ ๊ฐ์๋ฅผ ์ํด WebCodecs๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๊น์ด ์์๋ณผ ๊ฒ์
๋๋ค. ๋น๋์ค ๋
ธ์ด์ฆ๊ฐ ๋ฌด์์ธ์ง, ์ ํด๋ก์ด์ง, ๊ทธ๋ฆฌ๊ณ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ํํฐ๋ง ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ๊ธฐ ์ํด VideoFrame
๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ํ๊ตฌํ ๊ฒ์
๋๋ค. ๊ธฐ๋ณธ ์ด๋ก ๋ถํฐ ์ค์ JavaScript ๊ตฌํ, WebAssembly๋ฅผ ์ฌ์ฉํ ์ฑ๋ฅ ๊ณ ๋ ค์ฌํญ, ๊ทธ๋ฆฌ๊ณ ์ ๋ฌธ๊ฐ ์์ค์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํ ๊ณ ๊ธ ๊ฐ๋
๊น์ง ๋ชจ๋ ๊ฒ์ ๋ค๋ฃฐ ๊ฒ์
๋๋ค.
๋น๋์ค ๋ ธ์ด์ฆ๋ ๋ฌด์์ด๋ฉฐ ์ ์ค์ํ๊ฐ?
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ ์ ๋จผ์ ์ดํดํด์ผ ํฉ๋๋ค. ๋์งํธ ๋น๋์ค์์ ๋ ธ์ด์ฆ๋ ๋น๋์ค ์ ํธ์ ๋ฐ๊ธฐ๋ ์์ ์ ๋ณด์ ๋ฌด์์์ ์ธ ๋ณ๋์ ์๋ฏธํฉ๋๋ค. ์ด๋ ์ด๋ฏธ์ง ์บก์ฒ ๋ฐ ์ ์ก ๊ณผ์ ์์ ๋ฐ์ํ๋ ๋ฐ๋์งํ์ง ์์ ๋ถ์ฐ๋ฌผ์ ๋๋ค.
๋ ธ์ด์ฆ์ ์์ธ๊ณผ ์ข ๋ฅ
- ์ผ์ ๋ ธ์ด์ฆ: ์ฃผ๋ ์์ธ์ ๋๋ค. ์ ์กฐ๋ ํ๊ฒฝ์์ ์นด๋ฉ๋ผ ์ผ์๋ ์ถฉ๋ถํ ๋ฐ์ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๋ค์ด์ค๋ ์ ํธ๋ฅผ ์ฆํญํฉ๋๋ค. ์ด ์ฆํญ ๊ณผ์ ์ ๋ฌด์์์ ์ธ ์ ์์ ๋ณ๋ ๋ํ ์ฆํญ์์ผ ๋์ ๋ณด์ด๋ ๊ทธ๋ ์ธ(grain)์ ๋ฐ์์ํต๋๋ค.
- ์ด ๋ ธ์ด์ฆ: ์นด๋ฉ๋ผ ์ ์ ๋ถํ์์ ๋ฐ์ํ๋ ์ด๋ก ์ธํด ์ ์๊ฐ ๋ฌด์์๋ก ์์ง์ด๋ฉด์ ๋น์ ์๊ณผ ๋ฌด๊ดํ ๋ ธ์ด์ฆ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ์์ํ ๋ ธ์ด์ฆ: ์๋ ๋ก๊ทธ-๋์งํธ ๋ณํ ๋ฐ ์์ถ ๊ณผ์ ์์ ์ฐ์์ ์ธ ๊ฐ์ด ์ ํ๋ ์ด์ฐ ๋ ๋ฒจ ์งํฉ์ผ๋ก ๋งคํ๋ ๋ ๋ฐ์ํฉ๋๋ค.
์ด๋ฌํ ๋ ธ์ด์ฆ๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฐ์์ ๋ ธ์ด์ฆ๋ก ๋ํ๋๋ฉฐ, ๊ฐ ํฝ์ ์ ๊ฐ๋๊ฐ ์ค์ ๊ฐ ์ฃผ์์์ ๋ฌด์์๋ก ๋ณ๋ํ์ฌ ํ๋ ์ ์ ์ฒด์ ๋ฏธ์ธํ๊ณ ๋ฐ์ง์ด๋ ๊ทธ๋ ์ธ์ ๋ง๋ญ๋๋ค.
๋ ธ์ด์ฆ์ ์ด์ค์ ์ํฅ
๋น๋์ค ๋ ธ์ด์ฆ๋ ๋จ์ํ ๋ฏธ๊ด์์ ๋ฌธ์ ๋ฅผ ๋์ด, ์๋นํ ๊ธฐ์ ์ ๋ฐ ์ง๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํฉ๋๋ค:
- ์ฌ์ฉ์ ๊ฒฝํ ์ ํ: ๊ฐ์ฅ ๋ช ๋ฐฑํ ์ํฅ์ ์๊ฐ์ ํ์ง์ ์์ต๋๋ค. ๋ ธ์ด์ฆ๊ฐ ๋ง์ ๋น๋์ค๋ ๋น์ ๋ฌธ์ ์ผ๋ก ๋ณด์ด๊ณ ์ฐ๋งํ๋ฉฐ, ์ค์ํ ์ธ๋ถ ์ฌํญ์ ๋ถ๊ฐํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ํ์ ํ์์ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ์ฐธ๊ฐ์๋ค์ด ๊ฑฐ์น ๊ณ ๋ถ๋ถ๋ช ํ๊ฒ ๋ณด์ฌ ํ์ฅ๊ฐ์ ๋จ์ด๋จ๋ฆด ์ ์์ต๋๋ค.
- ์์ถ ํจ์จ์ฑ ๊ฐ์: ๋ ์ง๊ด์ ์ด์ง๋ง ๋๊ฐ์ด ์ค์ํ ๋ฌธ์ ์ ๋๋ค. ์ต์ ๋น๋์ค ์ฝ๋ฑ(H.264, VP9, AV1 ๋ฑ)์ ์ค๋ณต์ฑ์ ํ์ฉํ์ฌ ๋์ ์์ถ๋ฅ ์ ๋ฌ์ฑํฉ๋๋ค. ์ด๋ค์ ํ๋ ์ ๊ฐ์ ์ ์ฌ์ฑ(์๊ฐ์ ์ค๋ณต์ฑ)๊ณผ ๋จ์ผ ํ๋ ์ ๋ด์ ์ ์ฌ์ฑ(๊ณต๊ฐ์ ์ค๋ณต์ฑ)์ ์ฐพ์ต๋๋ค. ๋ ธ์ด์ฆ๋ ๋ณธ์ง์ ์ผ๋ก ๋ฌด์์์ ์ด๊ณ ์์ธก ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ ์ด๋ฌํ ์ค๋ณต์ฑ ํจํด์ ๊นจ๋จ๋ฆฝ๋๋ค. ์ธ์ฝ๋๋ ๋ฌด์์ ๋ ธ์ด์ฆ๋ฅผ ๋ณด์กดํด์ผ ํ ๊ณ ์ฃผํ ๋ํ ์ผ๋ก ๊ฐ์ฃผํ์ฌ, ์ค์ ์ฝํ ์ธ ๋์ ๋ ธ์ด์ฆ๋ฅผ ์ธ์ฝ๋ฉํ๋ ๋ฐ ๋ ๋ง์ ๋นํธ๋ฅผ ํ ๋นํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋์ผํ ์ฒด๊ฐ ํ์ง์ ๋ํด ํ์ผ ํฌ๊ธฐ๊ฐ ์ปค์ง๊ฑฐ๋, ๋์ผํ ๋นํธ๋ ์ดํธ์์ ํ์ง์ด ๋ฎ์์ง๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณ์ต๋๋ค.
์ธ์ฝ๋ฉ ์ ์ ๋ ธ์ด์ฆ๋ฅผ ์ ๊ฑฐํจ์ผ๋ก์จ ๋น๋์ค ์ ํธ๋ฅผ ๋ ์์ธก ๊ฐ๋ฅํ๊ฒ ๋ง๋ค์ด ์ธ์ฝ๋๊ฐ ๋ ํจ์จ์ ์ผ๋ก ์๋ํ๋๋ก ํ ์ ์์ต๋๋ค. ์ด๋ ๋ ๋์ ์๊ฐ์ ํ์ง, ๋ ๋ฎ์ ๋์ญํญ ์ฌ์ฉ, ๊ทธ๋ฆฌ๊ณ ์ ์ธ๊ณ ์ฌ์ฉ์๋ค์๊ฒ ๋ ๋ถ๋๋ฌ์ด ์คํธ๋ฆฌ๋ฐ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
WebCodecs์ ๋ฑ์ฅ: ๋ก์ฐ-๋ ๋ฒจ ๋น๋์ค ์ ์ด์ ํ
์๋
๊ฐ ๋ธ๋ผ์ฐ์ ์์์ ์ง์ ์ ์ธ ๋น๋์ค ์กฐ์์ ์ ํ์ ์ด์์ต๋๋ค. ๊ฐ๋ฐ์๋ค์ ์ฃผ๋ก <video>
์์์ Canvas API์ ๊ธฐ๋ฅ์ ๊ตญํ๋์์ผ๋ฉฐ, ์ด๋ ์ข
์ข
GPU๋ก๋ถํฐ์ ์ฑ๋ฅ์ ์ ํ์ํค๋ ๋ฐ์ดํฐ ๋ฆฌ๋๋ฐฑ(readback)์ ์๋ฐํ์ต๋๋ค. WebCodecs๋ ์ด ํ๋๋ฅผ ์์ ํ ๋ฐ๊ฟ๋๋ค.
WebCodecs๋ ๋ธ๋ผ์ฐ์ ์ ๋ด์ฅ ๋ฏธ๋์ด ์ธ์ฝ๋ ๋ฐ ๋์ฝ๋์ ์ง์ ์ ๊ทผํ ์ ์๊ฒ ํด์ฃผ๋ ๋ก์ฐ-๋ ๋ฒจ API์ ๋๋ค. ์ด๋ ๋น๋์ค ํธ์ง๊ธฐ, ํด๋ผ์ฐ๋ ๊ฒ์ ํ๋ซํผ, ๊ณ ๊ธ ์ค์๊ฐ ํต์ ํด๋ผ์ด์ธํธ์ ๊ฐ์ด ๋ฏธ๋์ด ์ฒ๋ฆฌ์ ๋ํ ์ ๋ฐํ ์ ์ด๊ฐ ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํด ์ค๊ณ๋์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ง์คํ ํต์ฌ ๊ตฌ์ฑ ์์๋ VideoFrame
๊ฐ์ฒด์
๋๋ค. VideoFrame
์ ๋น๋์ค์ ๋จ์ผ ํ๋ ์์ ์ด๋ฏธ์ง๋ก ๋ํ๋ด์ง๋ง, ๋จ์ํ ๋นํธ๋งต ์ด์์
๋๋ค. ์ด๋ ๋ค์ํ ํฝ์
ํ์(์: RGBA, I420, NV12)์ผ๋ก ๋น๋์ค ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ์๊ณ ๋ค์๊ณผ ๊ฐ์ ์ค์ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋งค์ฐ ํจ์จ์ ์ด๊ณ ์ ์ก ๊ฐ๋ฅํ ๊ฐ์ฒด์
๋๋ค:
timestamp
: ๋ง์ดํฌ๋ก์ด ๋จ์์ ํ๋ ์ ํ์ ์๊ฐ.duration
: ๋ง์ดํฌ๋ก์ด ๋จ์์ ํ๋ ์ ์ง์ ์๊ฐ.codedWidth
๋ฐcodedHeight
: ํฝ์ ๋จ์์ ํ๋ ์ ํฌ๊ธฐ.format
: ๋ฐ์ดํฐ์ ํฝ์ ํ์ (์: 'I420', 'RGBA').
๊ฒฐ์ ์ ์ผ๋ก, VideoFrame
์ copyTo()
๋ผ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ ์์, ๋น์์ถ ํฝ์
๋ฐ์ดํฐ๋ฅผ ArrayBuffer
๋ก ๋ณต์ฌํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๊ฒ์ด ๋ถ์ ๋ฐ ์กฐ์์ ์ํ ์ฐ๋ฆฌ์ ์ง์
์ ์
๋๋ค. ์์ ๋ฐ์ดํธ๋ฅผ ํ๋ณดํ๋ฉด, ๋
ธ์ด์ฆ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ ๋ค์, ์์ ๋ ๋ฐ์ดํฐ๋ก๋ถํฐ ์๋ก์ด VideoFrame
์ ๊ตฌ์ฑํ์ฌ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ค์ ๋จ๊ณ(์: ๋น๋์ค ์ธ์ฝ๋๋ ์บ๋ฒ์ค)๋ก ์ ๋ฌํ ์ ์์ต๋๋ค.
์๊ฐ์ ํํฐ๋ง์ ์ดํด
๋ ธ์ด์ฆ ๊ฐ์ ๊ธฐ์ ์ ํฌ๊ฒ ๊ณต๊ฐ์ (spatial)๊ณผ ์๊ฐ์ (temporal) ๋ ๊ฐ์ง ์ ํ์ผ๋ก ๋ถ๋ฅํ ์ ์์ต๋๋ค.
- ๊ณต๊ฐ์ ํํฐ๋ง: ์ด ๊ธฐ์ ์ ๋จ์ผ ํ๋ ์์ ๋ ๋ฆฝ์ ์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค. ์ด์ ํฝ์ ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ถ์ํ์ฌ ๋ ธ์ด์ฆ๋ฅผ ์๋ณํ๊ณ ๋ถ๋๋ฝ๊ฒ ๋ง๋ญ๋๋ค. ๊ฐ๋จํ ์๋ก ๋ธ๋ฌ ํํฐ๊ฐ ์์ต๋๋ค. ๋ ธ์ด์ฆ ๊ฐ์์ ํจ๊ณผ์ ์ด์ง๋ง, ๊ณต๊ฐ ํํฐ๋ ์ค์ํ ๋ํ ์ผ๊ณผ ๊ฐ์ฅ์๋ฆฌ๋ฅผ ๋ถ๋๋ฝ๊ฒ ๋ง๋ค์ด ์ด๋ฏธ์ง๋ฅผ ๋ ์ ๋ช ํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
- ์๊ฐ์ ํํฐ๋ง: ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ์ง์คํ๋ ๋ ์ ๊ตํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค. ์๊ฐ์ ๋ฐ๋ผ ์ฌ๋ฌ ํ๋ ์์ ๊ฑธ์ณ ์๋ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ธ ์๋ฆฌ๋ ์ค์ ์ฅ๋ฉด ์ฝํ ์ธ ๋ ํ๋ ์๋ง๋ค ์๊ด๊ด๊ณ๊ฐ ์์ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ฐ๋ฉด, ๋ ธ์ด์ฆ๋ ๋ฌด์์์ ์ด๊ณ ์๊ด๊ด๊ณ๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ฌ๋ฌ ํ๋ ์์ ๊ฑธ์ณ ํน์ ์์น์ ํฝ์ ๊ฐ์ ๋น๊ตํจ์ผ๋ก์จ, ์ผ๊ด๋ ์ ํธ(์ค์ ์ด๋ฏธ์ง)์ ๋ฌด์์์ ์ธ ๋ณ๋(๋ ธ์ด์ฆ)์ ๊ตฌ๋ณํ ์ ์์ต๋๋ค.
๊ฐ์ฅ ๊ฐ๋จํ ํํ์ ์๊ฐ์ ํํฐ๋ง์ ์๊ฐ์ ํ๊ท ํ์ ๋๋ค. ํ์ฌ ํ๋ ์๊ณผ ์ด์ ํ๋ ์์ด ์๋ค๊ณ ์์ํด ๋ณด์ธ์. ์ด๋ค ํฝ์ ์ด๋ ๊ทธ '์ค์ ' ๊ฐ์ ํ์ฌ ํ๋ ์์ ๊ฐ๊ณผ ์ด์ ํ๋ ์์ ๊ฐ ์ฌ์ด ์ด๋๊ฐ์ ์์ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ์ด๋ค์ ํผํฉํจ์ผ๋ก์จ ๋ฌด์์ ๋ ธ์ด์ฆ๋ฅผ ํ๊ท ํํ ์ ์์ต๋๋ค. ์๋ก์ด ํฝ์ ๊ฐ์ ๊ฐ๋จํ ๊ฐ์ค ํ๊ท ์ผ๋ก ๊ณ์ฐํ ์ ์์ต๋๋ค:
new_pixel = (alpha * current_pixel) + ((1 - alpha) * previous_pixel)
์ฌ๊ธฐ์ alpha
๋ 0๊ณผ 1 ์ฌ์ด์ ํผํฉ ๊ณ์์
๋๋ค. alpha
๊ฐ ๋์์๋ก ํ์ฌ ํ๋ ์์ ๋ ์ ๋ขฐํ๋ค๋ ์๋ฏธ์ด๋ฉฐ, ๋
ธ์ด์ฆ ๊ฐ์๋ ๋ํ์ง๋ง ์์ง์ ์ธ๊ณต๋ฌผ(motion artifact)์ด ์ค์ด๋ญ๋๋ค. alpha
๊ฐ ๋ฎ์์๋ก ๋ ๊ฐ๋ ฅํ ๋
ธ์ด์ฆ ๊ฐ์๋ฅผ ์ ๊ณตํ์ง๋ง ์์ง์์ด ์๋ ์์ญ์์ '๊ณ ์คํ
(ghosting)'์ด๋ ์์์ ์ ๋ฐํ ์ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๊ท ํ์ ์ฐพ๋ ๊ฒ์ด ํต์ฌ์
๋๋ค.
๊ฐ๋จํ ์๊ฐ์ ํ๊ท ํ ํํฐ ๊ตฌํํ๊ธฐ
WebCodecs๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๊ฐ๋ ์ ์ค์ ๊ตฌํ์ ๋ง๋ค์ด ๋ด ์๋ค. ์ฐ๋ฆฌ์ ํ์ดํ๋ผ์ธ์ ์ธ ๊ฐ์ง ์ฃผ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
VideoFrame
๊ฐ์ฒด์ ์คํธ๋ฆผ์ ๊ฐ์ ธ์ต๋๋ค (์: ์น์บ ์์).- ๊ฐ ํ๋ ์์ ๋ํด ์ด์ ํ๋ ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์๊ฐ์ ํํฐ๋ฅผ ์ ์ฉํฉ๋๋ค.
- ์๋กญ๊ณ ๊นจ๋ํด์ง
VideoFrame
์ ์์ฑํฉ๋๋ค.
1๋จ๊ณ: ํ๋ ์ ์คํธ๋ฆผ ์ค์ ํ๊ธฐ
๋ผ์ด๋ธ VideoFrame
๊ฐ์ฒด ์คํธ๋ฆผ์ ์ป๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ MediaStreamTrackProcessor
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ์ด๋ MediaStreamTrack
(์: getUserMedia
์์ ์ป์ ๊ฒ)์ ์๋นํ๊ณ ๊ทธ ํ๋ ์๋ค์ ์ฝ์ ์ ์๋ ์คํธ๋ฆผ(readable stream)์ผ๋ก ๋
ธ์ถํฉ๋๋ค.
๊ฐ๋ ์ ์ธ JavaScript ์ค์ :
async function setupVideoStream() {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const track = stream.getVideoTracks()[0];
const trackProcessor = new MediaStreamTrackProcessor({ track });
const reader = trackProcessor.readable.getReader();
let previousFrameBuffer = null;
let previousFrameTimestamp = -1;
while (true) {
const { value: frame, done } = await reader.read();
if (done) break;
// ์ฌ๊ธฐ์ ๊ฐ 'frame'์ ์ฒ๋ฆฌํ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
const processedFrame = await applyTemporalFilter(frame, previousFrameBuffer);
// ๋ค์ ๋ฐ๋ณต์ ์ํด *์๋ณธ* ํ์ฌ ํ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด์ผ ํฉ๋๋ค.
// ์๋ณธ ํ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ซ๊ธฐ ์ ์ 'previousFrameBuffer'์ ๋ณต์ฌํฉ๋๋ค.
// ๋ฉ๋ชจ๋ฆฌ ํด์ ๋ฅผ ์ํด ํ๋ ์์ ์์ง ๋ง๊ณ ๋ซ์ผ์ธ์!
frame.close();
// processedFrame์ผ๋ก ๋ฌด์ธ๊ฐ๋ฅผ ํฉ๋๋ค (์: ์บ๋ฒ์ค์ ๋ ๋๋ง, ์ธ์ฝ๋ฉ).
// ... ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ ๋ซ์ผ์ธ์!
processedFrame.close();
}
}
2๋จ๊ณ: ํํฐ๋ง ์๊ณ ๋ฆฌ์ฆ - ํฝ์ ๋ฐ์ดํฐ ์์
์ด๊ฒ์ด ์ฐ๋ฆฌ ์์
์ ํต์ฌ์
๋๋ค. applyTemporalFilter
ํจ์ ๋ด๋ถ์์ ๋ค์ด์ค๋ ํ๋ ์์ ํฝ์
๋ฐ์ดํฐ์ ์ ๊ทผํด์ผ ํฉ๋๋ค. ๊ฐ๋จํ ํ๊ธฐ ์ํด, ํ๋ ์์ด 'RGBA' ํ์์ด๋ผ๊ณ ๊ฐ์ ํฉ์๋ค. ๊ฐ ํฝ์
์ ๋นจ๊ฐ, ์ด๋ก, ํ๋, ๊ทธ๋ฆฌ๊ณ ์ํ(ํฌ๋ช
๋)์ 4๋ฐ์ดํธ๋ก ํํ๋ฉ๋๋ค.
async function applyTemporalFilter(currentFrame, previousFrameBuffer) {
// ํผํฉ ๊ณ์๋ฅผ ์ ์ํฉ๋๋ค. 0.8์ ์ ํ๋ ์ 80%์ ์ด์ ํ๋ ์ 20%๋ฅผ ์๋ฏธํฉ๋๋ค.
const alpha = 0.8;
// ํ๋ ์ ํฌ๊ธฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
const width = currentFrame.codedWidth;
const height = currentFrame.codedHeight;
// ํ์ฌ ํ๋ ์์ ํฝ์
๋ฐ์ดํฐ๋ฅผ ๋ด์ ArrayBuffer๋ฅผ ํ ๋นํฉ๋๋ค.
const currentFrameSize = width * height * 4; // RGBA๋ ํฝ์
๋น 4๋ฐ์ดํธ์
๋๋ค.
const currentFrameBuffer = new Uint8Array(currentFrameSize);
await currentFrame.copyTo(currentFrameBuffer);
// ์ด๊ฒ์ด ์ฒซ ํ๋ ์์ด๋ผ๋ฉด ํผํฉํ ์ด์ ํ๋ ์์ด ์์ต๋๋ค.
// ๊ทธ๋๋ก ๋ฐํํ๋, ๋ค์ ๋ฐ๋ณต์ ์ํด ๋ฒํผ๋ฅผ ์ ์ฅํฉ๋๋ค.
if (!previousFrameBuffer) {
const newFrameBuffer = new Uint8Array(currentFrameBuffer);
// ์ด ํจ์ ๋ฐ์์ ์ ์ญ 'previousFrameBuffer'๋ฅผ ์ด ๋ฒํผ๋ก ์
๋ฐ์ดํธํ ๊ฒ์
๋๋ค.
return { buffer: newFrameBuffer, frame: currentFrame };
}
// ์ถ๋ ฅ ํ๋ ์์ ์ํ ์ ๋ฒํผ๋ฅผ ์์ฑํฉ๋๋ค.
const outputFrameBuffer = new Uint8Array(currentFrameSize);
// ์ฃผ ์ฒ๋ฆฌ ๋ฃจํ์
๋๋ค.
for (let i = 0; i < currentFrameSize; i++) {
const currentPixelValue = currentFrameBuffer[i];
const previousPixelValue = previousFrameBuffer[i];
// ๊ฐ ์์ ์ฑ๋์ ์๊ฐ์ ํ๊ท ํ ๊ณต์์ ์ ์ฉํฉ๋๋ค.
// ์ํ ์ฑ๋์ ๊ฑด๋๋๋๋ค (๋งค 4๋ฒ์งธ ๋ฐ์ดํธ).
if ((i + 1) % 4 !== 0) {
outputFrameBuffer[i] = Math.round(alpha * currentPixelValue + (1 - alpha) * previousPixelValue);
} else {
// ์ํ ์ฑ๋์ ๊ทธ๋๋ก ์ ์งํฉ๋๋ค.
outputFrameBuffer[i] = currentPixelValue;
}
}
return { buffer: outputFrameBuffer, frame: currentFrame };
}
YUV ํ์(I420, NV12)์ ๋ํ ์ฐธ๊ณ : RGBA๋ ์ดํดํ๊ธฐ ์ฝ์ง๋ง, ๋๋ถ๋ถ์ ๋น๋์ค๋ ํจ์จ์ฑ์ ์ํด ๊ธฐ๋ณธ์ ์ผ๋ก YUV ์ ๊ณต๊ฐ์์ ์ฒ๋ฆฌ๋ฉ๋๋ค. YUV๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ ์์(U, V)๊ณผ ๋ฐ๊ธฐ(Y) ์ ๋ณด๊ฐ ๋ณ๋๋ก('ํ๋ฉด'์ผ๋ก) ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ ๋ ๋ณต์กํฉ๋๋ค. ํํฐ๋ง ๋ก์ง์ ๋์ผํ๊ฒ ์ ์ง๋์ง๋ง, ๊ฐ ํ๋ฉด(Y, U, V)์ ๊ฐ๋ณ์ ์ผ๋ก ๋ฐ๋ณตํด์ผ ํ๋ฉฐ, ๊ฐ๊ฐ์ ํฌ๊ธฐ(์์ ํ๋ฉด์ ์ข ์ข ๋ ๋ฎ์ ํด์๋์ธ๋ฐ, ์ด๋ฅผ ํฌ๋ก๋ง ์๋ธ์ํ๋ง์ด๋ผ๊ณ ํจ)์ ์ ์ํด์ผ ํฉ๋๋ค.
3๋จ๊ณ: ์๋ก์ด ํํฐ๋ง๋ `VideoFrame` ์์ฑํ๊ธฐ
๋ฃจํ๊ฐ ๋๋๋ฉด, outputFrameBuffer
์๋ ์๋กญ๊ณ ๊นจ๋ํด์ง ํ๋ ์์ ํฝ์
๋ฐ์ดํฐ๊ฐ ๋ด๊ฒจ ์์ต๋๋ค. ์ด์ ์ด ๋ฐ์ดํฐ๋ฅผ ์๋ณธ ํ๋ ์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ์ฌ ์๋ก์ด VideoFrame
๊ฐ์ฒด๋ก ๊ฐ์ธ์ผ ํฉ๋๋ค.
// applyTemporalFilter ํธ์ถ ํ ๋ฉ์ธ ๋ฃจํ ๋ด๋ถ...
const { buffer: processedBuffer, frame: originalFrame } = await applyTemporalFilter(frame, previousFrameBuffer);
// ์ฒ๋ฆฌ๋ ๋ฒํผ๋ก๋ถํฐ ์๋ก์ด VideoFrame์ ์์ฑํฉ๋๋ค.
const newFrame = new VideoFrame(processedBuffer, {
format: 'RGBA',
codedWidth: originalFrame.codedWidth,
codedHeight: originalFrame.codedHeight,
timestamp: originalFrame.timestamp,
duration: originalFrame.duration
});
// ์ค์: ๋ค์ ๋ฐ๋ณต์ ์ํด ์ด์ ํ๋ ์ ๋ฒํผ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
// ํํฐ๋ง๋ ๋ฐ์ดํฐ๊ฐ ์๋ *์๋ณธ* ํ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํด์ผ ํฉ๋๋ค.
// ํํฐ๋ง ์ ์ ๋ณ๋์ ๋ณต์ฌ๋ณธ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
previousFrameBuffer = new Uint8Array(originalFrameData);
// ์ด์ 'newFrame'์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ ๋๋งํ๊ฑฐ๋, ์ธ์ฝ๋ฉํ๋ ๋ฑ์ ์์
์ ํ์ธ์.
// renderer.draw(newFrame);
// ๊ทธ๋ฆฌ๊ณ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์์
์ด ๋๋๋ฉด ๋ฐ๋์ ๋ซ์์ผ ํฉ๋๋ค.
newFrame.close();
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ๋งค์ฐ ์ค์ํฉ๋๋ค: VideoFrame
๊ฐ์ฒด๋ ๋๋์ ๋น์์ถ ๋น๋์ค ๋ฐ์ดํฐ๋ฅผ ๋ณด์ ํ ์ ์์ผ๋ฉฐ JavaScript ํ ์ธ๋ถ์ ๋ฉ๋ชจ๋ฆฌ์ ์ํด ์ง์๋ ์ ์์ต๋๋ค. ์ฌ์ฉ์ด ๋๋ ๋ชจ๋ ํ๋ ์์ ๋ํด ๋ฐ๋์ frame.close()
๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๊ณ ๊ฐ๊ณผ ํญ ์ถฉ๋์ด ๋น ๋ฅด๊ฒ ๋ฐ์ํ ๊ฒ์
๋๋ค.
์ฑ๋ฅ ๊ณ ๋ ค์ฌํญ: JavaScript ๋ WebAssembly
์์ ์์ JavaScript ๊ตฌํ์ ํ์ต ๋ฐ ์์ฐ์ฉ์ผ๋ก ํ๋ฅญํฉ๋๋ค. ํ์ง๋ง 30 FPS, 1080p(1920x1080) ๋น๋์ค์ ๊ฒฝ์ฐ, ์ฐ๋ฆฌ ๋ฃจํ๋ ์ด๋น 2์ต 4,800๋ง ๊ฐ ์ด์์ ๊ณ์ฐ์ ์ํํด์ผ ํฉ๋๋ค! (1920 * 1080 * 4 ๋ฐ์ดํธ * 30 fps). ์ต์ JavaScript ์์ง์ ๋ฏฟ์ ์ ์์ ์ ๋๋ก ๋น ๋ฅด์ง๋ง, ์ด๋ฌํ ํฝ์ ๋จ์ ์ฒ๋ฆฌ๋ ๋ ์ฑ๋ฅ ์งํฅ์ ์ธ ๊ธฐ์ ์ธ WebAssembly(Wasm)์ ์๋ฒฝํ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค.
WebAssembly ์ ๊ทผ ๋ฐฉ์
WebAssembly๋ฅผ ์ฌ์ฉํ๋ฉด C++, Rust, Go์ ๊ฐ์ ์ธ์ด๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ๋ค์ดํฐ๋ธ์ ๊ฐ๊น์ด ์๋๋ก ์คํํ ์ ์์ต๋๋ค. ์๊ฐ์ ํํฐ์ ๋ก์ง์ ์ด๋ฌํ ์ธ์ด์์ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. ์ ๋ ฅ ๋ฐ ์ถ๋ ฅ ๋ฒํผ์ ๋ํ ํฌ์ธํฐ๋ฅผ ๋ฐ์ ๋์ผํ ๋ฐ๋ณต์ ํผํฉ ์ฐ์ฐ์ ์ํํ๋ ํจ์๋ฅผ ์์ฑํ๋ฉด ๋ฉ๋๋ค.
Wasm์ ์ํ ๊ฐ๋ ์ ์ธ C++ ํจ์:
extern "C" {
void apply_temporal_filter(unsigned char* current_frame, unsigned char* previous_frame, unsigned char* output_frame, int buffer_size, float alpha) {
for (int i = 0; i < buffer_size; ++i) {
if ((i + 1) % 4 != 0) { // ์ํ ์ฑ๋ ๊ฑด๋๋ฐ๊ธฐ
output_frame[i] = (unsigned char)(alpha * current_frame[i] + (1.0 - alpha) * previous_frame[i]);
} else {
output_frame[i] = current_frame[i];
}
}
}
}
JavaScript ์ธก์์๋ ์ด ์ปดํ์ผ๋ Wasm ๋ชจ๋์ ๋ก๋ํฉ๋๋ค. ํต์ฌ์ ์ธ ์ฑ๋ฅ ์ด์ ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต์ ์์ ๋น๋กฏ๋ฉ๋๋ค. Wasm ๋ชจ๋์ ์ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ํด ์ง์๋๋ ArrayBuffer
๋ฅผ JavaScript์์ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋น์ผ ๋ณต์ฌ ๊ณผ์ ์์ด ํ๋ ์ ๋ฐ์ดํฐ๋ฅผ Wasm์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ์ ์ฒด ํฝ์
์ฒ๋ฆฌ ๋ฃจํ๋ ๋จ์ผ์ ๊ณ ๋๋ก ์ต์ ํ๋ Wasm ํจ์ ํธ์ถ๋ก ์คํ๋๋ฉฐ, ์ด๋ JavaScript์ `for` ๋ฃจํ๋ณด๋ค ํจ์ฌ ๋น ๋ฆ
๋๋ค.
๊ณ ๊ธ ์๊ฐ์ ํํฐ๋ง ๊ธฐ๋ฒ
๊ฐ๋จํ ์๊ฐ์ ํ๊ท ํ๋ ํ๋ฅญํ ์ถ๋ฐ์ ์ด์ง๋ง, ์์ง์ ๋ธ๋ฌ(motion blur)๋ '๊ณ ์คํ '์ ์ ๋ฐํ๋ค๋ ์๋นํ ๋จ์ ์ด ์์ต๋๋ค. ๊ฐ์ฒด๊ฐ ์์ง์ผ ๋, ํ์ฌ ํ๋ ์์ ํฝ์ ์ด ์ด์ ํ๋ ์์ ๋ฐฐ๊ฒฝ ํฝ์ ๊ณผ ํผํฉ๋์ด ์์์ ๋ง๋ญ๋๋ค. ์ง์ ์ผ๋ก ์ ๋ฌธ๊ฐ ์์ค์ ํํฐ๋ฅผ ๊ตฌ์ถํ๋ ค๋ฉด ์์ง์์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์์ง์ ๋ณด์ ์๊ฐ์ ํํฐ๋ง (MCTF)
์๊ฐ์ ๋ ธ์ด์ฆ ๊ฐ์์ ํฉ๊ธ ํ์ค์ ์์ง์ ๋ณด์ ์๊ฐ์ ํํฐ๋ง์ ๋๋ค. ํฝ์ ์ ์ด์ ํ๋ ์์ ๋์ผํ (x, y) ์ขํ์ ์๋ ํฝ์ ๊ณผ ๋งน๋ชฉ์ ์ผ๋ก ํผํฉํ๋ ๋์ , MCTF๋ ๋จผ์ ๊ทธ ํฝ์ ์ด ์ด๋์ ์๋์ง ์์๋ด๋ ค๊ณ ์๋ํฉ๋๋ค.
์ด ๊ณผ์ ์ ๋ค์์ ํฌํจํฉ๋๋ค:
- ์์ง์ ์์ธก: ์๊ณ ๋ฆฌ์ฆ์ ํ์ฌ ํ๋ ์์ ๋ธ๋ก(์: 16x16 ํฝ์ )์ผ๋ก ๋๋๋๋ค. ๊ฐ ๋ธ๋ก์ ๋ํด ์ด์ ํ๋ ์์์ ๊ฐ์ฅ ์ ์ฌํ ๋ธ๋ก(์: ์ ๋์ฐจ์ ํฉ์ด ๊ฐ์ฅ ๋ฎ์ ๋ธ๋ก)์ ๊ฒ์ํฉ๋๋ค. ์ด ๋ ๋ธ๋ก ๊ฐ์ ๋ณ์๋ฅผ '๋ชจ์ ๋ฒกํฐ'๋ผ๊ณ ํฉ๋๋ค.
- ์์ง์ ๋ณด์: ๊ทธ๋ฐ ๋ค์ ๋ชจ์ ๋ฒกํฐ์ ๋ฐ๋ผ ๋ธ๋ก์ ์ด๋์์ผ ์ด์ ํ๋ ์์ '์์ง์ ๋ณด์' ๋ฒ์ ์ ๋ง๋ญ๋๋ค.
- ํํฐ๋ง: ๋ง์ง๋ง์ผ๋ก, ํ์ฌ ํ๋ ์๊ณผ ์ด ์๋ก์ด ์์ง์ ๋ณด์๋ ์ด์ ํ๋ ์ ์ฌ์ด์์ ์๊ฐ์ ํ๊ท ํ๋ฅผ ์ํํฉ๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ผ๋ก, ์์ง์ด๋ ๊ฐ์ฒด๋ ๋ฐฉ๊ธ ๋๋ฌ๋ ๋ฐฐ๊ฒฝ์ด ์๋ ์ด์ ํ๋ ์์ ์๊ธฐ ์์ ๊ณผ ํผํฉ๋ฉ๋๋ค. ์ด๋ ๊ณ ์คํ ์ธ๊ณต๋ฌผ์ ๊ทน์ ์ผ๋ก ์ค์ฌ์ค๋๋ค. ์์ง์ ์์ธก์ ๊ตฌํํ๋ ๊ฒ์ ๊ณ์ฐ ์ง์ฝ์ ์ด๊ณ ๋ณต์กํ๋ฉฐ, ์ข ์ข ๊ณ ๊ธ ์๊ณ ๋ฆฌ์ฆ์ ํ์๋ก ํ๊ณ , ๊ฑฐ์ ์ ์ ์ผ๋ก WebAssembly๋ ์ฌ์ง์ด WebGPU ์ปดํจํธ ์ ฐ์ด๋์ ์์ญ์ ๋๋ค.
์ ์ํ ํํฐ๋ง
๋ ๋ค๋ฅธ ๊ฐ์ ์ ์ ํํฐ๋ฅผ ์ ์ํ์ผ๋ก ๋ง๋๋ ๊ฒ์
๋๋ค. ์ ์ฒด ํ๋ ์์ ๊ณ ์ ๋ alpha
๊ฐ์ ์ฌ์ฉํ๋ ๋์ , ์ง์ญ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ์์ง์ ์ ์์ฑ: ์์ง์์ด ๋ง์ด ๊ฐ์ง๋๋ ์์ญ์์๋
alpha
๋ฅผ ๋์ฌ(์: 0.95 ๋๋ 1.0) ๊ฑฐ์ ์ ์ ์ผ๋ก ํ์ฌ ํ๋ ์์ ์์กดํ๊ฒ ํจ์ผ๋ก์จ ์์ง์ ๋ธ๋ฌ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ์ ์ ์ธ ์์ญ(์: ๋ฐฐ๊ฒฝ์ ๋ฒฝ)์์๋alpha
๋ฅผ ๋ฎ์ถฐ(์: 0.5) ํจ์ฌ ๊ฐ๋ ฅํ ๋ ธ์ด์ฆ ๊ฐ์๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค. - ํ๋ ์ ์์ฑ: ๋ ธ์ด์ฆ๋ ์ข ์ข ์ด๋ฏธ์ง์ ์ด๋์ด ์์ญ์์ ๋ ์ ๋ณด์ ๋๋ค. ํํฐ๋ฅผ ๊ทธ๋ฆผ์ ์์ญ์์๋ ๋ ๊ณต๊ฒฉ์ ์ผ๋ก, ๋ฐ์ ์์ญ์์๋ ๋ ๊ณต๊ฒฉ์ ์ผ๋ก ๋ง๋ค์ด ๋ํ ์ผ์ ๋ณด์กดํ ์ ์์ต๋๋ค.
์ค์ฉ์ ์ธ ์ฌ์ฉ ์ฌ๋ก ๋ฐ ์์ฉ ๋ถ์ผ
๋ธ๋ผ์ฐ์ ์์ ๊ณ ํ์ง ๋ ธ์ด์ฆ ๊ฐ์๋ฅผ ์ํํ ์ ์๋ ๋ฅ๋ ฅ์ ์๋ง์ ๊ฐ๋ฅ์ฑ์ ์ด์ด์ค๋๋ค:
- ์ค์๊ฐ ํต์ (WebRTC): ์ฌ์ฉ์์ ์น์บ ํผ๋๋ฅผ ๋น๋์ค ์ธ์ฝ๋๋ก ๋ณด๋ด๊ธฐ ์ ์ ์ ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ ์ ์กฐ๋ ํ๊ฒฝ์์์ ํ์ ํตํ์ ํฐ ์ด์ ์ ์ ๊ณตํ๋ฉฐ, ์๊ฐ์ ํ์ง์ ๊ฐ์ ํ๊ณ ํ์ํ ๋์ญํญ์ ์ค์ ๋๋ค.
- ์น ๊ธฐ๋ฐ ๋น๋์ค ํธ์ง: ์ธ-๋ธ๋ผ์ฐ์ ๋น๋์ค ํธ์ง๊ธฐ์์ '๋ ธ์ด์ฆ ์ ๊ฑฐ' ํํฐ๋ฅผ ๊ธฐ๋ฅ์ผ๋ก ์ ๊ณตํ์ฌ ์ฌ์ฉ์๊ฐ ์๋ฒ ์ธก ์ฒ๋ฆฌ ์์ด ์ ๋ก๋๋ ์์์ ์ ๋ฆฌํ ์ ์๊ฒ ํฉ๋๋ค.
- ํด๋ผ์ฐ๋ ๊ฒ์ด๋ฐ ๋ฐ ์๊ฒฉ ๋ฐ์คํฌํฑ: ๋ค์ด์ค๋ ๋น๋์ค ์คํธ๋ฆผ์ ์ ๋ฆฌํ์ฌ ์์ถ ์ธ๊ณต๋ฌผ์ ์ค์ด๊ณ ๋ ์ ๋ช ํ๊ณ ์์ ์ ์ธ ํ๋ฉด์ ์ ๊ณตํฉ๋๋ค.
- ์ปดํจํฐ ๋น์ ์ ์ฒ๋ฆฌ: ์น ๊ธฐ๋ฐ AI/ML ์ ํ๋ฆฌ์ผ์ด์ (์: ๊ฐ์ฒด ์ถ์ ๋๋ ์ผ๊ตด ์ธ์)์ ๊ฒฝ์ฐ, ์ ๋ ฅ ๋น๋์ค์ ๋ ธ์ด์ฆ๋ฅผ ์ ๊ฑฐํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์์ ํ๋์ด ๋ ์ ํํ๊ณ ์ ๋ขฐํ ์ ์๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
๊ณผ์ ๋ฐ ๋ฏธ๋ ๋ฐฉํฅ
๊ฐ๋ ฅํ์ง๋ง, ์ด ์ ๊ทผ ๋ฐฉ์์๋ ๊ณผ์ ๊ฐ ์๋ ๊ฒ์ ์๋๋๋ค. ๊ฐ๋ฐ์๋ ๋ค์ ์ฌํญ์ ์ ์ํด์ผ ํฉ๋๋ค:
- ์ฑ๋ฅ: HD ๋๋ 4K ๋น๋์ค์ ์ค์๊ฐ ์ฒ๋ฆฌ๋ ๊น๋ค๋กญ์ต๋๋ค. ํจ์จ์ ์ธ ๊ตฌํ, ํนํ WebAssembly๋ฅผ ์ฌ์ฉํ ๊ตฌํ์ด ํ์์ ์ ๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ: ํ๋ ์ด์์ ์ด์ ํ๋ ์์ ๋น์์ถ ๋ฒํผ๋ก ์ ์ฅํ๋ ๊ฒ์ ์๋นํ ์์ RAM์ ์๋นํฉ๋๋ค. ์ ์คํ ๊ด๋ฆฌ๊ฐ ํ์์ ์ ๋๋ค.
- ์ง์ฐ ์๊ฐ: ๋ชจ๋ ์ฒ๋ฆฌ ๋จ๊ณ๋ ์ง์ฐ ์๊ฐ์ ์ถ๊ฐํฉ๋๋ค. ์ค์๊ฐ ํต์ ์ ์ํด ์ด ํ์ดํ๋ผ์ธ์ ๋์ ๋๋ ์ง์ฐ์ ํผํ๊ธฐ ์ํด ๊ณ ๋๋ก ์ต์ ํ๋์ด์ผ ํฉ๋๋ค.
- WebGPU์ ๋ฏธ๋: ์๋กญ๊ฒ ๋ฑ์ฅํ๋ WebGPU API๋ ์ด๋ฌํ ์ข ๋ฅ์ ์์ ์ ์ํ ์๋ก์ด ์งํ์ ์ด ๊ฒ์ ๋๋ค. ์ด๋ ์ด๋ฌํ ํฝ์ ๋จ์ ์๊ณ ๋ฆฌ์ฆ์ ์์คํ ์ GPU์์ ๊ณ ๋๋ก ๋ณ๋ ฌํ๋ ์ปดํจํธ ์ ฐ์ด๋๋ก ์คํํ ์ ์๊ฒ ํ์ฌ, CPU์์์ WebAssembly๋ณด๋ค ํจ์ฌ ๋ ํฐ ์ฑ๋ฅ ํฅ์์ ์ ๊ณตํ ๊ฒ์ ๋๋ค.
๊ฒฐ๋ก
WebCodecs API๋ ์น์์์ ๊ณ ๊ธ ๋ฏธ๋์ด ์ฒ๋ฆฌ๋ฅผ ์ํ ์๋ก์ด ์๋๋ฅผ ์ด์์ต๋๋ค. ์ด๋ ์ ํต์ ์ธ ๋ธ๋๋ฐ์ค <video>
์์์ ์ฅ๋ฒฝ์ ํ๋ฌผ๊ณ ๊ฐ๋ฐ์์๊ฒ ์ง์ ์ผ๋ก ์ ๋ฌธ์ ์ธ ๋น๋์ค ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๋ ๋ฐ ํ์ํ ์ธ๋ฐํ ์ ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์๊ฐ์ ๋
ธ์ด์ฆ ๊ฐ์๋ ๊ทธ ํ์ ๋ณด์ฌ์ฃผ๋ ์๋ฒฝํ ์์
๋๋ค: ์ฌ์ฉ์ ์ฒด๊ฐ ํ์ง๊ณผ ๊ทผ๋ณธ์ ์ธ ๊ธฐ์ ํจ์จ์ฑ์ ๋ชจ๋ ์ง์ ์ ์ผ๋ก ๋ค๋ฃจ๋ ์ ๊ตํ ๊ธฐ์ ์
๋๋ค.
๊ฐ๋ณ VideoFrame
๊ฐ์ฒด๋ฅผ ๊ฐ๋ก์ฑ์ผ๋ก์จ ๋
ธ์ด์ฆ๋ฅผ ์ค์ด๊ณ , ์์ถ๋ฅ ์ ํฅ์์ํค๋ฉฐ, ์ฐ์ํ ๋น๋์ค ๊ฒฝํ์ ์ ๊ณตํ๋ ๊ฐ๋ ฅํ ํํฐ๋ง ๋ก์ง์ ๊ตฌํํ ์ ์์์ ๋ณด์์ต๋๋ค. ๊ฐ๋จํ JavaScript ๊ตฌํ์ด ํ๋ฅญํ ์ถ๋ฐ์ ์ด์ง๋ง, ์์ฉ ์์ค์ ์ค์๊ฐ ์๋ฃจ์
์ผ๋ก ๊ฐ๋ ๊ธธ์ WebAssembly์ ์ฑ๋ฅ์ ๊ฑฐ์ณ, ๋ฏธ๋์๋ WebGPU์ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๋ฅ๋ ฅ์ผ๋ก ์ด์ด์ง๋๋ค.
๋ค์์ ์น ์ฑ์์ ๊ฑฐ์น ๋น๋์ค๋ฅผ ๋ณด๊ฒ ๋๋ค๋ฉด, ๊ทธ๊ฒ์ ํด๊ฒฐํ ๋๊ตฌ๊ฐ ์ด์ ์ฒ์์ผ๋ก ์น ๊ฐ๋ฐ์๋ค์ ์์ ์ง์ ์ฅ์ด์ ธ ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์. ์น์์ ๋น๋์ค๋ก ๋ฌด์ธ๊ฐ๋ฅผ ๊ตฌ์ถํ๊ธฐ์ ์ ๋ง ํฅ๋ฏธ๋ก์ด ์๊ธฐ์ ๋๋ค.