트랜스코딩(Transcoding)은 디지털 미디어 파일을 한 압축 형식에서 다른 형식으로 완전한 디코딩과 재인코딩을 통해 변환하는 프로세스입니다. 트랜스멀티플렉싱(컨테이너만 변경)과 달리 트랜스코딩은 코덱, 비트레이트, 해상도 및 압축 스트림의 기타 매개변수를 변경합니다. Apple AVFoundation documentation (2026)에 따르면 트랜스코딩은 다양한 장치 및 네트워크 조건에 콘텐츠를 적응시키는 데 사용됩니다.
핵심 요점
트랜스코딩은 미디어 파일을 한 압축 형식에서 다른 형식으로 변환하는 프로세스로, 소스 스트림을 중간 비압축 PCM 형식으로 완전히 디코딩한 후 새 매개변수로 인코딩합니다. 소스 파일이 10Mbps 비트레이트의 H.264 코덱을 사용하고 출력에 3Mbps 비트레이트의 H.265가 필요한 경우 — 이것이 트랜스코딩입니다.
트랜스코딩은 단순한 재패키징(트랜스멀티플렉싱)과 다릅니다. 트랜스멀티플렉싱에서는 컨테이너만 변경되고(예: MP4에서 MKV) 압축 비트스트림은 변경되지 않습니다. 트랜스코딩에는 계산 비용이 많이 드는 작업이 포함됩니다: 각 프레임 디코딩, 필터 적용(크기 조정, 색상 보정, 자르기), 새 매개변수로 재인코딩. 이로 인해 트랜스코딩은 미디어 작업 시 가장 리소스 집약적인 작업 중 하나가 됩니다.
트랜스코딩은 다양한 작업에 사용됩니다: 대역폭 제한에 맞춘 비디오 적응, 대상 기기의 하드웨어 디코딩 지원 형식으로 변환, HLS/DASH 스트리밍용 여러 버전 생성, 별도 파일로 오디오 트랙 추출. OTT 서비스(Netflix, YouTube, Twitch)는 업로드된 각 파일을 다양한 비트레이트, 해상도 및 코덱의 수십 가지 변형으로 트랜스코딩하여 수백만 사용자에게 적응형 스트리밍을 제공합니다.
트랜스코딩 프로세스는 디코딩, 처리, 인코딩의 세 가지 주요 단계로 구성됩니다. 각 단계는 가용성과 필요한 성능에 따라 CPU 또는 GPU/하드웨어 블록에서 실행할 수 있습니다.
첫 번째 단계는 소스 스트림 디코딩입니다. 소스 파일은 컨테이너(MP4, MOV, MKV)에서 읽힌 후 압축된 비디오 패킷이 디코더로 전송됩니다. 디코딩은 하드웨어 기반(코덱이 지원되는 경우) 또는 FFmpeg를 통한 소프트웨어 기반일 수 있습니다. 디코딩 출력은 YUV420 또는 BGRA 형식의 비압축 프레임입니다 — 트랜스코딩이 단순한 재다중화와 다른 지점입니다.
두 번째 단계는 필터링 및 처리입니다. 디코딩된 프레임은 필터 체인을 통과합니다: 대상 해상도로 크기 조정, 프레임 속도 변경, 색상 보정, 텍스트 또는 그래픽 오버레이. FFmpeg 필터 체인은 각 필터가 별도의 처리 모듈인 그래프로 구축됩니다. 예를 들어 scale=1280:720 필터는 해상도를 변경하고, fps=30은 프레임 속도를 변경하며, yadif는 디인터레이싱을 수행합니다. 모든 작업은 비압축 프레임에서 수행되므로 두 번째 단계가 가장 리소스 집약적입니다.
세 번째 단계는 대상 형식으로 인코딩입니다. 처리된 프레임은 인코더에 공급되어 대상 코덱 알고리즘에 따라 압축됩니다. 인코더는 하드웨어 기반(iOS의 VideoToolbox, Android의 MediaCodec) 또는 소프트웨어 기반(libx264, libx265)일 수 있습니다. 인코딩 매개변수: 일정한 품질을 위한 CRF(Constant Rate Factor), CBR/VBR용 비트레이트, 대상 기기와의 호환성을 위한 프로필 및 레벨.
// FFmpeg 트랜스코딩 파이프라인 다이어그램
AVFormatContext *inputCtx, *outputCtx;
AVCodecContext *decoderCtx, *encoderCtx;
AVFrame *frame = av_frame_alloc();
AVPacket packet;
while (av_read_frame(inputCtx, &packet) >= 0) {
// 1. 디코드
avcodec_send_packet(decoderCtx, &packet);
avcodec_receive_frame(decoderCtx, frame);
// 2. 필터(스케일 + fps 변경)
sws_scale(swsCtx, frame->data, frame->linesize,
0, frame->height, scaledFrame->data,
scaledFrame->linesize);
// 3. 인코드
avcodec_send_frame(encoderCtx, scaledFrame);
avcodec_receive_packet(encoderCtx, &outPacket);
av_interleaved_write_frame(outputCtx, &outPacket);
}
위 파이프라인은 클래식 트랜스코딩 사이클을 보여줍니다. av_read_frame 함수는 입력 파일에서 압축 패킷을 읽고, avcodec_send_packet은 이를 프레임으로 디코딩하며, sws_scale은 크기 조정을 수행하고, avcodec_send_frame은 처리된 프레임을 출력 형식으로 인코딩합니다. 이 3단계 사이클은 인코더 설정에 따라 각 프레임 또는 프레임 그룹(GOP)마다 반복됩니다.
트랜스코딩과 트랜스멀티플렉싱의 차이는 미디어 엔지니어링에서 가장 흔한 혼란 지점 중 하나입니다. 이 차이를 이해하는 것은 올바른 미디어 처리 전략을 선택하는 데 중요합니다.
| 매개변수 | 트랜스코딩 | 트랜스멀티플렉싱 |
|---|---|---|
| 변경 사항 | 코덱, 비트레이트, 해상도 | 컨테이너, 메타데이터 |
| 계산 부하 | 높음(디코딩 + 인코딩) | 최소(패킷 복사) |
| 품질 | 저하 가능(세대 손실) | 무손실 |
| 실행 시간 | 긴 동영상의 경우 수분~수시간 | 수초~수분 |
| 응용 | 형식 적응, 압축 | 호환성을 위한 컨테이너 변경 |
트랜스멀티플렉싱은 디코딩 및 재인코딩 없이 압축 스트림을 다른 컨테이너로 재패키징하는 것입니다. 비디오가 이미 MP4 컨테이너에서 H.265 코덱으로 압축되어 있고 MOV 또는 MKV 컨테이너에 넣어야 하는 경우 — 트랜스멀티플렉싱은 단순히 비트스트림 패킷을 한 컨테이너에서 다른 컨테이너로 복사합니다. 품질에 영향을 미치지 않으며 프레임 디코딩이 필요 없어 처리 시간이 최소화됩니다. FFmpeg는 -codec copy 플래그로 트랜스멀티플렉싱을 수행합니다.
트랜스코딩은 미디어 스트림을 완전히 디코딩하고 재압축합니다. 비디오가 트랜스코딩을 거칠 때마다 세대 손실(generation loss)이 발생할 수 있습니다 — 반복된 손실 압축으로 인한 품질의 약간의 저하입니다. 동일한 비트레이트에서도 트랜스코딩의 3세대는 일반적으로 1세대보다 품질이 낮습니다. 이것이 전문가들이 마스터 사본을 비압축 또는 최소 압축 형식(ProRes, DNxHR)으로 저장하고 배송용 최종 버전만 트랜스코딩할 것을 권장하는 이유입니다.
트랜스코딩 도구의 선택은 플랫폼, 성능 요구 사항 및 사용 사례에 따라 달라집니다. 모바일 개발을 위해 네이티브 API와 크로스 플랫폼 라이브러리를 모두 사용할 수 있습니다.
FFmpeg는 모든 플랫폼에서 트랜스코딩의 사실상 표준입니다. FFmpeg 명령줄은 코덱 변경, 비트레이트 조정, 자르기, 연결, 필터 적용 등 거의 모든 변환을 수행할 수 있습니다. 모바일 애플리케이션의 경우 FFmpeg는 libavformat, libavcodec 및 libavfilter 라이브러리를 통해 통합됩니다. 일반적인 트랜스코딩 명령의 예: ffmpeg -i input.mp4 -c:v libx265 -crf 23 -c:a aac -b:a 128k output.mp4.
iOS에서 트랜스코딩은 AVAssetWriter와 AVAssetReader를 통해 수행됩니다. AVAssetReader는 비압축 프레임을 읽어 소스 파일을 디코딩하고 AVAssetWriter는 이를 대상 형식으로 인코딩합니다. 이 접근 방식은 자동으로 VideoToolbox 하드웨어 인코더를 사용하여 최대 성능을 보장합니다. Android에서는 MediaCodec을 MediaExtractor 및 MediaMuxer와 함께 사용하여 유사한 기능을 사용할 수 있습니다 — MediaExtractor는 압축 패킷을 추출하고 MediaCodec은 디코딩 및 인코딩하며 MediaMuxer는 결과를 기록합니다.
프로덕션 환경에서 서버 측 트랜스코딩을 위해 클라우드 서비스가 사용됩니다: AWS Elemental MediaConvert, Azure Media Services, Google Transcoder API. 이러한 서비스는 부하에 따라 자동으로 확장되고 모든 인기 형식을 지원하며 적응형 스트리밍(HLS, DASH)을 위해 단일 입력 파일을 수십 개의 출력 변형으로 트랜스코딩할 수 있습니다. 모바일 애플리케이션의 경우 클라우드 트랜스코딩이 최적의 솔루션입니다. 사용자 기기에 부담을 주지 않고 비동기 콘텐츠 준비가 가능하기 때문입니다.
하드웨어 가속 및 주요 품질 매개변수 구성을 사용하여 모바일 플랫폼에서의 실제 트랜스코딩 예제를 살펴보겠습니다.
import AVFoundation
func transcodeVideo(sourceURL: URL, destURL: URL) {
let asset = AVAsset(url: sourceURL)
let preset = AVAssetExportPresetHEVCHighestQuality
AVAssetExportSession(asset: asset, presetName: preset)?
.exportAsynchronously {
switch assetExportSession?.status {
case .completed:
print("트랜스코딩 완료")
case .failed:
print("오류: " + assetExportSession.error.localizedDescription)
default:
break
}
}
// AVAssetReader + AVAssetWriter를 사용한 수동 트랜스코딩
let reader = try AVAssetReader(asset: asset)
let writer = try AVAssetWriter(url: destURL,
fileType: .mp4)
let outputSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.hevc,
AVVideoWidthKey: 1920,
AVVideoHeightKey: 1080,
AVVideoCompressionPropertiesKey: [
AVVideoAverageBitRateKey: 4_000_000,
AVVideoProfileLevelKey: AVVideoProfileLevelH265Main10
]
]
let adaptor = AVAssetWriterInput(
mediaType: .video,
outputSettings: outputSettings
)
writer.add(adaptor)
}
예제는 iOS에서 트랜스코딩의 두 가지 접근 방식을 보여줍니다. AVAssetExportSession은 품질 사전 설정(H.265용 HEVCHighestQuality)이 있는 간단한 방법입니다. AVAssetReader + AVAssetWriter를 통한 수동 파이프라인은 비트레이트, 프로필, 레벨 등 매개변수를 완전히 제어할 수 있습니다. AVVideoProfileLevelH265Main10 매개변수는 10비트 색상 깊이의 HDR 프로필 Main10을 활성화하며, 이는 최신 HDR 콘텐츠에 중요합니다.
class Transcoder(private val context: Context) {
fun transcodeToHevc(inputUri: Uri, outputFile: File) {
val extractor = MediaExtractor()
extractor.setDataSource(context, inputUri, null)
val trackFormat = extractor.getTrackFormat(videoTrackIndex)
val mime = trackFormat.getString(MediaFormat.KEY_MIME)
val decoder = MediaCodec.createDecoderByType(mime!!)
val encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC)
val outputFormat = MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_HEVC, 1920, 1080
).apply {
setInteger(MediaFormat.KEY_BIT_RATE, 4_000_000)
setInteger(MediaFormat.KEY_FRAME_RATE, 30)
setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2)
}
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
encoder.start()
}
}
Android 코드는 MediaExtractor — MediaCodec 디코더 — MediaCodec 인코더 — MediaMuxer의 파이프라인을 만듭니다. MediaExtractor는 입력 파일에서 코덱 유형을 확인하고 해당 디코더를 선택합니다. 인코더는 H.265(HEVC)용으로 4Mbps 비트레이트와 2초 키프레임 간격으로 구성되어 스트리밍에 최적입니다. 중요: MediaCodec 인코더는 동기식으로 작동하므로 실시간 트랜스코딩을 위해서는 각 프레임의 올바른 PTS 타임스탬프 처리가 포함된 루프를 구현해야 합니다.
모바일 기기에서의 트랜스코딩은 제한된 CPU, GPU 리소스 및 열적 제약으로 인해 신중한 최적화가 필요한 작업입니다. 몇 가지 전략을 통해 효율적으로 트랜스코딩을 수행할 수 있습니다.
핵심 성능 요소는 하드웨어 인코더입니다. iOS에서 VideoToolbox는 소프트웨어 libx264보다 5~10배 빠른 속도로 하드웨어 H.264 및 H.265 인코딩을 제공합니다. Android에서 MediaCodec은 사용 가능한 경우 하드웨어 OMX 구성 요소를 사용합니다. 하드웨어 인코딩을 활성화하면 플래그십 기기에서 10분 동영상의 트랜스코딩 시간이 30~40분(소프트웨어)에서 3~5분(하드웨어)으로 단축됩니다.
모바일 트랜스코딩의 경우 품질, 크기 및 처리 시간 간의 균형이 중요합니다. 모바일 기기에서 H.265의 경우 30FPS 1080p 동영상에 4~8Mbps 비트레이트가 권장됩니다. libx265의 CRF 모드(Constant Rate Factor)는 품질을 직접 설정할 수 있으며 23~28은 적당한 파일 크기에서 좋은 시각적 품질을 제공합니다. 하드웨어 인코더의 경우 CRF가 하드웨어에서 지원되지 않으므로 대상 비트레이트로 CBR 모드를 사용하십시오.
모바일 기기에서 지속적인 트랜스코딩은 상당한 발열을 유발합니다. 4K 동영상의 5~7분 집중 인코딩 후 프로세서 온도가 50~55도에 도달할 수 있으며 그 후 스로틀링이 시작됩니다. 해결책은 일시 중지를 포함한 트랜스코딩 또는 프레임 속도를 30FPS로 낮추는 것입니다. 애플리케이션에 일괄 트랜스코딩이 필요한 경우(예: 비디오 편집기) 냉각 간격을 두고 2~3분 배치로 처리하는 것이 좋습니다. 프로덕션 시나리오의 경우 트랜스코딩을 서버 측으로 오프로드하고 클라우드 서비스를 사용하는 것이 최적입니다.
자주 묻는 질문
인코딩(encoding)은 원시 비압축 데이터를 대상 코덱으로 압축하는 것입니다. 트랜스코딩은 디코딩과 인코딩을 모두 포함합니다: 먼저 기존 압축 스트림을 디코딩한 다음 다시 인코딩합니다. 단순 인코딩은 입력으로 비압축 데이터(예: 카메라)를 받는 반면 트랜스코딩은 이미 압축된 파일을 받습니다.
최대 호환성을 위해 — H.264. 더 나은 압축을 위해 — H.265(HEVC). 기기가 하드웨어 H.265 인코딩(iPhone 8+, Snapdragon 845+ 탑재 Android)을 지원하는 경우 동일한 품질에서 파일 크기가 절반으로 줄어듭니다. AV1 인코딩은 모바일 기기에서 하드웨어 가속을 사용하더라도 아직 너무 느립니다.
엄밀히 말해 손실 코덱 간 전환 시 무손실 트랜스코딩은 불가능합니다. 두 코덱 모두 손실이 있는 경우 트랜스코딩 세대가 거듭될수록 품질이 저하됩니다. 무손실 트랜스코딩은 무손실 형식(FFV1, H.264 Lossless) 간 또는 재인코딩 없는 컨테이너 변경(트랜스멀티플렉싱) 시에만 가능합니다.
네, 하드웨어 디코더와 인코더를 사용하고 대상 해상도가 1080p를 초과하지 않는 경우 가능합니다. VideoToolbox(iOS) 또는 MediaCodec(Android)가 있는 기기에서 실시간 H.264→H.265 트랜스코딩은 1~3초 지연으로 가능합니다. 4K 실시간 처리에는 Apple A17 Pro, Snapdragon 8 Gen 2 이상의 강력한 SoC가 필요합니다.
손실 트랜스코딩은 압축 아티팩트를 축적합니다. 소스 파일이 이미 심하게 압축된 경우(1080p에서 2~3Mbps 비트레이트) 재압축으로 손실이 두 배가 됩니다. 권장사항은 높은 비트레이트(20+Mbps)의 마스터 사본에서만 트랜스코딩하고 최소 손실을 위해 CRF 18~23을 사용하는 것입니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.