Faststart MP4: moov atom을 파일 앞으로 옮기는 방법
faststart MP4는 인덱스인 moov atom이 파일 앞부분에 있는 MP4입니다. FFmpeg는 -movflags +faststart를 주면 두 번째 패스에서 인덱스를 앞으로 옮깁니다.

faststart MP4는 인덱스인 moov atom이 파일 끝이 아니라 앞부분에 있는 MP4입니다. FFmpeg는 보통 인덱스를 파일 끝에 쓰지만, -movflags +faststart를 더하면 moov atom을 파일 앞으로 옮기는 두 번째 패스를 실행합니다. 그래서 파일을 처음부터 읽는 플레이어가 인덱스를 먼저 받습니다.
FFmpeg 관련 내용은 포맷과 ffmpeg 문서에서, YouTube 관련 내용은 업로드 인코딩 설정에서, Sume 관련 내용은 영상 트림, 영상 필터, Timeline 1.0 문서에서 가져왔으며, 모두 2026-09-28에 확인했습니다. 현재 동작이라고 설명한 내용은 Sume의 코드에서 확인한 것입니다.
moov atom은 무엇이고, 위치가 왜 중요한가요?
MP4는 미디어 데이터와 인덱스를 따로 둡니다. FFmpeg 문서에 따르면 일반적인 MOV/MP4 파일은 모든 패킷에 대한 메타데이터를 moov atom이라는 한곳에 저장하며, 이 atom은 보통 파일 끝에 쓰이지만 더 나은 재생을 위해 파일 앞으로 옮길 수 있습니다.
플레이어가 파일 안에서 각 프레임을 찾으려면 이 인덱스가 필요합니다. 인덱스가 끝에 있으면 파일을 스트리밍하는 플레이어는 재생을 시작하기 전에 파일 끝부터 가져와야 하지만, faststart 파일에서는 인덱스가 미디어보다 먼저 첫 바이트들에 담겨 도착합니다. YouTube의 권장 업로드 설정은 MP4 항목에 moov atom을 파일 앞에 둘 것(Fast Start)을 적어 두었습니다.
FFmpeg로 MP4를 faststart로 만들려면 어떻게 하나요?
MP4를 쓰는 명령에 이 플래그를 넣으세요. 이미 있는 파일이라면 플래그를 붙여 스트림을 새 파일로 복사하세요. 아무것도 재인코딩하지 않고 인덱스만 옮깁니다.
-c copy는 스트림 카피입니다. FFmpeg 문서에 따르면 디코딩도 인코딩도 하지 않으므로 화질 손실이 없습니다.- 인코딩할 때는 별도의 두 번째 작업을 실행하지 말고 인코딩 명령에
-movflags +faststart를 더하세요. - FFmpeg 문서에 따르면 두 번째 패스는 시간이 걸릴 수 있고 조각화된(fragmented) 출력 같은 여러 상황에서는 동작하지 않으며, 그래서 기본으로 켜져 있지 않습니다.
- 같은 문서는 인덱스를 옮기는 또 다른 방법으로 별도 도구인
qt-faststart를 소개합니다. - MP4 먹서(muxer)의
moov_size옵션은 moov atom을 파일 끝에 두는 대신 파일 앞부분에 그 공간을 예약합니다. 예약한 공간이 너무 작으면 먹싱이 실패합니다.
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4faststart로 열리지 않는 MP4를 고칠 수 있나요?
아니요, 고칠 수 없습니다. faststart는 이미 있는 인덱스를 옮길 뿐입니다. FFmpeg 문서에 따르면 일반적인 MOV/MP4는 제대로 마무리되지 않으면 디코딩할 수 없으며, 인덱스를 쓰기 전에 끊긴 파일에는 옮길 인덱스가 없습니다. 같은 문서는 이와 대비되는 조각화된 MP4(fragmented MP4)도 설명합니다. 조각화된 MP4는 패킷과 그 메타데이터를 함께 저장하므로 쓰기가 중간에 끊겨도 디코딩할 수 있습니다. 문서가 꼽는 단점은 다른 애플리케이션과의 호환성이 떨어진다는 점입니다.
Sume에서 트림하거나 렌더링한 MP4 파일은 faststart인가요?
네, 다음 네 가지 도구에서 나온 파일은 그렇습니다. 현재 코드에서는 영상 트림, 영상 필터, 타임라인 합성, Timeline 렌더가 재인코딩 여부와 관계없이 모두 -movflags +faststart를 붙여 FFmpeg를 실행합니다.
| Sume 도구 | 영상 스트림 | faststart 적용 |
|---|---|---|
영상 트림, precision: "keyframe" | 스트림 카피, 재인코딩 없음 | 예 |
영상 트림, precision: "exact"(기본값) | libx264로 재인코딩 | 예 |
| 영상 필터 | libx264로 재인코딩 | 예 |
| 타임라인 합성 | libx264로 재인코딩 | 예 |
| Timeline 1.0 렌더 | libx264로 재인코딩 | 예 |
Sume에 호스팅된 MP4의 faststart 사본은 어떻게 만드나요?
다른 Job의 출력처럼 이 네 가지 도구에서 나오지 않은 Sume 호스팅 MP4라면, precision: "keyframe"으로 전체 길이를 트림하세요. start는 0, end는 클립 길이로 지정합니다. 문서는 keyframe 트림을 스트림 카피로 설명하고, 현재 코드에서는 이 트림도 +faststart를 붙여 파일을 쓰므로 결과는 인덱스가 앞에 놓인 같은 영상입니다. 소스는 그대로이고, 새 파일은 GET /v1/jobs/:id/result의 video_url로 돌아옵니다.
video_url은 이전 Sume Job의 출력처럼 워크스페이스에 있는media.sume.com아티팩트나 에셋이어야 합니다. 이 규칙은 엔드포인트별로 받는 URL에서 설명합니다.- 트림은 최대 1,800초 길이의 소스를 읽지만 Job당 최대 900초까지만 쓰므로, 전체 길이 복사는 900초 이하 클립에서만 됩니다. 현재 코드에서는 300 MiB가 넘는 소스 파일이
source_too_large로 거부됩니다. 소스 길이를 넘는end는 소스 끝으로 제한되고trim_clamped_to_source경고가 붙습니다. - 트림은 Job당 과금되며 기본적으로 5.5% 에이전트 수수료가 더해집니다. 문서는 요율을
GET /v1/catalog에서 확인하라고 안내합니다.
curl -X POST https://api.sume.com/v1/video-trim \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: faststart-copy-001" \
-d '{
"video_url": "https://media.sume.com/artifacts/artf_demo/clip.mp4",
"start": 0,
"end": 42,
"precision": "keyframe"
}'출처
관련 글
개발자 카테고리의 다른 글
- Retry-After 헤더: 429·503 후 얼마나 기다려야 하나요?
Retry-After는 재시도 전에 얼마나 기다릴지 클라이언트에 알려 주는 헤더로, 초 단위 숫자나 HTTP 날짜이며 429나 503과 함께 옵니다. 읽는 법과 대응 방법을 정리했습니다.
- 재시도 가능한 HTTP 상태 코드: 어떤 오류를 재시도해야 하나요?
네트워크 오류, 408, 429, 5xx는 백오프하며 재시도하고, 그 밖의 4xx는 대부분 재시도하지 마세요. POST는 멱등성 키가 있을 때만 재시도하고, API의 재시도 플래그를 읽으세요.
- Java 음성 인식 API: HttpClient로 오디오를 텍스트로
JDK HttpClient와 Jackson으로 Java에서 음성 인식 API를 호출하세요. 오디오 URL을 POST하고 Job을 폴링한 뒤, 전사문과 단어별 시간을 읽습니다.
- Stateless MCP 서버: 세션·Mcp-Session-Id·핸들
Stateless MCP 서버는 요청 사이에 세션을 유지하지 않습니다. Mcp-Session-Id의 역할, 2026-07-28 개정판이 없앤 것, 상태를 대신 어디에 두는지 정리합니다.
작성자 Sume