본문 바로가기
디지털 파일 검증 연구소 디지털 파일 검증 연구소

MP4 파일 구조 분석|ftyp·moov·mdat 박스와 메타데이터 확인 방법

디지털 파일 검증 연구소 읽는 시간 약 42분

MP4는 스마트폰 동영상, 디지털카메라 영상, 온라인 강의, 웹사이트 동영상 등 다양한 환경에서 사용되는 멀티미디어 컨테이너 형식이다.

일반적으로 .mp4 확장자로 저장되며, 하나의 파일 안에 영상, 음성, 자막, 재생 시간, 트랙 정보 등을 함께 담을 수 있다.

그러나 MP4 파일은 단순히 영상과 음성 데이터를 이어 붙인 파일이 아니다.

파일 형식과 호환성을 나타내는 ftyp, 재생에 필요한 구조와 메타데이터를 담는 moov, 실제 미디어 데이터를 저장하는 mdat 등의 박스(Box)로 구성된다.

또한 moov 내부에는 mvhd, trak, mdia, minf, stbl 같은 하위 박스가 존재할 수 있으며, 각 박스는 재생 시간, 트랙 구성, 샘플 위치, 시간 정보 등을 해석하는 데 사용된다.

이번 글에서는 MP4 파일 구조 분석을 중심으로 ISO Base Media File Format의 기본 원리, 주요 박스의 역할, 메타데이터 구성, 파일 손상 점검 방법을 설명한다.

Windows PowerShell 5.1을 이용해 실제 MP4 파일의 헤더와 최상위 박스를 확인하는 실습도 진행한다.

1. MP4 파일 구조 분석이 필요한 이유

MP4 파일은 대부분의 동영상 재생 프로그램에서 쉽게 열 수 있다.

하지만 확장자가 .mp4라고 해서 모든 파일이 정상적인 MP4 구조를 갖추고 있거나 모든 재생 환경에서 동작하는 것은 아니다.

다음과 같은 상황에서 내부 구조 분석이 도움이 된다.

  • MP4 파일이 열리지 않는 경우
  • 동영상 재생 시간이 0초로 표시되는 경우
  • 영상은 나오지만 음성이 재생되지 않는 경우
  • 파일 전송 중 손상이 의심되는 경우
  • 다운로드한 MP4가 정상적인 컨테이너인지 확인하려는 경우
  • moov 박스가 존재하는지 확인하려는 경우
  • 파일의 주요 박스 크기와 위치를 조사하려는 경우
  • 원본 파일과 복사본의 무결성을 비교하려는 경우

MP4 구조 분석은 파일 형식 오류, 메타데이터 누락, 미디어 데이터 손상 가능성을 구분하는 첫 단계가 될 수 있다.

다만 박스 구조가 정상적으로 보인다는 사실만으로 실제 영상과 음성이 완전히 재생된다고 보장할 수는 없다.

2. MP4와 ISO Base Media File Format의 관계

MP4 파일 구조를 이해하려면 먼저 ISO Base Media File Format을 알아야 한다.

ISO Base Media File Format은 시간에 따라 재생되는 미디어 데이터를 저장하기 위한 기본 컨테이너 구조를 정의한다.

대표적인 관련 표준은 다음과 같다.

  • ISO/IEC 14496-12: ISO Base Media File Format
  • ISO/IEC 14496-14: MP4 File Format

ISO/IEC 14496-12는 박스 구조와 미디어 데이터 표현의 기본 규칙을 제공한다.

ISO/IEC 14496-14는 이 기반 형식에서 파생된 MP4 파일 형식을 정의한다.

따라서 MP4는 ISO Base Media File Format을 사용하는 여러 파일 형식 중 하나로 이해할 수 있다.

MP4는 코덱이 아니다

MP4는 영상이나 음성을 직접 압축하는 코덱 자체가 아니라, 압축된 미디어와 관련 정보를 저장하는 컨테이너 형식이다.

예를 들어 MP4 파일 안에는 H.264 또는 H.265 계열의 영상과 AAC 계열의 음성이 저장될 수 있다.

그러나 MP4 확장자만 보고 내부 코덱을 확정할 수는 없다.

파일의 실제 코덱을 파악하려면 트랙과 샘플 설명 정보를 확인해야 한다.

3. MP4 파일의 전체 구조

일반적인 비분할 MP4 파일은 여러 최상위 박스로 구성된다.

MP4 기본 구조

MP4 File
│
├── ftyp
│   ├── major_brand
│   ├── minor_version
│   └── compatible_brands
│
├── moov
│   ├── mvhd
│   │
│   └── trak
│       ├── tkhd
│       │
│       └── mdia
│           ├── mdhd
│           ├── hdlr
│           │
│           └── minf
│               └── stbl
│                   ├── stsd
│                   ├── stts
│                   ├── stsc
│                   ├── stsz
│                   └── stco / co64
│
└── mdat
    └── Media Data

위 구조는 이해를 돕기 위한 단순화된 예시다.

실제 MP4 파일에서는 박스의 순서와 개수, 하위 박스 구성이 달라질 수 있다.

특히 moov 안에는 여러 trak 박스가 존재할 수 있으며, 분할 MP4(Fragmented MP4)에서는 moof와 mdat가 반복되는 구조도 사용된다.

주요 박스의 역할

박스주요 역할
ftyp파일 형식과 호환 브랜드
moov재생 구조 및 메타데이터
mvhd영화 전체의 시간 관련 정보
trak개별 미디어 트랙
tkhd트랙 헤더
mdia트랙 미디어 정보
mdhd미디어 시간 정보
hdlr트랙 처리 유형
minf미디어 정보 컨테이너
stbl샘플 테이블
stsd샘플 설명 및 코덱 관련 정보
stts디코딩 시간 정보
stsc샘플과 청크의 관계
stsz샘플 크기 정보
stco32비트 청크 오프셋
co6464비트 청크 오프셋
mdat미디어 데이터
moof분할 미디어의 프래그먼트 정보

이 박스들은 서로 연관되어 동영상 재생에 필요한 정보를 제공한다.

4. MP4 박스의 기본 구조

MP4에서 박스는 파일 내부의 구조적 데이터 단위다.

일반적인 박스는 크기와 유형을 나타내는 헤더로 시작한다.

기본 박스 구조

+-------------------------+
| size          4 bytes   |
+-------------------------+
| type          4 bytes   |
+-------------------------+
| payload       variable  |
+-------------------------+

size는 일반적으로 박스 전체 크기를 나타낸다.

이 값에는 8바이트 기본 헤더도 포함된다.

type은 박스의 종류를 나타내는 4바이트 식별자다.

예를 들어 다음과 같다.

ftyp
moov
mdat
free

박스 크기 계산

일반적인 박스의 전체 크기는 다음과 같다.

Box Size = Header Size + Payload Size

기본 헤더는 8바이트다.

하지만 모든 박스가 반드시 8바이트 헤더만 사용하는 것은 아니다.

5. MP4 박스의 32비트·64비트 길이 규칙

MP4 파일을 분석할 때는 박스 크기의 예외 규칙을 이해해야 한다.

일반적인 박스

size 값이 1보다 크면 해당 값이 박스 전체 크기를 나타낸다.

size = 24
type = ftyp

이 경우 박스의 전체 크기는 24바이트다.

size가 1인 경우

size가 1이면 기본 헤더 뒤에 64비트 largesize 필드가 추가된다.

+-------------------------+
| size = 1       4 bytes  |
+-------------------------+
| type           4 bytes  |
+-------------------------+
| largesize      8 bytes  |
+-------------------------+
| payload        variable |
+-------------------------+

이 경우 일반적인 확장 헤더는 16바이트다.

largesize는 확장 헤더를 포함한 박스 전체 크기를 나타낸다.

size가 0인 경우

size가 0이면 해당 박스가 파일 끝까지 이어진다는 의미로 사용된다.

다만 실제 적용에는 박스 유형과 파일 형식의 제약이 있으므로 모든 박스에 무조건 허용되는 규칙으로 이해해서는 안 된다.

UUID 박스

유형이 uuid인 박스에는 사용자 정의 유형을 식별하기 위한 추가 16바이트가 존재한다.

따라서 UUID 박스는 일반 박스보다 헤더가 길다.

6. MP4 파일 시그니처와 ftyp 식별 원리

MP4 파일을 식별할 때는 ftyp 박스를 확인하는 방법이 널리 사용된다.

일반적인 MP4 파일에서는 파일 시작 부분에 ftyp 박스가 배치된다.

대표적인 헤더 예시

00 00 00 20 66 74 79 70
69 73 6F 6D 00 00 02 00

앞의 4바이트는 박스 크기다.

00 00 00 20

16진수 0x20은 10진수 32다.

다음 4바이트는 박스 유형이다.

66 74 79 70

ASCII 문자열로 변환하면 다음과 같다.

ftyp

이후에는 주요 브랜드와 호환 브랜드 등의 정보가 이어진다.

주의사항

MP4는 JPEG의 FF D8이나 PNG의 고정 8바이트 시그니처처럼 단일한 시작 바이트열만으로 모든 파일을 식별하는 방식과 다르다.

일반적인 MP4에서는 파일 시작 부분의 박스 구조와 ftyp 브랜드 정보를 함께 확인한다.

따라서 ftyp 문자열만 발견했다고 해서 해당 파일이 정상적인 MP4라고 확정할 수는 없다.

7. ftyp 박스와 브랜드 정보

ftyp은 File Type Box를 의미한다.

이 박스는 파일 형식의 식별과 호환성 판단에 사용되는 정보를 담는다.

주요 필드

필드크기의미
major_brand4바이트주요 브랜드
minor_version4바이트부 버전 정보
compatible_brands4바이트 단위 반복호환 브랜드 목록

브랜드 예시

isom
iso2
mp41
mp42

이 값들은 파일의 형식과 호환성에 관한 정보를 제공한다.

하지만 브랜드가 특정 값을 가진다고 해서 영상 코덱, 음성 코덱, 해상도 또는 정상 재생 가능 여부가 자동으로 결정되는 것은 아니다.

ftyp 분석의 한계

ftyp은 파일 형식 식별의 중요한 단서지만 전체 파일의 적합성을 검증하는 장치는 아니다.

정확한 판단을 위해서는 박스 경계와 필수 구조, 트랙 구성 등을 추가로 점검해야 한다.

8. moov 박스와 동영상 메타데이터

moov는 Movie Box를 의미한다.

MP4 파일에서 재생 구조를 해석하는 데 중요한 박스다.

moov 내부에는 재생 시간과 트랙 구성, 미디어 샘플을 찾아가기 위한 정보 등이 저장될 수 있다.

moov 내부의 대표적인 구성

moov
│
├── mvhd
│
├── trak
│   ├── tkhd
│   └── mdia
│       ├── mdhd
│       ├── hdlr
│       └── minf
│           └── stbl
│
└── trak
    └── ...

moov의 주요 역할

  • 전체 미디어의 시간 관련 정보 제공
  • 비디오와 오디오 등 트랙 구조 관리
  • 미디어 샘플 위치 해석에 필요한 정보 제공
  • 트랙별 시간 정보 및 샘플 구성 연결
  • 재생에 필요한 메타데이터 제공

moov가 없거나 내부 구조가 손상되면 일반적인 비분할 MP4 파일의 재생이 어려워질 수 있다.

그러나 모든 MP4 파일이 동일한 방식으로 moov를 사용하는 것은 아니며, 분할 MP4와 초기화 세그먼트 등의 구조도 고려해야 한다.

9. mvhd 박스와 재생 시간 정보

mvhd는 Movie Header Box다.

일반적으로 moov 내부에 위치한다.

이 박스에는 전체 영화의 시간 척도와 재생 시간 등에 관한 정보가 포함된다.

주요 필드

필드역할
version필드 해석 버전
creation_time생성 시각 관련 값
modification_time수정 시각 관련 값
timescale시간 단위의 기준
duration시간 단위로 표현한 길이

재생 시간 계산

일반적인 경우 다음과 같은 계산이 가능하다.

재생 시간(초) = duration / timescale

예를 들어 다음과 같다면,

timescale = 1000
duration  = 125000

계산 결과는 다음과 같다.

125000 / 1000 = 125초

이는 약 2분 5초다.

다만 duration 값이 미정의 값이거나 편집 목록, 프래그먼트 구조 등의 영향을 받는 경우에는 단순 계산만으로 실제 재생 시간을 확정하기 어렵다.

10. trak 박스와 영상·음성 트랙

trak은 Track Box다.

하나의 MP4 파일에는 여러 트랙이 존재할 수 있다.

대표적인 트랙은 다음과 같다.

  • 비디오 트랙
  • 오디오 트랙
  • 자막 또는 시간 기반 텍스트 트랙
  • 기타 시간 기반 미디어 트랙

trak의 주요 하위 박스

tkhd

트랙 식별과 트랙 헤더 정보를 담는다.

mdia

트랙에 연결된 미디어 정보를 담는 컨테이너다.

mdhd

해당 미디어의 시간 척도와 길이 등을 나타낸다.

hdlr

미디어를 처리하는 유형을 식별한다.

트랙 구조 확인이 필요한 이유

동영상 파일에서 영상은 정상적으로 표시되지만 음성이 나오지 않는 경우가 있다.

이때 트랙 구조를 분석하면 오디오 트랙 자체가 없는지, 트랙은 있지만 재생 프로그램이 코덱을 지원하지 않는지 등을 구분하는 데 도움이 된다.

단, 박스 존재 여부만으로 코덱 지원 문제를 확정할 수는 없다.

11. mdia·minf·stbl 박스의 역할

mdia는 Media Box다.

일반적으로 trak 내부에 존재하며 트랙의 미디어 정보를 관리한다.

minf는 Media Information Box로, 미디어 관련 정보를 담는 컨테이너다.

stbl은 Sample Table Box로, 미디어 샘플을 찾아가고 시간 정보를 해석하는 데 필요한 테이블을 포함한다.

주요 샘플 테이블

박스의미
stsd샘플 설명
stts디코딩 시간 정보
ctts구성 시간 오프셋
stsc샘플과 청크의 관계
stsz샘플 크기
stco32비트 청크 오프셋
co6464비트 청크 오프셋
stss동기 샘플 정보

모든 파일에 위 박스가 전부 포함되는 것은 아니다.

미디어 종류, 코덱, 파일 형식, 프래그먼트 사용 여부 등에 따라 구성은 달라질 수 있다.

12. mdat 박스와 실제 미디어 데이터

mdat는 Media Data Box다.

이 박스는 영상과 음성 등의 실제 미디어 데이터를 저장하는 데 사용된다.

mdat의 개념적 구조

mdat
│
├── Video Samples
│
├── Audio Samples
│
└── Other Media Data

위 그림은 개념적인 표현이다.

실제 미디어 데이터의 배열과 구분은 샘플 테이블 및 프래그먼트 메타데이터에 의해 해석된다.

mdat 안의 데이터를 단순히 영상 구간과 음성 구간으로 나누어 저장한다고 일반화해서는 안 된다.

mdat가 중요한 이유

moov가 미디어의 위치와 재생 구조를 설명한다면, mdat는 실제 미디어 데이터를 담는 역할을 한다.

하지만 mdat가 존재한다고 해서 그 안의 영상과 음성 데이터가 정상이라는 뜻은 아니다.

실제 재생 가능 여부를 확인하려면 샘플 위치와 크기, 코덱 구성, 데이터 복호화 또는 디코딩 가능성 등을 추가로 점검해야 한다.

13. moov 박스 위치와 스트리밍

MP4 파일에서는 moov와 mdat의 배치가 재생 시작 방식에 영향을 줄 수 있다.

moov가 앞에 있는 경우

ftyp
moov
mdat

재생에 필요한 메타데이터를 파일 앞부분에서 읽을 수 있으므로 일반적인 HTTP 기반 점진적 다운로드 재생에 유리할 수 있다.

moov가 뒤에 있는 경우

ftyp
mdat
moov

일부 재생 환경에서는 재생을 시작하기 전에 파일 뒤쪽의 메타데이터를 읽어야 할 수 있다.

이 때문에 다운로드나 네트워크 접근 방식에 따라 재생 시작이 지연될 수 있다.

Fast Start의 의미

일반적으로 Fast Start 또는 Web Optimized MP4는 재생에 필요한 moov 정보를 파일 앞부분에 배치하는 최적화와 관련된다.

다만 moov 위치만으로 모든 스트리밍 성능이 결정되는 것은 아니다.

네트워크 환경, 서버의 범위 요청 지원, 플레이어 동작, 파일의 프래그먼트 구조 등도 영향을 준다.

14. Fragmented MP4와 moof 박스

MP4에는 일반적인 비분할 파일 외에도 Fragmented MP4 구조가 존재한다.

Fragmented MP4에서는 미디어를 여러 프래그먼트로 나누어 저장할 수 있다.

개념적 구조

ftyp
moov
moof
mdat
moof
mdat
moof
mdat

위 구조는 단순화한 예시이며 실제 파일에는 다른 박스가 추가될 수 있다.

주요 프래그먼트 박스

박스역할
moofMovie Fragment Box
mfhd프래그먼트 헤더
trafTrack Fragment Box
tfhd트랙 프래그먼트 헤더
tfdt트랙 프래그먼트의 디코딩 시작 시간
trun샘플 실행 정보

프래그먼트 구조에서는 기존 stbl만으로 모든 미디어 샘플 위치를 해석할 수 없을 수 있다.

따라서 MP4 분석 도구를 만들 때는 일반 MP4와 Fragmented MP4의 차이를 고려해야 한다.

15. MP4 파일의 메타데이터 종류

MP4 파일에는 재생을 위한 구조적 메타데이터와 사용자 또는 응용 프로그램 관련 메타데이터가 포함될 수 있다.

구조적 메타데이터

  • 트랙 식별 정보
  • 재생 시간
  • 미디어 시간 척도
  • 샘플 위치
  • 샘플 크기
  • 코덱 구성 정보

사용자 및 응용 메타데이터

  • 제목
  • 작성자
  • 설명
  • 촬영 또는 생성 관련 정보
  • 위치 관련 정보
  • 응용 프로그램이 추가한 사용자 정의 정보

단, 모든 MP4 파일에 이러한 항목이 포함되는 것은 아니다.

또한 메타데이터의 존재와 값은 파일의 출처나 진위를 보장하지 않는다.

생성 시각이나 수정 시각 역시 도구를 통해 변경될 수 있으므로 분석의 단서로만 활용해야 한다.

16. Windows PowerShell 5.1로 MP4 헤더 확인하기

이번 실습에서는 MP4 파일의 처음 16바이트를 읽어 박스 크기와 유형을 확인한다.

① 실습 파일 준비

다음 위치에 MP4 파일이 있다고 가정한다.

C:\FileTest\sample.mp4

실제 실행 시에는 본인의 파일 경로로 변경한다.

② PowerShell 코드

$path = "C:\FileTest\sample.mp4"

$stream = [System.IO.File]::OpenRead($path)

try {
    $buffer = New-Object byte[] 16
    $count = $stream.Read($buffer, 0, 16)

    if ($count -lt 8) {
        throw "File is too short for a box header."
    }

    $size = (
        ([uint64]$buffer[0] -shl 24) -bor
        ([uint64]$buffer[1] -shl 16) -bor
        ([uint64]$buffer[2] -shl 8) -bor
        [uint64]$buffer[3]
    )

    $type = [System.Text.Encoding]::ASCII.GetString(
        $buffer, 4, 4
    )

    [PSCustomObject]@{
        HeaderHex = [BitConverter]::ToString(
            $buffer, 0, $count
        )
        FirstBoxSize = $size
        FirstBoxType = $type
    }
}
finally {
    $stream.Dispose()
}

③ 출력 예시

HeaderHex    : 00-00-00-20-66-74-79-70-...
FirstBoxSize : 32
FirstBoxType : ftyp

위 결과는 설명을 위한 예시다.

④ 코드 해석

처음 4바이트를 빅엔디언 정수로 읽어 박스 크기를 확인한다.

다음 4바이트는 ASCII 문자열로 변환해 박스 유형을 확인한다.

일반적인 MP4 파일에서는 첫 번째 박스 유형이 ftyp으로 표시될 수 있다.

⑤ 실습의 한계

이 코드는 첫 번째 박스 헤더를 확인하는 예제다.

64비트 확장 크기나 전체 박스 구조를 완전히 검증하지 않는다.

또한 첫 번째 박스 유형이 ftyp이라고 해서 파일 전체가 정상적인 MP4라고 판단할 수는 없다.

17. PowerShell 5.1로 MP4 최상위 박스 목록 확인하기

이번에는 파일 전체를 메모리에 올리지 않고 스트림을 이용해 최상위 박스의 위치와 크기를 확인한다.

일반적인 32비트 박스, 64비트 확장 크기, size=0 규칙을 처리한다.

① PowerShell 코드

$path = "C:\FileTest\sample.mp4"

function Read-ExactBytes {
    param(
        [System.IO.Stream]$Stream,
        [int]$Count
    )

    $buffer = New-Object byte[] $Count
    $offset = 0

    while ($offset -lt $Count) {
        $read = $Stream.Read(
            $buffer,
            $offset,
            $Count - $offset
        )

        if ($read -le 0) {
            throw "Unexpected end of file."
        }

        $offset += $read
    }

    return ,$buffer
}

function Read-BigEndianUInt32 {
    param([byte[]]$Bytes)

    return (
        ([uint64]$Bytes[0] -shl 24) -bor
        ([uint64]$Bytes[1] -shl 16) -bor
        ([uint64]$Bytes[2] -shl 8) -bor
        [uint64]$Bytes[3]
    )
}

function Read-BigEndianUInt64 {
    param([byte[]]$Bytes)

    $value = [uint64]0

    foreach ($b in $Bytes) {
        $value = ($value -shl 8) -bor [uint64]$b
    }

    return $value
}

$stream = [System.IO.File]::OpenRead($path)

try {
    while ($stream.Position -lt $stream.Length) {

        $start = $stream.Position
        $remaining = $stream.Length - $start

        if ($remaining -lt 8) {
            throw "Incomplete MP4 box header."
        }

        $sizeBytes = Read-ExactBytes $stream 4
        $typeBytes = Read-ExactBytes $stream 4

        $size32 = Read-BigEndianUInt32 $sizeBytes
        $type = [System.Text.Encoding]::ASCII.GetString(
            $typeBytes
        )

        $headerSize = [uint64]8

        if ($size32 -eq 1) {

            if (($stream.Length - $stream.Position) -lt 8) {
                throw "Incomplete extended box size."
            }

            $largeBytes = Read-ExactBytes $stream 8
            $boxSize = Read-BigEndianUInt64 $largeBytes
            $headerSize = [uint64]16
        }
        elseif ($size32 -eq 0) {
            $boxSize = [uint64]$remaining
        }
        else {
            $boxSize = [uint64]$size32
        }

        if ($type -eq "uuid") {

            if (($stream.Length - $stream.Position) -lt 16) {
                throw "Incomplete UUID box header."
            }

            $uuidBytes = Read-ExactBytes $stream 16
            $headerSize += 16
        }

        if ($boxSize -lt $headerSize) {
            throw "Box size is smaller than header."
        }

        if ($boxSize -gt [uint64]$remaining) {
            throw "Box exceeds file boundary."
        }

        [PSCustomObject]@{
            Offset = $start
            Type = $type
            Size = $boxSize
            HeaderSize = $headerSize
        }

        $next = [uint64]$start + $boxSize

        if ($next -gt [uint64][long]::MaxValue) {
            throw "Box offset exceeds supported range."
        }

        $stream.Position = [long]$next
    }
}
finally {
    $stream.Dispose()
}

② 출력 결과 예시

Offset  Type  Size      HeaderSize
------  ----  --------  ----------
0       ftyp  32        8
32      free  8         8
40      moov  2048      8
2088    mdat  1048576   8

위 결과는 예시이며 실제 파일의 박스 순서와 크기는 다를 수 있다.

③ 확인할 수 있는 내용

  • 최상위 박스 유형
  • 박스 시작 오프셋
  • 박스 전체 크기
  • 기본 헤더 및 확장 헤더 크기
  • 박스가 파일 경계를 초과하는지 여부

④ 코드의 한계

이 코드는 최상위 박스만 탐색한다.

moov 내부의 mvhd, trak, stbl 같은 하위 박스를 재귀적으로 분석하지 않는다.

또한 ftyp의 브랜드 값이나 mdat 내부의 코덱 데이터를 해석하지 않는다.

따라서 박스 목록이 정상적으로 출력되더라도 MP4 파일의 완전한 정상 여부가 검증된 것은 아니다.

18. PowerShell 5.1로 ftyp 브랜드 확인하기

이번에는 ftyp 박스의 주요 브랜드와 호환 브랜드를 읽어 보자.

이 예제는 파일 시작 부분에 일반적인 32비트 크기의 ftyp 박스가 있는 경우를 대상으로 한다.

① PowerShell 코드

$path = "C:\FileTest\sample.mp4"

$stream = [System.IO.File]::OpenRead($path)

try {
    $header = New-Object byte[] 8
    $read = $stream.Read($header, 0, 8)

    if ($read -ne 8) {
        throw "Incomplete file header."
    }

    $size = (
        ([uint64]$header[0] -shl 24) -bor
        ([uint64]$header[1] -shl 16) -bor
        ([uint64]$header[2] -shl 8) -bor
        [uint64]$header[3]
    )

    $type = [System.Text.Encoding]::ASCII.GetString(
        $header, 4, 4
    )

    if ($type -ne "ftyp") {
        throw "First box is not ftyp."
    }

    if ($size -lt 16 -or
        $size -gt [uint64]$stream.Length) {
        throw "Invalid ftyp box size."
    }

    if ($size -gt 1048576) {
        throw "ftyp exceeds the example size limit."
    }

    $payloadSize = [int]($size - 8)
    $payload = New-Object byte[] $payloadSize

    $offset = 0

    while ($offset -lt $payloadSize) {
        $n = $stream.Read(
            $payload,
            $offset,
            $payloadSize - $offset
        )

        if ($n -le 0) {
            throw "Incomplete ftyp payload."
        }

        $offset += $n
    }

    if ((($payloadSize - 8) % 4) -ne 0) {
        throw "Invalid compatible brand length."
    }

    $majorBrand = [System.Text.Encoding]::ASCII.GetString(
        $payload, 0, 4
    )

    $minorVersion = (
        ([uint64]$payload[4] -shl 24) -bor
        ([uint64]$payload[5] -shl 16) -bor
        ([uint64]$payload[6] -shl 8) -bor
        [uint64]$payload[7]
    )

    $brands = @()

    for ($i = 8; $i -lt $payload.Length; $i += 4) {
        $brands += [System.Text.Encoding]::ASCII.GetString(
            $payload, $i, 4
        )
    }

    [PSCustomObject]@{
        MajorBrand = $majorBrand
        MinorVersion = $minorVersion
        CompatibleBrands = ($brands -join ", ")
    }
}
finally {
    $stream.Dispose()
}

② 출력 예시

MajorBrand       : isom
MinorVersion     : 512
CompatibleBrands : isom, iso2, mp41

위 결과는 예시다.

③ 결과 해석

MajorBrand는 파일의 주요 브랜드를 나타낸다.

MinorVersion은 브랜드와 관련된 버전 정보를 담는다.

CompatibleBrands는 파일이 선언한 호환 브랜드 목록이다.

④ 실습 코드의 한계

이 코드는 ftyp의 브랜드 정보를 읽을 뿐, 실제 코덱이나 트랙 정보를 분석하지 않는다.

또한 64비트 확장 크기를 사용하는 ftyp이나 다른 배치의 파일은 처리하지 않는다.

따라서 브랜드 정보는 형식 분석의 단서로 활용해야 한다.

19. MP4 파일 손상 시 점검할 주요 항목

MP4 파일이 열리지 않거나 정상적으로 재생되지 않는 경우 다음 항목을 확인할 수 있다.

점검 항목확인 목적
ftyp파일 형식 및 호환 브랜드
Box Size박스 길이의 정상 범위
moov재생 구조 및 메타데이터
mvhd전체 시간 관련 정보
trak트랙 존재 여부
stbl샘플 테이블 구조
mdat미디어 데이터 영역
moof프래그먼트 구성
SHA-256기준 파일과 바이트 동일성 비교

대표적인 손상 상황

① ftyp 또는 시작 박스 구조 이상

파일 형식 식별에 문제가 생길 수 있다.

② 박스 크기 오류

박스에 기록된 크기가 실제 파일 경계를 벗어나면 파일이 잘렸거나 구조가 손상되었을 가능성이 있다.

③ moov 누락 또는 손상

일반적인 비분할 MP4에서는 재생에 필요한 구조 정보를 읽지 못할 수 있다.

④ mdat 데이터 손상

트랙 정보가 정상이어도 영상 또는 음성 재생 중 오류가 발생할 수 있다.

⑤ 샘플 테이블 이상

샘플 위치와 크기를 정확히 찾지 못하면 재생 오류가 발생할 수 있다.

이러한 증상은 손상의 단서가 될 수 있지만, 실제 원인을 확정하려면 추가 분석이 필요하다.

20. MP4 구조 검증과 SHA-256 무결성 검증

MP4 파일의 구조를 확인하는 것과 원본 파일의 동일성을 확인하는 것은 서로 다른 작업이다.

MP4 구조 검증

박스 유형, 길이, 배치, 트랙 구조 등을 확인한다.

메타데이터 검증

시간 정보, 트랙 구성, 브랜드 정보, 샘플 테이블 등을 확인한다.

SHA-256 검증

파일 전체의 바이트를 대상으로 해시값을 계산하고 신뢰할 수 있는 기준값과 비교한다.

PowerShell 코드

$path = "C:\FileTest\sample.mp4"

Get-FileHash -LiteralPath $path -Algorithm SHA256 |
    Format-List Algorithm, Hash, Path

검증 방식 비교

구분구조 분석메타데이터 분석SHA-256
확인 대상박스 구성시간·트랙·샘플 정보파일 전체
주요 목적형식 점검재생 구조 확인바이트 동일성 비교
미디어 디코딩 검증불가능불가능불가능
기준 파일과 동일성 비교불가능불가능가능
보안상 안전성 보장불가능불가능단독으로는 불가능

SHA-256 해시값이 신뢰할 수 있는 기준값과 일치하면 두 파일이 동일한 바이트 내용을 가질 가능성이 매우 높다고 판단할 수 있다.

그러나 해시값만으로 동영상의 내용이 안전하거나 저작권 문제가 없다는 사실을 확인할 수는 없다.

21. MP4 파일 분석 시 보안과 개인정보 주의사항

① 메타데이터에 포함된 개인정보

일부 MP4 파일에는 생성 시각, 장치 관련 정보, 위치 관련 정보 등이 포함될 수 있다.

파일을 공개하거나 공유하기 전에 불필요한 메타데이터가 있는지 확인하는 것이 좋다.

② 메타데이터의 신뢰성

생성 시각과 수정 시각 등은 프로그램을 통해 변경될 수 있다.

따라서 메타데이터만으로 실제 촬영 시각이나 제작자를 확정해서는 안 된다.

③ 비정상적인 박스 크기

출처가 불분명한 파일에는 비정상적인 박스 크기나 깊은 중첩 구조가 존재할 수 있다.

분석 도구는 파일 경계, 최대 처리 크기, 중첩 깊이 등을 제한하는 것이 바람직하다.

④ 원본 파일 보존

손상 분석이나 무결성 검증이 목적이라면 원본을 보존하고 복사본을 사용해야 한다.

동영상을 다시 저장하거나 메타데이터를 변경하면 해시값이 달라질 수 있다.

22. 자주 묻는 질문

Q1. MP4 파일의 Magic Number는 무엇인가요?

일반적인 MP4 파일은 시작 부분에 ftyp 박스를 포함한다. 다만 파일 형식과 브랜드 정보를 함께 확인해야 하므로 하나의 고정 바이트열만으로 모든 MP4를 식별할 수는 없다.

Q2. ftyp 박스는 어떤 역할을 하나요?

파일의 주요 브랜드, 버전 관련 값, 호환 브랜드 목록을 저장한다.

Q3. moov 박스에는 영상 데이터가 들어 있나요?

일반적으로 moov는 재생 구조와 메타데이터를 저장한다. 실제 미디어 샘플은 주로 mdat에 저장된다.

Q4. mdat 박스가 있으면 동영상이 정상인가요?

아니다. mdat가 존재해도 샘플 데이터가 손상되었거나 코덱 구성이 잘못되면 정상 재생되지 않을 수 있다.

Q5. MP4와 H.264는 같은 것인가요?

아니다. MP4는 컨테이너 형식이고 H.264는 영상 압축 방식이다.

Q6. moov가 파일 끝에 있으면 손상된 파일인가요?

반드시 그렇지는 않다. 일부 정상 MP4 파일에서도 moov가 뒤쪽에 배치될 수 있다.

Q7. Fragmented MP4는 일반 MP4와 무엇이 다른가요?

Fragmented MP4는 moof 등의 프래그먼트 정보를 사용해 미디어 데이터를 여러 구간으로 나누어 저장할 수 있다.

Q8. MP4 파일에도 PNG처럼 CRC-32가 있나요?

일반적인 MP4 박스 헤더에는 PNG 청크와 같은 공통 CRC-32 필드가 존재하지 않는다.

Q9. PowerShell만으로 MP4가 정상인지 확인할 수 있나요?

PowerShell로 박스 헤더와 일부 구조를 확인할 수 있지만, 전체 미디어 데이터의 디코딩 가능성까지 검증하려면 별도의 미디어 분석 및 디코딩 도구가 필요하다.

마무리

MP4 파일은 ISO Base Media File Format을 기반으로 하는 박스 구조의 멀티미디어 컨테이너다.

ftyp은 파일 형식과 호환성 정보를 제공하고, moov는 재생에 필요한 구조와 메타데이터를 저장하며, mdat는 실제 미디어 데이터를 담는다.

또한 mvhd, trak, mdia, stbl 등의 하위 박스는 시간 정보, 트랙 구성, 샘플 위치 등을 해석하는 데 사용된다.

하지만 MP4 파일 구조 분석은 컨테이너의 형식과 내부 배치를 확인하는 작업이지, 동영상의 정상 재생이나 원본 동일성, 보안상 안전성을 보장하는 과정은 아니다.

따라서 박스 구조 분석, 메타데이터 확인, 실제 디코딩 테스트, SHA-256 무결성 검증은 각각의 목적에 맞게 구분하여 활용해야 한다.


핵심 내용 3줄 요약

  • MP4는 ftyp, moov, mdat 등의 박스로 구성되는 멀티미디어 컨테이너 형식이다.
  • moov 내부의 트랙과 샘플 테이블은 미디어의 재생 시간과 데이터 위치를 해석하는 데 사용된다.
  • MP4 박스 구조가 정상이어도 미디어 데이터의 정상성이나 원본 동일성이 보장되는 것은 아니다.

공식 및 기술 참고자료

  1. ISO — ISO/IEC 14496-12:2026, ISO Base Media File Format
    https://www.iso.org/standard/85596.html
  2. ISO — ISO/IEC 14496-14:2020, MP4 File Format
    https://www.iso.org/standard/79110.html
  3. ISO — ISO Base Media File Format 온라인 표준 열람
    https://www.iso.org/obp/ui/
  4. Microsoft Learn — File.OpenRead Method
    https://learn.microsoft.com/dotnet/api/system.io.file.openread
  5. Microsoft Learn — FileStream.Read Method
    https://learn.microsoft.com/dotnet/api/system.io.filestream.read
  6. Microsoft Learn — Get-FileHash (PowerShell 5.1)
    https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/get-filehash?view=powershell-5.1

※ 본문의 PowerShell 코드는 MP4의 일부 박스 구조를 읽기 전용으로 확인하는 학습용 예시다. 실제 Windows PowerShell 5.1 환경에서의 실행 검증은 별도로 필요하며, 완전한 MP4 파서 또는 미디어 디코더를 대체하지 않는다.

디지털 파일 검증 연구소

디지털 파일 검증 연구소
디지털 파일 검증 연구소는 파일 형식, 확장자, 무결성 확인, 데이터 손상 예방 및 디지털 자료 관리 방법을 다루는 정보 사이트입니다. 파일 오류의 원인과 점검 절차를 이해하기 쉽게 정리하고, 공식 문서와 검증 가능한 자료를 바탕으로 실생활에 도움이 되는 해결 방법을 안내합니다.
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.