Transcode Video on iOS with AVFoundation and FFmpeg

This article provides a practical guide on how to transcode video files within a custom iOS application. You will learn how to use Apple’s native AVFoundation framework for efficient, hardware-accelerated encoding, how to integrate the open-source FFmpeg library for broader format support, and how to execute transcoding tasks using both technologies.

Native Video Transcoding with AVFoundation

For most iOS applications, Apple’s native AVFoundation framework is the preferred choice for video transcoding. It utilizes the device’s hardware encoder, which maximizes performance and minimizes battery consumption.

Method 1: Using AVAssetExportSession (Simple)

The simplest way to transcode a video in iOS is by using AVAssetExportSession. This is ideal for standard tasks like converting a MOV file to an MP4 or reducing video resolution.

import AVFoundation

func transcodeVideo(inputURL: URL, outputURL: URL, completion: @escaping (Bool) -> Void) {
    let asset = AVAsset(url: inputURL)
    
    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {
        completion(false)
        return
    }
    
    exportSession.outputURL = outputURL
    exportSession.outputFileType = .mp4
    exportSession.shouldOptimizeForNetworkUse = true
    
    exportSession.exportAsynchronously {
        switch exportSession.status {
        case .completed:
            completion(true)
        case .failed, .cancelled:
            print("Error: \(String( some: exportSession.error?.localizedDescription))")
            completion(false)
        default:
            completion(false)
        }
    }
}

Method 2: Using AVAssetReader and AVAssetWriter (Advanced)

If you need precise control over the transcoding process—such as altering video frames, applying custom bitrates, or modifying audio tracks—you must use AVAssetReader to decode the video and AVAssetWriter to encode it.

  1. AVAssetReader: Reads the raw pixel buffers (YUV/RGB) and audio samples from the source file.
  2. AVAssetWriter: Encodes the raw samples into the target format (e.g., H.264/HEVC) and writes them to the output file.

Transcoding with FFmpeg on iOS

While AVFoundation is highly optimized, it only supports Apple-approved containers and codecs (like MP4, MOV, M4V, H.264, and HEVC). If your application needs to handle containers like MKV, AVI, or WebM, or use codecs like VP9 or AV1, you must integrate FFmpeg.

Step 1: Integrating FFmpeg into your iOS Project

You can integrate FFmpeg into your iOS project using pre-built libraries. The most common and maintained option is FFmpegKit.

You can add FFmpegKit to your project using CocoaPods:

pod 'ffmpeg-kit-ios-full', '~> 6.0'

Or via Swift Package Manager (SPM) by adding the repository URL for FFmpegKit.

Step 2: Executing an FFmpeg Transcoding Command

Once integrated, you can run FFmpeg commands asynchronously in your Swift code. FFmpegKit provides a wrapper to execute standard command-line instructions.

Here is how to transcode an input video to an optimized H.264 MP4 file using FFmpeg:

import ffmpeg_kit_ios

func transcodeWithFFmpeg(inputPath: String, outputPath: String) {
    // FFmpeg command to convert input to H.264 video and AAC audio
    let command = "-i \(inputPath) -c:v libx264 -crf 23 -preset ultrafast -c:a aac \(outputPath)"
    
    FFmpegKit.executeAsync(command) { session in
        guard let session = session else { return }
        let returnCode = session.getReturnCode()
        
        if ReturnCode.isSuccess(returnCode) {
            print("Transcoding completed successfully.")
        } else if ReturnCode.isCancel(returnCode) {
            print("Transcoding was cancelled.")
        } else {
            print("Transcoding failed.")
        }
    }
}

Choosing Between AVFoundation and FFmpeg

Feature AVFoundation FFmpeg
Performance Extremely fast (Hardware Accelerated) Slower (Mostly Software-based on iOS)
Battery Consumption Low High
Format Support Limited (MP4, MOV, M4V, H.264, HEVC) Universal (MKV, AVI, WEBM, VP9, etc.)
App Size Impact Zero (Built-in iOS SDK) Significant (Adds 30MB - 100MB+ to binary)

For standard MP4/HEVC transcoding, always use AVFoundation to preserve battery life and performance. Utilize FFmpeg only when you require compatibility with non-standard file formats or advanced filtering options not natively supported by iOS.