WebM 컨테이너 웹 표준 | VP9·AV1·Opus·HTML5·FFmpeg 입문

이 글의 핵심

WebM은 로열티 없는 웹 표준 포맷이지만 브라우저별 지원 범위와 인코딩 속도 문제 때문에 MP4 폴백을 함께 두는 경우가 많습니다. MKV와의 구조적 관계, 코덱별 파일 크기와 호환성 비교, 웹 강의·게임 트레일러·WebRTC 같은 사례를 통해 언제 WebM을 기본으로 쓸지 판단하도록 돕습니다.

들어가며

WebM은 웹 배포를 염두에 둔 미디어 컨테이너입니다. Matroska의 구조를 그대로 따르되 쓸 수 있는 코덱과 요소를 제한한 프로파일이라고 보면 됩니다. VP8·VP9·AV1처럼 로열티 없이 쓰도록 공개된 비디오 코덱과 Opus·Vorbis 오디오를 묶어 담기 때문에, HTML5 <video>와 MSE(Media Source Extensions)에서 라이선스 부담을 줄이려는 선택지로 자주 등장합니다.

WebM이 코덱을 좁힌 이유는 브라우저가 “이 파일을 재생할 수 있는가”를 확장자와 MIME 타입만으로 판단할 수 있게 하기 위해서입니다. MKV는 어떤 코덱이든 담을 수 있어서, 파일을 열어 보기 전에는 재생 가능 여부를 알 수 없습니다. WebM은 허용 코덱을 몇 가지로 고정했기 때문에 video/webm; codecs="vp9, opus"처럼 MIME 타입과 코덱 문자열만으로 브라우저가 미리 지원 여부를 답할 수 있습니다(MediaSource.isTypeSupported, canPlayType). 반대로 말하면 WebM의 제약은 결함이 아니라 설계 목표이고, H.264나 AAC를 담고 싶다면 WebM이 아니라 MP4나 MKV를 쓰는 것이 맞습니다.


컨테이너 개요

역사 및 개발 배경

WebM은 2010년 구글이 On2를 인수해 얻은 VP8 코덱을 공개하면서 함께 발표한 포맷입니다. 이후 VP9와 AV1이 같은 컨테이너에 담기면서 웹용 비디오 포맷으로 자리 잡았습니다.

주요 마일스톤은 다음과 같습니다.

  • 2010: WebM 프로젝트 발표 (Google)
  • 2010: VP8 + Vorbis 조합 공개
  • 2013: VP9 출시
  • 2018: AV1 1.0 릴리스 (AOMedia)
  • 2021: macOS Safari 14.1에서 WebM(VP8·VP9) 재생 지원 시작(초기에는 부분 지원)

기술적 특징

항목설명
기반Matroska (EBML) 부분집합
허용 비디오VP8, VP9, AV1
허용 오디오Vorbis, Opus
자막WebVTT (외부 권장)
라이선스BSD 유사 (로열티 프리)
스트리밍MSE, DASH 일부 지원

WebM vs MKV

특징WebMMKV
코덱 제한VP8/VP9/AV1 + Opus/Vorbis거의 모든 코덱
용도웹 배포범용 아카이브
복잡도단순복잡 (다중 트랙, 챕터)
브라우저 지원높음낮음

내부 구조

EBML·Matroska 관계

WebM은 Matroska의 부분집합이라 Segment → Cluster → SimpleBlock으로 이어지는 구조가 MKV와 같습니다. 차이는 트랙에 담을 수 있는 코덱이 비디오는 VP8·VP9·AV1, 오디오는 Vorbis·Opus로 고정되어 있다는 점과, Matroska의 일부 요소(첨부 파일 등)를 쓰지 않는다는 점입니다.

구조 다이어그램

WebM 파일
├─ EBML Header
├─ Segment
│  ├─ SeekHead (인덱스)
│  ├─ Info (메타데이터)
│  ├─ Tracks
│  │  ├─ Video Track (VP8/VP9/AV1)
│  │  └─ Audio Track (Opus/Vorbis)
│  ├─ Cluster 1 (타임스탬프 0-2s)
│  ├─ Cluster 2 (타임스탬프 2-4s)
│  └─ Cues (시크 인덱스)

메타데이터

지원 태그:

  • TITLE: 제목

  • LANGUAGE: 언어 코드

  • DATE_RELEASED: 출시일 제한사항:

  • MP4보다 메타데이터 지원 제한적

  • 커버 아트는 별도 처리 권장


실전 사용

FFmpeg 기본 예제

1) VP9 + Opus (일반 웹 배포)

# CRF 모드 (품질 우선)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -row-mt 1 \
  -c:a libopus \
  -b:a 128k \
  output.webm

파라미터 설명:

  • -crf 32: 품질 (libvpx-vp9 범위 0~63, 낮을수록 고품질. 웹 배포용으로는 보통 30 안팎에서 시작해 조정)
  • -b:v 0: CRF 모드 활성화
  • -row-mt 1: 멀티스레드 (VP9)

-b:v 0은 빠뜨리기 쉬운데 결과가 크게 달라집니다. libvpx-vp9는 -b:v를 지정하지 않으면 기본 목표 비트레이트를 적용하기 때문에, -crf만 주면 “CRF 값을 목표로 하되 그 비트레이트를 넘지 않는” 제한 품질 모드가 됩니다. 고해상도 영상에서 CRF를 낮춰도 화질이 좋아지지 않는다면 대개 이 경우입니다. x264의 CRF와 숫자 범위도 의미도 다르므로 x264에서 쓰던 값(예: 23)을 그대로 옮기면 파일이 지나치게 커집니다.

-row-mt 1은 한 프레임을 행 단위로 나눠 여러 스레드가 동시에 인코딩하게 합니다. libvpx-vp9의 기본값은 이 옵션이 꺼진 상태라서, 옵션 없이 인코딩하면 코어가 많은 서버에서도 CPU 사용률이 한두 코어에 머물러 매우 느리게 느껴집니다. 저는 VP9 인코딩이 느리다는 이야기를 들으면 가장 먼저 이 옵션과 -deadline/-cpu-used 설정을 확인합니다.

2) AV1 + Opus (최신 브라우저)

# SVT-AV1 인코더
ffmpeg -i input.mp4 \
  -c:v libsvtav1 \
  -crf 28 \
  -preset 6 \
  -c:a libopus \
  -b:a 128k \
  output.webm

프리셋:

  • 0-3: 느림, 고품질
  • 4-6: 중간
  • 7 이상: 빠름, 같은 CRF에서 압축 효율이 낮음 (최신 SVT-AV1은 13까지)

SVT-AV1의 프리셋은 화질이 아니라 인코더가 탐색하는 양을 정합니다. 빠른 프리셋은 같은 -crf에서 화질이 조금 떨어지거나 파일이 커지는 방식으로 대가를 치릅니다. 그래서 프리셋을 바꿀 때는 CRF도 함께 다시 맞춰야 합니다. AV1의 CRF 범위는 063이고, VP9나 x264와 숫자를 직접 비교할 수 없다는 점도 같습니다. 인코더 버전에 따라 프리셋별 속도와 품질이 꽤 달라지므로, 실제 영상의 12분 구간으로 몇 가지 조합을 시험해 보고 전체 인코딩에 적용하는 방식을 권합니다.

3) 오디오만 (Opus)

# 음악
ffmpeg -i music.wav \
  -c:a libopus \
  -b:a 128k \
  -application audio \
  music.webm
# 음성
ffmpeg -i voice.wav \
  -c:a libopus \
  -b:a 32k \
  -ac 1 \
  -application voip \
  voice.webm

고급 옵션

2-pass 인코딩 (VP9)

# 1st pass
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -b:v 1M \
  -pass 1 \
  -an \
  -f webm \
  /dev/null
# 2nd pass
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -b:v 1M \
  -pass 2 \
  -c:a libopus \
  -b:a 128k \
  output.webm

키프레임 간격 조정

-g는 프레임 수 단위이므로 원하는 초 수에 프레임레이트를 곱해서 정합니다. 아래는 30fps 영상에서 2초 간격입니다.

# 2초마다 키프레임 (30fps 기준, 탐색 개선)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -g 60 \
  -keyint_min 60 \
  -c:a libopus \
  -b:a 128k \
  output.webm

배치 처리

import subprocess
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def convert_to_webm(input_file, output_file, video_crf=32, audio_bitrate='128k'):
    """
    MP4 → WebM 변환
    """
    cmd = [
        'ffmpeg', '-y',
        '-i', str(input_file),
        '-c:v', 'libvpx-vp9',
        '-crf', str(video_crf),
        '-b:v', '0',
        '-row-mt', '1',
        '-c:a', 'libopus',
        '-b:a', audio_bitrate,
        str(output_file)
    ]
    
    subprocess.run(cmd, check=True)
    return output_file
def batch_convert(input_dir, output_dir, max_workers=2):
    """
    병렬 배치 변환
    """
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    
    mp4_files = list(Path(input_dir).glob('*.mp4'))
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = []
        
        for mp4_file in mp4_files:
            output_file = Path(output_dir) / f"{mp4_file.stem}.webm"
            future = executor.submit(convert_to_webm, mp4_file, output_file)
            futures.append((mp4_file.name, future))
        
        for name, future in futures:
            try:
                result = future.result()
                print(f"✓ {name} → {result.name}")
            except Exception as e:
                print(f"✗ {name}: {e}")
# 사용
batch_convert('input_videos', 'output_webm', max_workers=2)

성능 비교

컨테이너 오버헤드

컨테이너오버헤드특징
WebM매우 낮음Matroska 계열, 간단한 구조
MP4낮음최적화되며, 스트리밍 친화
MKV낮음유연하지만 복잡

파일 크기를 결정하는 것은 컨테이너가 아니라 코덱과 인코더 설정입니다. 같은 VP9 스트림을 WebM과 MKV에 각각 담으면 크기 차이는 무시할 만큼 작습니다.

코덱별 파일 크기와 인코딩 시간

같은 체감 화질 기준으로 보면 일반적으로 H.264, VP9, AV1 순으로 파일이 작아지고, 인코딩 시간은 반대로 늘어납니다. 다만 차이의 크기는 영상 종류(움직임이 많은 게임 영상인지, 정지 화면이 많은 슬라이드인지), 해상도, 인코더 버전과 프리셋에 따라 크게 달라지므로 특정 비율을 기준으로 삼기보다는 직접 측정해야 합니다. 측정할 때는 파일 크기만 보지 말고 VMAF나 SSIM 같은 지표로 화질을 맞춘 상태에서 비교해야 공정합니다. -crf 숫자를 같게 맞추는 것은 코덱마다 척도가 달라 의미가 없습니다.

조합파일 크기 경향인코딩 속도 경향호환성
H.264 (MP4) + AAC가장 큼가장 빠름거의 모든 기기
VP9 (WebM) + Opus중간느림주요 브라우저, 최신 Safari
AV1 (WebM) + Opus가장 작음가장 느림 (프리셋에 크게 좌우)최신 브라우저, 디코딩 부담 있음

AV1은 인코딩뿐 아니라 디코딩도 무겁습니다. 하드웨어 AV1 디코더가 없는 오래된 노트북이나 휴대폰에서는 소프트웨어 디코딩으로 CPU 사용률과 배터리 소모가 커지고, 고해상도에서는 프레임이 떨어질 수 있습니다. 대상 기기를 모른다면 AV1만 제공하지 말고 VP9나 H.264를 함께 두는 편이 안전합니다.

브라우저 호환성

브라우저VP8VP9AV1Opus
Chrome✅✅✅✅
Firefox✅✅✅✅
Edge✅✅✅✅
Safari버전별버전별하드웨어 디코더 있는 기기버전별
Opera✅✅✅✅

Safari 지원은 “된다/안 된다”로 단정하기 어렵습니다. macOS Safari는 14.1부터 VP8·VP9 WebM을 재생하지만, iOS·iPadOS는 그보다 늦게, 그리고 기능별로 순차 지원되어 왔고, AV1은 하드웨어 디코더를 갖춘 최신 칩의 기기에서만 재생됩니다. 그래서 “내 Mac에서는 되는데 사용자 아이폰에서는 검은 화면”이라는 상황이 흔합니다. 표를 믿기보다 실제 대상 기기에서 document.createElement('video').canPlayType('video/webm; codecs="vp9, opus"')의 결과를 확인하고, <source> 폴백을 기본으로 깔아 두는 것이 가장 확실합니다.


실무 활용 사례

사례 1: YouTube 스타일 다중 품질

요구사항:

  • 다양한 해상도 제공
  • 적응형 스트리밍
  • 대역폭 최적화

다중 품질 생성

# 1080p (고품질)
ffmpeg -i input.mp4 \
  -vf "scale=1920:1080" \
  -c:v libvpx-vp9 -crf 30 -b:v 0 \
  -c:a libopus -b:a 128k \
  1080p.webm
# 720p (중품질)
ffmpeg -i input.mp4 \
  -vf "scale=1280:720" \
  -c:v libvpx-vp9 -crf 32 -b:v 0 \
  -c:a libopus -b:a 96k \
  720p.webm
# 480p (저품질)
ffmpeg -i input.mp4 \
  -vf "scale=854:480" \
  -c:v libvpx-vp9 -crf 35 -b:v 0 \
  -c:a libopus -b:a 64k \
  480p.webm

HTML5 적응형 플레이어

<!DOCTYPE html>
<html>
<head>
  <title>WebM 적응형 플레이어</title>
</head>
<body>
  <video id="player" controls width="1280"></video>
  
  <div>
    <button onclick="changeQuality('1080p')">1080p</button>
    <button onclick="changeQuality('720p')">720p</button>
    <button onclick="changeQuality('480p')">480p</button>
  </div>
  
  <script>
    const player = document.getElementById('player');
    const qualities = {
      '1080p': 'videos/1080p.webm',
      '720p': 'videos/720p.webm',
      '480p': 'videos/480p.webm'
    };
    
    function changeQuality(quality) {
      const currentTime = player.currentTime;
      player.src = qualities[quality];
      // 새 소스의 메타데이터가 로드된 뒤에야 재생 위치를 옮길 수 있음
      player.addEventListener('loadedmetadata', () => {
        player.currentTime = currentTime;
        player.play();
      }, { once: true });
    }
    
    // 자동 품질 선택
    function selectQuality() {
      const connection = navigator.connection || navigator.mozConnection;
      
      if (!connection) {
        return '720p';
      }
      
      const effectiveType = connection.effectiveType;
      
      if (effectiveType === '4g') {
        return '1080p';
      } else if (effectiveType === '3g') {
        return '480p';
      } else {
        return '720p';
      }
    }
    
    // 초기 로드
    player.src = qualities[selectQuality()];
  </script>
</body>
</html>

이 예제는 품질별로 파일을 통째로 바꾸는 단순한 방식이라, 전환할 때마다 버퍼링이 새로 시작됩니다. 재생 중에 끊김 없이 화질을 바꾸려면 세그먼트 단위로 나눈 DASH와 MSE 기반 플레이어(예: dash.js, Shaka Player)를 써야 합니다. navigator.connection은 Chromium 계열에서만 제공되는 API라서 Firefox와 Safari에서는 기본값으로 떨어집니다.

사례 2: 웹 강의 플랫폼

요구사항:

  • 긴 영상 (1-2시간)
  • 파일 크기 최소화
  • 화면 녹화 (슬라이드)

설정

# 화면 녹화 최적화 (낮은 프레임레이트)
ffmpeg -i lecture.mp4 \
  -vf "scale=1280:720" \
  -r 15 \
  -c:v libvpx-vp9 \
  -crf 35 \
  -b:v 0 \
  -c:a libopus \
  -b:a 64k \
  -ac 1 \
  lecture.webm

강의 영상은 화면 대부분이 정지된 슬라이드라서 프레임 간 변화가 적고, 이런 영상은 VP9가 특히 잘 압축합니다. -r 15로 프레임레이트를 낮추면 비트레이트가 더 줄지만, 마우스 커서나 판서 애니메이션이 끊겨 보일 수 있으므로 판서가 많은 강의라면 30fps를 유지하는 편이 낫습니다. 음성만 있는 강의는 -ac 1로 모노 처리해도 품질 차이가 거의 없고, Opus는 64kbps 모노에서도 음성이 충분히 선명합니다. 결과 크기는 슬라이드 전환 빈도와 화면 구성에 따라 크게 달라지므로 강의 몇 개로 먼저 측정해 보세요.

사례 3: 게임 트레일러

요구사항:

  • 고품질
  • 빠른 로딩
  • 웹 임베드

설정

# 고품질 VP9
ffmpeg -i trailer.mp4 \
  -c:v libvpx-vp9 \
  -crf 24 \
  -b:v 0 \
  -row-mt 1 \
  -c:a libopus \
  -b:a 192k \
  trailer.webm

HTML5 임베드

<video autoplay loop muted playsinline>
  <source src="trailer.webm" type="video/webm">
  <source src="trailer.mp4" type="video/mp4">
</video>

사례 4: 실시간 통신 (WebRTC)

먼저 짚어야 할 점은 WebRTC가 WebM 컨테이너를 쓰지 않는다는 것입니다. WebRTC는 VP8·VP9·AV1·Opus 같은 WebM과 같은 코덱을 쓰지만, 인코딩된 프레임을 파일 형식 없이 RTP 패킷으로 바로 전송합니다. WebM이 실제로 등장하는 곳은 브라우저에서 스트림을 녹화할 때입니다. Chrome과 Firefox의 MediaRecorder는 기본적으로 video/webm 파일을 만들며, 화상 회의 녹화나 화면 녹화 기능이 WebM 파일을 내놓는 이유가 이것입니다. 이렇게 녹화된 WebM은 실시간으로 이어 붙여 쓴 결과라서 재생 시간(Duration) 정보가 없거나 탐색이 안 되는 경우가 많고, ffmpeg -i rec.webm -c copy fixed.webm으로 리먹스하면 대개 해결됩니다.

요구사항:

  • 초저지연
  • 실시간 인코딩
  • P2P 전송

WebRTC 설정

const peerConnection = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// getUserMedia는 해상도·프레임레이트 같은 캡처 조건만 받습니다 (코덱·비트레이트는 여기서 지정 불가)
const stream = await navigator.mediaDevices.getUserMedia({
  video: { width: 1280, height: 720, frameRate: 30 },
  audio: { channelCount: 1 }
});
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));

// 코덱 선호 순서는 transceiver에서 지정 (VP9 우선)
const videoTransceiver = peerConnection.getTransceivers()
  .find(t => t.sender.track && t.sender.track.kind === 'video');
const codecs = RTCRtpReceiver.getCapabilities('video').codecs;
videoTransceiver.setCodecPreferences([
  ...codecs.filter(c => c.mimeType === 'video/VP9'),
  ...codecs.filter(c => c.mimeType !== 'video/VP9')
]);

// 비트레이트 상한은 sender 파라미터로 조정
const sender = videoTransceiver.sender;
const params = sender.getParameters();
if (!params.encodings || params.encodings.length === 0) params.encodings = [{}];
params.encodings[0].maxBitrate = 1_000_000;
await sender.setParameters(params);

최적화 팁

인코딩 속도 개선

VP9 멀티스레드

# 타일 인코딩 (멀티코어 활용)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -row-mt 1 \
  -tile-columns 2 \
  -tile-rows 1 \
  -threads 8 \
  -c:a libopus \
  -b:a 128k \
  output.webm

-tile-columns와 -tile-rows는 log2 값이라서 -tile-columns 2는 열 4개로 나눈다는 뜻입니다. 타일 하나의 폭은 최소 256픽셀이어야 하므로, 해상도가 낮으면 큰 값을 줘도 그만큼 나뉘지 않습니다.

AV1 프리셋 조정

# 빠른 인코딩 (품질 약간 저하)
ffmpeg -i input.mp4 \
  -c:v libsvtav1 \
  -crf 30 \
  -preset 8 \
  -c:a libopus \
  -b:a 128k \
  fast.webm

파일 크기 최소화

# 해상도 + 프레임레이트 감소
ffmpeg -i input.mp4 \
  -vf "scale=854:480" \
  -r 24 \
  -c:v libvpx-vp9 \
  -crf 35 \
  -b:v 0 \
  -c:a libopus \
  -b:a 64k \
  small.webm

스트리밍 최적화

# 키프레임 간격 조정 (2초)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -g 60 \
  -keyint_min 60 \
  -c:a libopus \
  -b:a 128k \
  streaming.webm

트러블슈팅

문제 1: Safari 재생 안 됨

증상: Safari에서 WebM 재생 불가

<video src="video.webm" controls></video>
<!-- Safari: 재생 불가 -->

해결: MP4 폴백 추가

<video controls>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>
# MP4 버전 생성
ffmpeg -i input.mp4 \
  -c:v libx264 \
  -preset medium \
  -crf 23 \
  -c:a aac \
  -b:a 128k \
  fallback.mp4

문제 2: 인코딩 너무 느림

증상: AV1 인코딩이 몇 시간 소요 해결 1: VP9 사용

# AV1 대신 VP9 (설정에 따라 훨씬 빠를 수 있음)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -c:a libopus \
  -b:a 128k \
  output.webm

해결 2: 프리셋 조정

# AV1 빠른 프리셋
ffmpeg -i input.mp4 \
  -c:v libsvtav1 \
  -crf 30 \
  -preset 10 \
  -c:a libopus \
  -b:a 128k \
  fast.webm

문제 3: 재생 시 끊김

증상: 웹 플레이어에서 버퍼링 발생, 또는 탐색(seek) 후 재생 시작이 느림 원인: 키프레임 간격이 너무 길거나, 네트워크 대역폭보다 비트레이트가 높음

키프레임 간격은 주로 탐색과 적응형 스트리밍에 영향을 줍니다. 플레이어는 키프레임부터만 디코딩을 시작할 수 있어서, 간격이 10초라면 탐색할 때 최대 10초 분량을 먼저 받아야 합니다. DASH처럼 세그먼트 단위로 화질을 바꾸는 경우에는 세그먼트 경계마다 키프레임이 있어야 하므로 간격을 세그먼트 길이에 맞춥니다. 반면 처음부터 끝까지 이어서 재생만 하는데 끊긴다면 키프레임보다 비트레이트가 원인인 경우가 많으니, -maxrate와 -bufsize로 순간 비트레이트 상한을 두는 것도 함께 검토하세요. 해결:

# 키프레임 간격 줄이기 (30fps 기준 2초)
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -g 60 \
  -c:a libopus \
  -b:a 128k \
  output.webm

문제 4: 오디오 코덱 미지원

증상: WebM에 AAC 넣었더니 재생 안 됨

# 잘못된 예
ffmpeg -i input.mp4 -c:v libvpx-vp9 -c:a aac output.webm
# WebM은 AAC 지원 안 함

최신 FFmpeg는 이 명령을 실행하는 단계에서 Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM. 오류를 내고 파일 작성을 거부합니다. 재생이 안 되는 파일이 만들어졌다면 확장자를 .mkv로 출력한 뒤 이름만 .webm으로 바꿨거나, 다른 도구로 만든 경우입니다. ffprobe output.webm으로 실제 들어 있는 코덱을 확인하세요. 해결: Opus 또는 Vorbis 사용

# 올바른 예
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 \
  -crf 32 \
  -b:v 0 \
  -c:a libopus \
  -b:a 128k \
  output.webm

선택 가이드

상황별로 어떤 포맷을 기본으로 둘지 정리하면 다음과 같습니다. 코덱 자체는 로열티 없이 공개되어 있지만, 특허 관련 최종 판단은 서비스마다 법률 검토가 필요합니다.

상황추천
최대 호환MP4 (H.264 + AAC)
대역폭 절약WebM (VP9/AV1 + Opus)
오픈 코덱WebM
Safari 필수MP4 + WebM 병행
편집 워크플로MP4/MOV

다음 단계

참고 자료


자주 묻는 질문 (FAQ)

Q. WebM용 AV1 인코딩이 너무 오래 걸리면 어떻게 하나요?

A. AV1은 압축 효율이 높은 대신 인코딩 연산량이 커서, 같은 영상이라도 VP9보다 훨씬 오래 걸릴 수 있습니다. 인코딩 시간이 중요하다면 libvpx-vp9로 바꾸거나, AV1을 유지하되 libsvtav1의 -preset 값을 높여 속도를 우선하는 방법이 있습니다. 프리셋을 빠르게 하면 같은 품질에서 파일이 커질 수 있으므로, 샘플 구간으로 속도와 크기를 비교한 뒤 전체 인코딩에 적용하는 것이 좋습니다.


같이 보면 좋은 글