Skip to content

Swift 6.2+ bindings for FFmpeg with cross-platform artifact bundle support

Notifications You must be signed in to change notification settings

wendylabsinc/ffmpeg-swift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ffmpeg-swift

Swift 6.2 Platforms License macOS Linux Windows Documentation

A type-safe, memory-safe Swift package that distributes FFmpeg 7.1 as pre-built static libraries via SE-0482 artifact bundles. Any Swift project can import FFmpeg and use FFmpeg on Apple platforms, Linux, Windows, and Android without installing FFmpeg system-wide.

Platform Support

Platform Architecture Status
macOS arm64 (Apple Silicon) Supported
macOS x86_64 (Intel) Supported
iOS arm64 Supported
tvOS arm64 Supported
watchOS arm64 Supported
Linux x86_64 Supported
Linux aarch64 Supported
Android arm64 Supported
Windows x86_64 Supported
Windows arm64 Supported

Installation

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/wendylabsinc/ffmpeg-swift.git", from: "0.0.3"),
]

Then add "FFmpeg" as a dependency of your target:

.target(name: "MyApp", dependencies: [
    .product(name: "FFmpeg", package: "ffmpeg-swift"),
])

Local Development

Build a host-architecture artifact bundle and tell SwiftPM to use it locally:

./Scripts/build-ffmpeg.sh
FFMPEG_SWIFT_USE_LOCAL_ARTIFACT=1 swift build

Notes:

  • The local bundle is expected at CFFmpeg.artifactbundle/ in the repo root.
  • Remove FFMPEG_SWIFT_USE_LOCAL_ARTIFACT to use the published artifact bundle again.

Architecture

┌─────────────────────────────┐
│  FFmpeg  (Swift module)     │  Ergonomic, type-safe, memory-safe Swift API
├─────────────────────────────┤
│  CFFmpegShim  (C target)    │  Bridges C macros → Swift-importable constants/functions
├─────────────────────────────┤
│  CFFmpeg  (binaryTarget)    │  SE-0482 artifact bundle with static libs + headers
└─────────────────────────────┘

Why three layers? FFmpeg uses complex C macros (AVERROR(EAGAIN), AV_NOPTS_VALUE, av_err2str) that Swift cannot import. The shim layer exposes these as static const / static inline functions.

Quick Start

import FFmpeg

// Check FFmpeg version
print(FFmpegLibrary.avutilVersion) // "7.1"

// Discover codecs
let codec = try Codec.findDecoder(name: "h264")

// Allocate frames and packets (move-only, auto-freed)
var frame = Frame()
frame.width = 1920
frame.height = 1080

var packet = Packet()

Decode a Video File

let reader = try MediaReader(url: "input.mp4")

print("Duration: \(reader.durationSeconds ?? 0)s")
print("Streams: \(reader.streams.count)")

for try await frame in reader.videoFrames() {
    print("Frame: \(frame.width)x\(frame.height) pts=\(frame.pts)")
}

Manual Decode Loop

let fmt = try FormatContext.openInput(url: "input.mp4")
let videoIdx = try fmt.findBestStream(type: .video)
let stream = fmt.stream(at: Int(videoIdx))

let ctx = try stream.makeDecoderContext()

var packet = Packet()
var frame = Frame()

while try fmt.readFrame(into: &packet) {
    guard packet.streamIndex == videoIdx else {
        packet.unref()
        continue
    }
    _ = try ctx.sendPacket(packet)
    packet.unref()

    while case .success = try ctx.receiveFrame(into: &frame) {
        // Process frame...
        frame.unref()
    }
}

Examples

Runnable examples live in Examples/:

swift run example-inspect
swift run example-decode
swift run example-filter
swift run example-encode
swift run example-adts
swift run example-mp3

See Examples/README.md for arguments and details.

Video Scaling

let scaler = try VideoScaler(
    srcWidth: 1920, srcHeight: 1080, srcFormat: .yuv420p,
    dstWidth: 640, dstHeight: 360, dstFormat: .rgb24
)

var dst = Frame()
dst.width = 640
dst.height = 360
dst.pixelFormat = .rgb24
try dst.allocateBuffers()

try scaler.scale(source: srcFrame, into: &dst)

Filter Graphs

let graph = try FilterGraph()
try graph.configureVideo(
    filterDescription: "scale=320:240,hflip",
    width: 1920, height: 1080,
    pixelFormat: .yuv420p,
    timeBase: Rational(numerator: 1, denominator: 30)
)

try graph.push(frame: inputFrame)
var filtered = Frame()
while case .success = try graph.pull(into: &filtered) {
    // Process filtered frame...
    filtered.unref()
}

API Overview

Type Description
Frame ~Copyable wrapper around AVFrame*, auto-freed
Packet ~Copyable wrapper around AVPacket*, auto-freed
FormatContext Demuxing (input) and muxing (output)
CodecContext Encoding and decoding with CodecResult enum
Codec Codec discovery by name or ID
VideoScaler ~Copyable SwsContext wrapper, uses sws_scale_frame
AudioResampler ~Copyable SwrContext wrapper
FilterGraph String-based filter graph configuration
MediaReader High-level async decoded frame streams
MediaWriter High-level frame encoder + muxer
FFmpegError Type-safe error with well-known static properties
Rational AVRational wrapper with arithmetic
AVDictionaryWrapper Safe dictionary for FFmpeg options
OwnedFrame Copyable/Sendable frame wrapper for async streams

Building the Artifact Bundle

To build the FFmpeg static libraries from source:

# Build for current platform only
./Scripts/build-ffmpeg.sh

# Build for specific platforms
./Scripts/build-ffmpeg.sh --platforms macos-arm64,macos-x86_64

# Build all platforms (Linux via Docker when on macOS)
./Scripts/build-ffmpeg.sh --platforms macos-arm64,macos-x86_64,linux-x86_64,linux-aarch64

# Build and zip for release
./Scripts/build-ffmpeg.sh --zip

The script downloads FFmpeg 7.1 source, builds static libraries, merges them into a single libcffmpeg.a, and assembles the SE-0482 artifact bundle.

Included FFmpeg Libraries

  • libavutil
  • libavcodec
  • libavformat
  • libavfilter
  • libswscale
  • libswresample
  • libpostproc

Requirements

  • Swift 6.2+ (SE-0482 static library artifact bundles require Swift 6.2+)
  • macOS 14+, iOS 16+, tvOS 16+, watchOS 9+, or Linux

License

FFmpeg is licensed under LGPL 2.1+ / GPL 2+ depending on configuration. This package builds FFmpeg with --enable-gpl --enable-version3.

About

Swift 6.2+ bindings for FFmpeg with cross-platform artifact bundle support

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors