AVFoundation
时间:2026-08-20 23:33:33 356浏览 收藏
裁剪视频Size
使用 A VFoundation如何裁剪视频大小,比如 原视频为 width: 920, height: 1680 我想裁剪为 width: 920, height: 1680 * 0.6 但是是从 1680 * 0.1开始裁剪

利用 A VFoundation 来裁剪视频大小,这一功能可借助 A VMutableComposition 以及 A VVideoComposition 得以实现。接下来,为您详细阐述具体的操作步骤,并附上代码示例,以展示如何从原始视频里裁剪出特定区域(比如说,从高度 1680 * 0.1 处起始,裁剪出高度为 1680 * 0.6 的区域)。
实现步骤
-
加载视频资源:
- 使用
A VAsset加载原始视频。
- 使用
-
创建
A VMutableComposition:- 用于将视频和音频轨道添加到新的组合中。
-
设置裁剪区域:
- 使用
A VVideoComposition的renderSize和instructions来定义裁剪区域。
- 使用
-
导出视频:
- 使用
A VAssetExportSession将裁剪后的视频导出到文件。
- 使用
完整代码实现
import UIKit
import A VFoundation
import Photos
class VideoCroppingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 1. 加载本地视频
guard let videoURL = Bundle.main.url(forResource: "input_video", withExtension: "mp4") else {
print("视频文件未找到")
return
}
// 2. 定义裁剪区域
let originalWidth: CGFloat = 920
let originalHeight: CGFloat = 1680
let cropStartY: CGFloat = originalHeight * 0.1 // 从高度的 10% 开始裁剪
let cropHeight: CGFloat = originalHeight * 0.6 // 裁剪高度为 60%
let cropRect = CGRect(x: 0, y: cropStartY, width: originalWidth, height: cropHeight)
// 3. 裁剪视频
cropVideo(sourceURL: videoURL, cropRect: cropRect) { outputURL in
if let outputURL = outputURL {
print("裁剪后的视频已保存到: (outputURL)")
// 4. 保存到相册
self.sa veVideoToPhotoLibrary(url: outputURL)
} else {
print("视频裁剪失败")
}
}
}
// 裁剪视频
func cropVideo(sourceURL: URL, cropRect: CGRect, completion: @escaping (URL?) -> Void) {
// 1. 加载视频资源
let asset = A VURLAsset(url: sourceURL)
// 2. 创建 A VMutableComposition
let composition = A VMutableComposition()
// 3. 添加视频轨道
guard let videoTrack = asset.tracks(withMediaType: .video).first else {
print("无法获取视频轨道")
completion(nil)
return
}
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
try compositionVideoTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: videoTrack, at: .zero)
} catch {
print("插入视频轨道失败: (error.localizedDescription)")
completion(nil)
return
}
// 4. 添加音频轨道
if let audioTrack = asset.tracks(withMediaType: .audio).first {
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
try compositionAudioTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: audioTrack, at: .zero)
} catch {
print("插入音频轨道失败: (error.localizedDescription)")
}
}
// 5. 创建 A VVideoComposition
let videoComposition = A VMutableVideoComposition()
videoComposition.renderSize = CGSize(width: cropRect.width, height: cropRect.height)
videoComposition.frameDuration = CMTime(value: 1, timescale: 30) // 30 FPS
// 6. 创建视频指令
let instruction = A VMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(start: .zero, duration: asset.duration)
let layerInstruction = A VMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack!)
// 设置裁剪区域
let transform = CGAffineTransform(translationX: -cropRect.origin.x, y: -cropRect.origin.y)
layerInstruction.setTransform(transform, at: .zero)
instruction.layerInstructions = [layerInstruction]
videoComposition.instructions = [instruction]
// 7. 导出视频
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let outputPath = documentsPath.appendingPathComponent("cropped_video.mov")
let outputURL = URL(fileURLWithPath: outputPath)
// 删除已存在的文件(如果存在)
if FileManager.default.fileExists(atPath: outputPath) {
try? FileManager.default.removeItem(at: outputURL)
}
let exporter = A VAssetExportSession(asset: composition, presetName: A VAssetExportPresetHighestQuality)
exporter?.outputURL = outputURL
exporter?.outputFileType = .mov
exporter?.videoComposition = videoComposition
exporter?.exportAsynchronously {
DispatchQueue.main.async {
if exporter?.status == .completed {
completion(outputURL)
} else {
print("导出失败: (exporter?.error?.localizedDescription ?? "未知错误")")
completion(nil)
}
}
}
}
// 保存视频到相册
func sa veVideoToPhotoLibrary(url: URL) {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
}) { success, error in
if success {
print("视频已保存到相册")
} else if let error = error {
print("保存视频到相册失败: (error.localizedDescription)")
}
}
}
}
代码说明
-
裁剪区域:
cropRect定义了裁剪的区域,x和y是裁剪的起始点,width和height是裁剪的尺寸。
-
视频轨道和音频轨道:
- 使用
A VMutableComposition将原始视频的轨道插入到新的组合中。
- 使用
-
视频指令:
- 使用
A VMutableVideoCompositionInstruction和A VMutableVideoCompositionLayerInstruction设置裁剪区域的变换。
- 使用
-
导出视频:
- 使用
A VAssetExportSession将裁剪后的视频导出到文件。
- 使用
-
保存到相册:
- 使用
PHPhotoLibrary将裁剪后的视频保存到相册。
- 使用
运行结果
- 视频将从指定区域裁剪。
- 裁剪后的视频会保存到相册。
- 控制台会输出裁剪后的视频文件路径。
注意事项
- 确保原始视频的分辨率和裁剪区域是合理的,否则可能会导致黑边或变形。
- 如果视频较大,导出操作可能需要一些时间。
- 在
Info.plist中添加相册访问权限:key>NSPhotoLibraryAddUsageDescriptionkey> string>我们需要保存视频到相册string>
通过这种方式,你可以使用 A VFoundation 实现视频的精确裁剪。
裁剪时长
在iOS中,使用Swift来拍摄视频并裁剪视频大小,涉及到两个主要的步骤:
- 拍摄视频:通过
UIImagePickerController或者A VCaptureSession来拍摄视频。 - 裁剪视频大小:利用
A VAsset和A VAssetExportSession来裁剪视频的大小。
下面是实现这两个步骤的代码示例:
1. 使用UIImagePickerController拍摄视频
首先,你需要请求相机权限,并使用UIImagePickerController来拍摄视频。
import UIKit
import A VFoundation
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINa vigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// 检查是否有摄像头权限
checkCameraPermission()
}
func checkCameraPermission() {
A VCaptureDevice.requestAccess(for: .video) { response in
if response {
// 可以访问摄像头
self.recordVideo()
} else {
// 没有权限
print("Camera access denied")
}
}
}
func recordVideo() {
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .camera
imagePicker.mediaTypes = ["public.movie"]
imagePicker.delegate = self
present(imagePicker, animated: true, completion: nil)
}
// 处理视频选取完成后的回调
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
print("Video URL: (videoURL)")
// 处理裁剪视频
self.trimVideo(videoURL: videoURL)
}
picker.dismiss(animated: true, completion: nil)
}
// 处理视频裁剪
func trimVideo(videoURL: URL) {
let asset = A VAsset(url: videoURL)
let startTime = CMTime(seconds: 5, preferredTimescale: 600) // 从第5秒开始
let duration = CMTime(seconds: 10, preferredTimescale: 600) // 视频裁剪的持续时间为10秒
let trimmedAsset = A VAsset(url: videoURL)
let trimmedVideoURL = getDocumentsDirectory().appendingPathComponent("trimmedVideo.mp4")
let exportSession = A VAssetExportSession(asset: trimmedAsset, presetName: A VAssetExportPresetHighestQuality)
exportSession?.outputURL = trimmedVideoURL
exportSession?.outputFileType = .mp4
exportSession?.timeRange = CMTimeRangeMake(start: startTime, duration: duration)
exportSession?.exportAsynchronously {
switch exportSession?.status {
case .completed:
print("Video trimming successful!")
print("Trimmed video URL: (trimmedVideoURL)")
case .failed:
print("Video trimming failed: (exportSession?.error?.localizedDescription ?? "")")
default:
break
}
}
}
// 获取文件保存路径
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
}
说明:
- 录制视频:我们通过
UIImagePickerController来拍摄视频,选取的媒体类型为public.movie,允许拍摄视频。 - 裁剪视频:使用
A VAsset来加载选中的视频,通过A VAssetExportSession裁剪视频。这里裁剪的是从视频的第5秒到第15秒(裁剪10秒的视频)。输出为.mp4格式。 - 保存视频:裁剪后的视频保存到文档目录。
注意事项:
- 确保在
Info.plist中配置了摄像头和麦克风权限:NSCameraUsageDescription:描述为何需要使用相机。NSMicrophoneUsageDescription:描述为何需要使用麦克风。
- 根据需要调整裁剪的视频起始时间和持续时间。
这种方法适用于在简单的视频录制和裁剪需求场景下。
相关阅读
更多>
最新阅读
更多>
-
391 收藏
-
131 收藏
-
469 收藏
-
306 收藏
-
105 收藏
-
327 收藏
-
199 收藏
-
481 收藏
-
228 收藏
-
175 收藏
-
268 收藏
-
334 收藏
课程推荐
更多>
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习