### 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..