AVFoundation
是 Apple 提供的一个功能丰富的 多媒体框架,用于处理音频、视频、音频视频的捕获与播放,还可以编辑和处理多媒体内容。它是苹果生态系统中开发多媒体相关应用(如媒体播放器、音频视频录制、编辑工具)的关键核心框架。不论是初学者还是高级用户,AVFoundation
都是实现复杂多媒体功能的强大工具。
1. AVFoundation 的体系结构 #
AVFoundation
的体系结构包含多个模块,根据功能被划分为以下几个主要部分:
1.1 播放音频与视频 (Playback) #
类/协议 | 描述 |
---|---|
AVPlayer | 用于播放音频或视频的核心类,支持网络流媒体和本地文件。 |
AVPlayerItem | AVPlayer 的媒体资源描述对象,包含当前播放媒体的属性和状态。 |
AVPlayerLayer | 用于显示视频内容的图层,通常嵌入 CALayer 层级实现视频画面渲染。 |
1.2 媒体捕获与录制 (Capture) #
类/协议 | 描述 |
---|---|
AVCaptureSession | 负责管理输入设备(如摄像头、麦克风)和输出目标(如文件、图像预览)的会话。 |
AVCaptureDevice | 代表具体的硬件输入设备,如摄像头、麦克风等。 |
AVCaptureDeviceInput | 表示输入源(摄像头或麦克风)的配置。 |
AVCaptureOutput | 输出捕获的音视频数据,例如存储为文件或提供实时音视频数据流。 |
AVCapturePhotoOutput | 专门处理拍照输出(静态图像)的类。 |
AVCaptureVideoDataOutput | 视频数据流输出,可以处理实时捕获的视频帧。 |
AVCaptureAudioDataOutput | 音频数据流输出,可捕获实时音频流。 |
1.3 媒体编辑与导出 (Editing) #
类/协议 | 描述 |
---|---|
AVAsset | 媒体文件的抽象表示,包括音频、视频、字幕等。 |
AVAssetExportSession | 将 AVAsset 导出为指定的格式和分辨率视频或音频文件。 |
AVMutableComposition | 用于创建或编辑音频和视频的可变复合媒体。 |
AVMutableVideoComposition | 修改或创建视频特效(如滤镜)和过渡效果。 |
AVMutableAudioMix | 用于实现音频的淡入/淡出或多轨音频混音。 |
1.4 媒体资源管理 (Reading & Metadata) #
类/协议 | 描述 |
---|---|
AVURLAsset | 管理基于 URL 的媒体资源(如本地文件或网络流媒体文件)。 |
AVMetadataItem | 包含媒体文件元数据信息(如视频标题、描述、艺术家信息等)。 |
AVMediaSelection | 用于管理音轨选择、多语言字幕和视频轨道。 |
1.5 低层次音频管理 (Audio) #
类/协议 | 描述 |
---|---|
AVAudioPlayer | 简单播放音频文件的类,用于播放本地音频(如 .mp3 、.wav )。 |
AVAudioRecorder | 音频录制类,可通过麦克风录制音频并存储为音频文件(如 .m4a )。 |
AVAudioSession | 配置并管理应用的音频行为(如录音和播放的模式)。 |
AVAudioEngine | 提供低级音频操作支持,适用于需要音频实时处理的场景(如音效增强或者多轨混音)。 |
2. 如何使用 AVFoundation? #
2.1 视频和音频播放(AVPlayer) #
示例:播放本地视频或音频文件 #
import AVFoundation
import UIKit
class PlayerViewController: UIViewController {
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
if let filePath = Bundle.main.path(forResource: "sample", ofType: "mp4") {
let fileURL = URL(fileURLWithPath: filePath)
// 初始化播放器
player = AVPlayer(url: fileURL)
// 创建视频显示的 Layer
playerLayer = AVPlayerLayer(player: player)
playerLayer?.videoGravity = .resizeAspect
playerLayer?.frame = self.view.bounds
// 添加播放器 Layer 到视图
if let playerLayer = playerLayer {
self.view.layer.addSublayer(playerLayer)
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
player?.play() // 开始播放
}
}
2.2 媒体捕获与录制(AVCaptureSession) #
示例:拍摄照片 #
import UIKit
import AVFoundation
class CapturePhotoViewController: UIViewController, AVCapturePhotoCaptureDelegate {
var captureSession: AVCaptureSession?
var photoOutput: AVCapturePhotoOutput?
override func viewDidLoad() {
super.viewDidLoad()
// 1. 创建捕获会话
captureSession = AVCaptureSession()
// 2. 设置视频输入设备
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back),
let videoInput = try? AVCaptureDeviceInput(device: camera) else {
print("Failed to get camera input.")
return
}
captureSession?.addInput(videoInput)
// 3. 设置照片输出
photoOutput = AVCapturePhotoOutput()
if let photoOutput = photoOutput {
captureSession?.addOutput(photoOutput)
}
// 4. 添加预览图层
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
previewLayer.frame = view.bounds
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
// 5. 开始捕获会话
captureSession?.startRunning()
}
// 捕获按钮点击事件
@IBAction func capturePhoto(_ sender: UIButton) {
let settings = AVCapturePhotoSettings()
photoOutput?.capturePhoto(with: settings, delegate: self)
}
// 处理照片捕获结果
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: Error?) {
if let photoData = photo.fileDataRepresentation() {
let image = UIImage(data: photoData)
// 保存照片到相册或者使用照片
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
print("Photo captured.")
}
}
}
2.3 视频编辑与导出(AVAssetExportSession) #
示例:裁剪视频并导出 #
import AVFoundation
func trimVideo(inputURL: URL, outputURL: URL, startTime: Double, duration: Double, completion: @escaping (Bool) -> Void) {
let asset = AVAsset(url: inputURL)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
let start = CMTime(seconds: startTime, preferredTimescale: 600)
let duration = CMTime(seconds: duration, preferredTimescale: 600)
let range = CMTimeRange(start: start, duration: duration)
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.timeRange = range
exportSession.exportAsynchronously {
switch exportSession.status {
case .completed:
completion(true)
case .failed, .cancelled:
print("Failed: \(String(describing: exportSession.error))")
completion(false)
default:
break
}
}
}
2.4 实现音频播放与录制(AVAudioPlayer 和 AVAudioRecorder) #
示例:播放音频 #
import AVFoundation
func playAudio() {
guard let fileURL = Bundle.main.url(forResource: "audio", withExtension: "mp3") else { return }
do {
let player = try AVAudioPlayer(contentsOf: fileURL)
player.play()
} catch {
print("Failed to play audio: \(error.localizedDescription)")
}
}
示例:录制音频 #
import AVFoundation
func recordAudio() {
guard let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let audioPath = documentsPath.appendingPathComponent("record.m4a")
let settings: [String: Any] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
let recorder = try AVAudioRecorder(url: audioPath, settings: settings)
recorder.record() // 开始录音
} catch {
print("Failed to record audio: \(error.localizedDescription)")
}
}
3. 注意事项 #
权限管理
- 如果需要访问用户的摄像头、麦克风或相册,需要在
Info.plist
中声明权限:<key>NSCameraUsageDescription</key> <string>We need camera access to record videos.</string> <key>NSMicrophoneUsageDescription</key> <string>We need microphone access to record audio.</string>
- 如果需要访问用户的摄像头、麦克风或相册,需要在
高耗性能
- 媒体捕获和编辑的操作会消耗较多内存和 CPU,建议优化。
文件格式和编码
- 确保输出文件格式与设备兼容,例如
.mp4
和.m4a
。
- 确保输出文件格式与设备兼容,例如
4. 总结 #
AVFoundation
是一个功能强大且灵活的多媒体框架,主要包含:
- 播放音视频
AVPlayer
- 捕获多媒体内容
AVCaptureSession
- 编辑和导出
AVAssetExportSession
- 音频管理和处理
AVAudioEngine
适用于创建视频播放器、音视频编辑工具、实时捕获应用等多媒体相关应用。