[2026] MKV(Matroska) 컨테이너 실전 활용 | EBML·다중 자막·FFmpeg 리먹스

[2026] MKV(Matroska) 컨테이너 실전 활용 | EBML·다중 자막·FFmpeg 리먹스

이 글의 핵심

EBML 기반 Matroska(MKV)의 Segment·Cluster 구조, 다중 오디오·자막·챕터 관리, FFmpeg·실무 워크플로까지 아카이브·배포 관점에서 정리했습니다.

들어가며

MKV(Matroska Video)EBML(Extensible Binary Meta Language)을 뼈대로 한 오픈 사양 컨테이너로, 여러 오디오·자막·챕터·첨부 파일을 한 파일에 의미 있게 묶는 것에 강합니다. 블루레이 리핑, 팟캐스트 아카이브, 다국어 강의 녹화, 자막 제작 워크플로처럼 “한 콘텐츠에 선택지가 많은 패키지”가 필요할 때 MP4보다 표현력에서 유리한 경우가 많습니다.

이 글을 읽으면

  • EBML·Segment·Cluster의 역할을 한 장면으로 설명할 수 있습니다
  • 다중 오디오·자막·챕터맵·메타데이터와 함께 다루는 명령을 복사해 쓸 수 있습니다
  • MKV vs MP4/WebM유연성 vs 호환성 축으로 선택할 수 있습니다
  • 자주 막히는 플레이어 이슈를 원인별로 줄일 수 있습니다

실무에서 마주한 현실

개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.

목차

  1. 컨테이너 개요
  2. 내부 구조
  3. 실전 사용
  4. 성능 비교
  5. 실무 활용 사례
  6. 최적화 팁
  7. 트러블슈팅
  8. 마무리

컨테이너 개요

역사 및 개발 배경

MatroskaMCF 등 기존 포맷을 대체하려는 목적으로 2000년대에 설계된 오픈 컨테이너이며, EBML확장 가능한 요소 트리를 표현합니다. 주요 마일스톤:

  • 2002: Matroska 프로젝트 시작
  • 2010: WebM (Matroska 부분집합) 발표
  • 2026: 블루레이 리핑, 아카이브 표준

기술적 특징

항목설명
기반EBML (Extensible Binary Meta Language)
트랙비디오, 오디오, 자막 독립 트랙
코덱H.264, HEVC, AV1, FLAC, AC3, ASS 등 광범위
메타데이터Tags, Chapters, Attachments
확장자.mkv (비디오), .mka (오디오), .mks (자막)

MKV vs MP4 vs WebM

특징MKVMP4WebM
코덱 지원거의 모든 코덱H.264/HEVC + AAC 중심VP8/VP9/AV1 + Opus
다중 트랙매우 강함제한적제한적
챕터풍부제한적제한적
브라우저 지원낮음최고높음
용도아카이브범용 배포웹 배포

내부 구조

EBML과 Matroska 요소

EBML은 가변 길이 정수(VINT)요소 ID·크기를 인코딩해, 앞에서 순차 스캔하며 트리를 복원합니다. 구조: 다음은 text를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

MKV 파일
├─ EBML Header
│  ├─ DocType: "matroska"
│  └─ DocTypeVersion: 4
├─ Segment
│  ├─ SeekHead (인덱스)
│  ├─ Info
│  │  ├─ TimestampScale: 1000000
│  │  ├─ Duration: 300.0s
│  │  └─ Title: "영화 제목"
│  ├─ Tracks
│  │  ├─ Video Track
│  │  │  ├─ CodecID: V_MPEG4/ISO/AVC
│  │  │  └─ Width: 1920, Height: 1080
│  │  ├─ Audio Track 1 (한국어)
│  │  │  ├─ CodecID: A_AAC
│  │  │  └─ Language: kor
│  │  ├─ Audio Track 2 (영어)
│  │  │  └─ Language: eng
│  │  └─ Subtitle Track (한국어)
│  │     ├─ CodecID: S_TEXT/ASS
│  │     └─ Language: kor
│  ├─ Tags
│  │  ├─ TITLE: "영화 제목"
│  │  ├─ ARTIST: "감독"
│  │  └─ DATE: "2026"
│  ├─ Chapters
│  │  ├─ Chapter 1: 00:00:00 "오프닝"
│  │  └─ Chapter 2: 00:05:00 "본편"
│  ├─ Attachments
│  │  └─ Font: subtitle_font.ttf
│  ├─ Cluster 1 (0-2s)
│  ├─ Cluster 2 (2-4s)
│  └─ Cues (시크 인덱스)

실전 사용

기본 명령

1) 구조 확인

아래 코드는 bash를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 전체 정보
ffprobe -hide_banner -show_format -show_streams -show_chapters input.mkv
# 트랙 목록만
ffprobe -v error -show_entries stream=index,codec_type,codec_name,language input.mkv

2) 무손실 리먹스

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# MKV → MKV (코덱 복사)
ffmpeg -i input.mkv -c copy output.mkv
# MP4 → MKV
ffmpeg -i input.mp4 -c copy output.mkv

다중 트랙 관리

여러 입력에서 트랙 조립

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 비디오 + 다중 오디오 + 자막
ffmpeg -i video.mp4 \
  -i audio_kor.m4a \
  -i audio_eng.m4a \
  -i subtitle_kor.srt \
  -i subtitle_eng.srt \
  -map 0:v:0 \
  -map 1:a:0 \
  -map 2:a:0 \
  -map 3:s:0 \
  -map 4:s:0 \
  -c copy \
  -metadata:s:a:0 language=kor -metadata:s:a:0 title="한국어" \
  -metadata:s:a:1 language=eng -metadata:s:a:1 title="English" \
  -metadata:s:s:0 language=kor -metadata:s:s:0 title="한국어 자막" \
  -metadata:s:s:1 language=eng -metadata:s:s:1 title="English Subtitle" \
  package.mkv

기본 트랙 설정

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 첫 번째 오디오를 기본으로
ffmpeg -i input.mkv \
  -c copy \
  -disposition:a:0 default \
  -disposition:a:1 0 \
  output.mkv

자막 관리

자막 추출

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 첫 번째 자막 트랙
ffmpeg -i input.mkv -map 0:s:0 -c:s copy subtitle.srt
# 모든 자막 트랙
ffmpeg -i input.mkv -map 0:s -c:s copy subtitle_%d.srt

자막 추가

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 외부 SRT 추가
ffmpeg -i video.mkv -i subtitle.srt \
  -map 0 -map 1 \
  -c copy \
  -metadata:s:s:0 language=kor \
  output.mkv

ASS 자막 + 폰트 임베드

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# ASS 자막 + 폰트 첨부
ffmpeg -i video.mkv \
  -i subtitle.ass \
  -attach font.ttf -metadata:s:t mimetype=application/x-truetype-font \
  -map 0 -map 1 \
  -c copy \
  -metadata:s:s:0 language=kor \
  output.mkv

챕터 관리

챕터 추가

아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 챕터 파일 (chapters.txt)
cat > chapters.txt << EOF
CHAPTER01=00:00:00.000
CHAPTER01NAME=오프닝
CHAPTER02=00:05:00.000
CHAPTER02NAME=본편
CHAPTER03=00:50:00.000
CHAPTER03NAME=엔딩
EOF
# 챕터 추가
ffmpeg -i input.mkv -i chapters.txt -map_metadata 1 -c copy output.mkv

MKV → MP4 변환

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 코덱 호환 시 (H.264 + AAC)
ffmpeg -i input.mkv \
  -c:v copy \
  -c:a copy \
  -map 0:v:0 \
  -map 0:a:0 \
  -movflags +faststart \
  output.mp4
# 코덱 변환 필요 시
ffmpeg -i input.mkv \
  -c:v libx264 \
  -preset medium \
  -crf 23 \
  -c:a aac \
  -b:a 192k \
  -movflags +faststart \
  output.mp4

성능 비교

컨테이너 오버헤드

컨테이너오버헤드메타데이터복잡도
MKV매우 낮음풍부높음
MP4낮음중간중간
WebM매우 낮음제한적낮음
결론: 컨테이너 오버헤드는 거의 무시 가능

트랙 개수별 파일 크기

테스트: 1080p 1시간 영상

구성파일 크기비고
비디오만1.2GB기준
+ 오디오 1개1.25GB+50MB
+ 오디오 3개1.35GB+150MB
+ 자막 5개1.36GB+10MB (텍스트)
결론: 오디오 트랙이 주요 용량 증가 요인

실무 활용 사례

사례 1: 블루레이 리핑 - 다중 오디오·자막

요구사항:

  • 원본 품질 유지
  • 다국어 오디오
  • 다국어 자막
  • 챕터 보존

MakeMKV 출력 → FFmpeg 정리

아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# MakeMKV 출력 (모든 트랙 포함)
# input.mkv: 비디오 1개, 오디오 5개, 자막 10개
# 필요한 트랙만 선택
ffmpeg -i input.mkv \
  -map 0:v:0 \
  -map 0:a:0 -map 0:a:1 \
  -map 0:s:0 -map 0:s:1 \
  -c copy \
  -metadata:s:a:0 language=kor -metadata:s:a:0 title="한국어" \
  -metadata:s:a:1 language=eng -metadata:s:a:1 title="English" \
  -metadata:s:s:0 language=kor \
  -metadata:s:s:1 language=eng \
  cleaned.mkv

Python 자동화

다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

import subprocess
from pathlib import Path
def clean_bluray_rip(input_file, output_file, keep_tracks):
    """
    블루레이 리핑 정리
    keep_tracks: {'audio': [0, 1], 'subtitle': [0, 1]}
    """
    cmd = ['ffmpeg', '-i', str(input_file)]
    
    cmd.extend(['-map', '0:v:0'])
    
    for audio_idx in keep_tracks.get('audio', []):
        cmd.extend(['-map', f'0:a:{audio_idx}'])
    
    for sub_idx in keep_tracks.get('subtitle', []):
        cmd.extend(['-map', f'0:s:{sub_idx}'])
    
    cmd.extend(['-c', 'copy', str(output_file)])
    
    subprocess.run(cmd, check=True)
# 사용
keep_tracks = {
    'audio': [0, 1],  # 한국어, 영어
    'subtitle': [0, 1, 2]  # 한국어, 영어, 일본어
}
clean_bluray_rip('rip.mkv', 'cleaned.mkv', keep_tracks)

사례 2: 다국어 강의 - 오디오 트랙 전환

요구사항:

  • 강의 비디오
  • 한국어/영어 음성
  • 한국어/영어 자막

생성

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 비디오 + 다국어 오디오 + 자막
ffmpeg -i lecture.mp4 \
  -i audio_kor.wav \
  -i audio_eng.wav \
  -i subtitle_kor.srt \
  -i subtitle_eng.srt \
  -map 0:v:0 \
  -map 1:a:0 \
  -map 2:a:0 \
  -map 3:s:0 \
  -map 4:s:0 \
  -c:v copy \
  -c:a aac -b:a 128k \
  -c:s copy \
  -metadata:s:a:0 language=kor -metadata:s:a:0 title="한국어" \
  -metadata:s:a:1 language=eng -metadata:s:a:1 title="English" \
  -metadata:s:s:0 language=kor \
  -metadata:s:s:1 language=eng \
  -disposition:a:0 default \
  lecture_multi.mkv

사례 3: 팟캐스트 아카이브 - 챕터 마커

요구사항:

  • 긴 팟캐스트 (2시간)
  • 챕터 마커 (주제별)
  • 메타데이터

챕터 파일 생성

아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# chapters.txt
cat > chapters.txt << EOF
CHAPTER01=00:00:00.000
CHAPTER01NAME=인트로
CHAPTER02=00:05:30.000
CHAPTER02NAME=주제 1: 기술 트렌드
CHAPTER03=00:35:00.000
CHAPTER03NAME=주제 2: 커리어
CHAPTER04=00:65:00.000
CHAPTER04NAME=Q&A
CHAPTER05=01:55:00.000
CHAPTER05NAME=아웃트로
EOF

MKV 생성

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

ffmpeg -i podcast.wav \
  -i chapters.txt \
  -c:a aac -b:a 128k \
  -map_metadata 1 \
  -metadata title="팟캐스트 에피소드 1" \
  -metadata artist="호스트 이름" \
  -metadata date="2026-03-31" \
  podcast_ep01.mka

사례 4: 영화 컬렉션 - 감독 해설 트랙

요구사항:

  • 원본 오디오
  • 감독 해설 오디오
  • 한국어/영어 자막

생성

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

ffmpeg -i movie.mp4 \
  -i commentary.wav \
  -i subtitle_kor.srt \
  -i subtitle_eng.srt \
  -map 0:v:0 \
  -map 0:a:0 \
  -map 1:a:0 \
  -map 2:s:0 \
  -map 3:s:0 \
  -c:v copy \
  -c:a aac -b:a 192k \
  -c:s copy \
  -metadata:s:a:0 title="원본 오디오" \
  -metadata:s:a:1 title="감독 해설" \
  -metadata:s:s:0 language=kor \
  -metadata:s:s:1 language=eng \
  -disposition:a:0 default \
  movie_deluxe.mkv

최적화 팁

1) 불필요한 트랙 제거

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 비디오 + 첫 번째 오디오만
ffmpeg -i input.mkv \
  -map 0:v:0 \
  -map 0:a:0 \
  -c copy \
  slim.mkv

2) 자막 형식 변환

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# ASS → SRT
ffmpeg -i input.mkv \
  -map 0:s:0 \
  -c:s srt \
  subtitle.srt
# SRT → ASS
ffmpeg -i subtitle.srt subtitle.ass

3) 오디오 정규화

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 라우드니스 정규화
ffmpeg -i input.mkv \
  -c:v copy \
  -af "loudnorm=I=-16:TP=-1.5:LRA=11" \
  -c:a aac -b:a 192k \
  normalized.mkv

트러블슈팅

문제 1: 브라우저에서 재생 안 됨

증상: HTML5 video에서 MKV 재생 불가

<video src="video.mkv" controls></video>
<!-- 대부분 브라우저: 재생 불가 -->

해결: MP4 또는 WebM으로 변환 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# MP4로 변환
ffmpeg -i input.mkv \
  -c:v libx264 \
  -c:a aac \
  -movflags +faststart \
  output.mp4

문제 2: 자막이 안 보임

증상: 플레이어에서 자막 트랙 인식 안 됨 원인 1: 언어 태그 누락 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 언어 태그 추가
ffmpeg -i input.mkv \
  -c copy \
  -metadata:s:s:0 language=kor \
  output.mkv

원인 2: 코덱 미지원 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# ASS → SRT 변환
ffmpeg -i input.mkv \
  -map 0:v -map 0:a \
  -map 0:s:0 \
  -c:v copy -c:a copy \
  -c:s srt \
  output.mkv

문제 3: 오디오 트랙 선택 안 됨

증상: 플레이어가 항상 첫 번째 오디오만 재생 해결: 기본 트랙 설정 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 두 번째 오디오를 기본으로
ffmpeg -i input.mkv \
  -c copy \
  -disposition:a:0 0 \
  -disposition:a:1 default \
  output.mkv

문제 4: 파일 크기 너무 큼

증상: 불필요한 트랙으로 파일 비대 해결: 트랙 정리 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 필요한 트랙만 유지
ffmpeg -i input.mkv \
  -map 0:v:0 \
  -map 0:a:0 \
  -map 0:s:0 \
  -c copy \
  slim.mkv

문제 5: 챕터 손실

증상: MKV → MP4 변환 시 챕터 사라짐 원인: MP4는 챕터 지원 제한적 해결: MKV 유지 또는 외부 챕터 파일

# 챕터 추출
ffprobe -v error -show_chapters -of json input.mkv > chapters.json

마무리

MKVEBML/Matroska 기반으로 다중 트랙·챕터·태그·첨부까지 담기 좋은 유연한 컨테이너입니다.

핵심 요약

  1. 유연성
    • 거의 모든 코덱 지원
    • 다중 오디오·자막·챕터
    • 첨부 파일 (폰트, 커버)
  2. 아카이브 최적
    • 원본 품질 유지
    • 메타데이터 풍부
    • 편집 워크플로 친화
  3. 배포 제약
    • 브라우저 지원 제한
    • 모바일 호환성 낮음
    • MP4 변환 필요

선택 가이드

상황추천
아카이브·보관MKV
웹 배포MP4/WebM
다중 트랙 필요MKV
최대 호환MP4
편집 워크플로MKV (중간), MP4 (최종)

FFmpeg 명령 치트시트

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 기본 리먹스
ffmpeg -i input.mkv -c copy output.mkv
# 다중 오디오 추가
ffmpeg -i video.mp4 -i audio1.wav -i audio2.wav \
  -map 0:v -map 1:a -map 2:a \
  -c:v copy -c:a aac -b:a 192k \
  -metadata:s:a:0 language=kor \
  -metadata:s:a:1 language=eng \
  output.mkv
# 자막 추가
ffmpeg -i video.mkv -i subtitle.srt \
  -map 0 -map 1 \
  -c copy \
  -metadata:s:s:0 language=kor \
  output.mkv
# MKV → MP4
ffmpeg -i input.mkv -c:v copy -c:a copy -movflags +faststart output.mp4
# 트랙 제거
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy slim.mkv

다음 단계

참고 자료

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3