### Install FFmpeg using Homebrew
Source: https://github.com/sunlubo/swiftffmpeg/blob/master/README.md
This command installs the FFmpeg library on macOS using the Homebrew package manager. Ensure FFmpeg version 7.1 or higher is installed before using the SwiftFFmpeg library.
```bash
brew install ffmpeg
```
--------------------------------
### Scale Video Frames with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
This example demonstrates how to scale video frames and convert between pixel formats (e.g., YUV420P to RGB24) using SwiftFFmpeg's libswscale. It requires creating a SwsContext with source and destination parameters and then performing the scaling operation on AVFrame objects. The input and output frames need to be allocated with appropriate buffers.
```swift
import SwiftFFmpeg
let srcWidth = 1920
let srcHeight = 1080
let srcFormat = AVPixelFormat.YUV420P
let dstWidth = 640
let dstHeight = 480
let dstFormat = AVPixelFormat.RGB24
// Create scaling context
guard let swsCtx = SwsContext(
srcWidth: srcWidth, srcHeight: srcHeight, srcPixelFormat: srcFormat,
dstWidth: dstWidth, dstHeight: dstHeight, dstPixelFormat: dstFormat,
flags: .bilinear
) else {
fatalError("Cannot create scaling context")
}
// Prepare source and destination frames
let srcFrame = AVFrame()
srcFrame.width = srcWidth
srcFrame.height = srcHeight
srcFrame.pixelFormat = srcFormat
try srcFrame.allocBuffer(align: 32)
let dstFrame = AVFrame()
dstFrame.width = dstWidth
dstFrame.height = dstHeight
dstFrame.pixelFormat = dstFormat
try dstFrame.allocBuffer(align: 32)
// Perform scaling
let scaledHeight = swsCtx.scale(
src: srcFrame.data,
srcStride: srcFrame.linesize,
srcSliceY: 0,
srcSliceHeight: srcHeight,
dst: dstFrame.data,
dstStride: dstFrame.linesize
)
print("Scaled \(srcHeight) lines to \(scaledHeight) lines")
```
--------------------------------
### Read and Process Video Frames with SwiftFFmpeg
Source: https://github.com/sunlubo/swiftffmpeg/blob/master/README.md
This Swift code demonstrates how to use the SwiftFFmpeg library to open a video file, find its streams and codecs, and then read and process individual video frames. It handles stream information, codec context setup, and frame decoding, printing details for each decoded frame.
```swift
import Foundation
import SwiftFFmpeg
if CommandLine.argc < 2 {
print("Usage: (CommandLine.arguments[0]) ")
exit(1)
}
let input = CommandLine.arguments[1]
let fmtCtx = try AVFormatContext(url: input)
try fmtCtx.findStreamInfo()
fmtCtx.dumpFormat(isOutput: false)
guard let stream = fmtCtx.videoStream else {
fatalError("No video stream.")
}
guard let codec = AVCodec.findDecoderById(stream.codecParameters.codecId) else {
fatalError("Codec not found.")
}
let codecCtx = AVCodecContext(codec: codec)
codecCtx.setParameters(stream.codecParameters)
try codecCtx.openCodec()
let pkt = AVPacket()
let frame = AVFrame()
while let _ = try? fmtCtx.readFrame(into: pkt) {
defer { pkt.unref() }
if pkt.streamIndex != stream.index {
continue
}
try codecCtx.sendPacket(pkt)
while true {
do {
try codecCtx.receiveFrame(frame)
} catch let err as AVError where err == .tryAgain || err == .eof {
break
}
let str = String(
format: "Frame %3d (type=%@, size=%5d bytes) pts %4lld key_frame %d",
codecCtx.frameNumber,
frame.pictureType.description,
frame.pktSize,
frame.pts,
frame.isKeyFrame
)
print(str)
frame.unref()
}
}
print("Done.")
```
--------------------------------
### Decode Video Frames with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
This code example shows how to decode video packets into raw frames using SwiftFFmpeg. It includes comprehensive error handling for finding the video stream, locating the decoder, configuring the codec context, and processing decoded frames, with support for end-of-file and try-again scenarios.
```swift
import SwiftFFmpeg
let input = "/path/to/video.mp4"
let fmtCtx = try AVFormatContext(url: input)
try fmtCtx.findStreamInfo()
// Find video stream and decoder
guard let stream = fmtCtx.videoStream else {
fatalError("No video stream found")
}
guard let codec = AVCodec.findDecoderById(stream.codecParameters.codecId) else {
fatalError("Codec not found")
}
// Create and configure decoder context
let codecCtx = AVCodecContext(codec: codec)
codecCtx.setParameters(stream.codecParameters)
try codecCtx.openCodec()
let pkt = AVPacket()
let frame = AVFrame()
// Read and decode frames
while let _ = try? fmtCtx.readFrame(into: pkt) {
defer { pkt.unref() }
if pkt.streamIndex != stream.index {
continue
}
try codecCtx.sendPacket(pkt)
while true {
do {
try codecCtx.receiveFrame(frame)
// Process decoded frame
print(String(
format: "Frame %3d (type=%@, size=%5d bytes) pts %4lld",
codecCtx.frameNumber,
frame.pictureType.description,
frame.pktSize,
frame.pts
))
frame.unref()
} catch let err as AVError where err == .tryAgain || err == .eof {
break
}
}
}
```
--------------------------------
### Hardware Accelerated Decoding with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
Utilizes hardware-accelerated decoding for improved performance, specifically demonstrating VideoToolbox on macOS/iOS. It finds the appropriate decoder, sets up the hardware device context, and configures the codec context for hardware formats. Dependencies include SwiftFFmpeg and the relevant hardware acceleration frameworks.
```swift
import SwiftFFmpeg
let input = "/path/to/video.mp4"
let fmtCtx = try AVFormatContext(url: input)
try fmtCtx.findStreamInfo()
guard let videoStream = fmtCtx.videoStream else {
fatalError("No video stream")
}
// Find decoder and create context
guard let codec = AVCodec.findDecoderById(videoStream.codecParameters.codecId) else {
fatalError("Codec not found")
}
let codecCtx = AVCodecContext(codec: codec)
codecCtx.setParameters(videoStream.codecParameters)
// Setup hardware acceleration (e.g., VideoToolbox on macOS/iOS)
let hwDeviceType = AVHWDeviceType.videotoolbox
if let hwDevice = try? AVHWDeviceContext(type: hwDeviceType) {
codecCtx.hwDeviceContext = hwDevice
// Set pixel format callback to prefer hardware formats
codecCtx.getFormat = { ctx, formats in
for format in formats {
if format == .videotoolbox {
return format
}
}
return formats.first ?? .none
}
}
try codecCtx.openCodec()
// Decode with hardware acceleration
let pkt = AVPacket()
let frame = AVFrame()
while let _ = try? fmtCtx.readFrame(into: pkt) {
defer { pkt.unref() }
if pkt.streamIndex != videoStream.index {
continue
}
try codecCtx.sendPacket(pkt)
while true {
do {
try codecCtx.receiveFrame(frame)
// Frame may be in hardware format
if frame.pixelFormat == .videotoolbox {
print("Hardware-decoded frame: (frame.pts)")
}
frame.unref()
} catch let err as AVError where err == .tryAgain || err == .eof {
break
}
}
}
```
--------------------------------
### Open and Read Media File Information with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
This snippet demonstrates how to open a media file using SwiftFFmpeg, read its header, display format details, and access metadata such as duration, bit rate, and stream count. It also shows how to find and extract information about the best video stream.
```swift
import SwiftFFmpeg
let input = "/path/to/video.mp4"
// Open input file and read header
let fmtCtx = try AVFormatContext(url: input)
try fmtCtx.findStreamInfo()
// Display format information
fmtCtx.dumpFormat(isOutput: false)
// Access file metadata
print("Duration: (fmtCtx.duration)")
print("Bit rate: (fmtCtx.bitRate)")
print("Number of streams: (fmtCtx.streamCount)")
// Find the best video stream
if let videoIndex = fmtCtx.findBestStream(type: .video) {
let stream = fmtCtx.streams[videoIndex]
print("Video codec: (stream.codecParameters.codecId)")
print("Resolution: (stream.codecParameters.width)x(stream.codecParameters.height)")
}
```
--------------------------------
### Apply Video Filters with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
Demonstrates applying video filters such as scale and hflip using libavfilter. It involves setting up an AVFilterGraph, configuring buffer source and sink, linking filters, and processing frames through the filter chain. Requires SwiftFFmpeg library.
```swift
import SwiftFFmpeg
let input = "/path/to/video.mp4"
let fmtCtx = try AVFormatContext(url: input)
try fmtCtx.findStreamInfo()
// Find video stream and create decoder
let streamIndex = fmtCtx.findBestStream(type: .video)!
let stream = fmtCtx.streams[streamIndex]
let decoder = AVCodec.findDecoderById(stream.codecParameters.codecId)!
let decoderCtx = AVCodecContext(codec: decoder)
decoderCtx.setParameters(stream.codecParameters)
try decoderCtx.openCodec()
// Create filter graph
let filterGraph = AVFilterGraph()
let buffersrc = AVFilter(name: "buffer")!
let buffersink = AVFilter(name: "buffersink")!
// Configure buffer source
let args = """
video_size=\(decoderCtx.width)x\(decoderCtx.height):\
pix_fmt=\(decoderCtx.pixelFormat.rawValue):\
time_base=\(stream.timebase.num)/\(stream.timebase.den):\
pixel_aspect=\(decoderCtx.sampleAspectRatio.num)/\(decoderCtx.sampleAspectRatio.den)
"""
let buffersrcCtx = try filterGraph.addFilter(buffersrc, name: "in", args: args)
// Configure buffer sink
let buffersinkCtx = try filterGraph.addFilter(buffersink, name: "out", args: nil)
let pixFmts = [AVPixelFormat.GRAY8]
try buffersinkCtx.set(pixFmts.map({ $0.rawValue }), forKey: "pix_fmts")
// Link filters
let inputs = AVFilterInOut()
let outputs = AVFilterInOut()
outputs.name = "in"
outputs.filterContext = buffersrcCtx
outputs.padIndex = 0
inputs.name = "out"
inputs.filterContext = buffersinkCtx
inputs.padIndex = 0
let filterSpec = "scale=640:480,hflip"
try filterGraph.parse(filterSpec, inputs: inputs, outputs: outputs)
try filterGraph.configure()
// Process frames through filter
let pkt = AVPacket()
let frame = AVFrame()
let filteredFrame = AVFrame()
while let _ = try? fmtCtx.readFrame(into: pkt) {
defer { pkt.unref() }
if pkt.streamIndex != streamIndex {
continue
}
try decoderCtx.sendPacket(pkt)
while true {
do {
try decoderCtx.receiveFrame(frame)
// Push frame to filter
try buffersrcCtx.addFrame(frame, flags: [.keepRef])
// Pull filtered frame
while true {
do {
try buffersinkCtx.getFrame(filteredFrame)
// Process filtered frame
print("Filtered frame \(filteredFrame.pts)")
filteredFrame.unref()
} catch let err as AVError where err == .tryAgain || err == .eof {
break
}
}
frame.unref()
} catch let err as AVError where err == .tryAgain || err == .eof {
break
}
}
}
```
--------------------------------
### Encode Video Frames with SwiftFFmpeg
Source: https://context7.com/sunlubo/swiftffmpeg/llms.txt
This SwiftFFmpeg snippet illustrates how to encode raw video frames into a compressed format. It covers finding and configuring an encoder (mpeg1video), setting up codec parameters like bit rate and resolution, allocating frame buffers, and writing encoded packets to an output file, including flushing the encoder at the end.
```swift
import SwiftFFmpeg
let output = "/path/to/output.mpg"
// Find and configure encoder
let codec = AVCodec.findEncoderByName("mpeg1video")!
let codecCtx = AVCodecContext(codec: codec)
codecCtx.bitRate = 400000
codecCtx.width = 352
codecCtx.height = 288
codecCtx.timebase = AVRational(num: 1, den: 25)
codecCtx.framerate = AVRational(num: 25, den: 1)
codecCtx.gopSize = 10
codecCtx.maxBFrames = 1
codecCtx.pixelFormat = .YUV420P
try codecCtx.openCodec()
// Prepare frame and packet
let frame = AVFrame()
frame.pixelFormat = codecCtx.pixelFormat
frame.width = codecCtx.width
frame.height = codecCtx.height
try frame.allocBuffer(align: 32)
let pkt = AVPacket()
guard let file = fopen(output, "wb") else {
fatalError("Cannot open output file")
}
defer { fclose(file) }
// Encode 25 frames (1 second at 25fps)
for i in 0..<25 {
try frame.makeWritable()
// Generate dummy YUV420P image data
for y in 0..