我尝试过以下方法:
- (void)compress:(NSURL *)videoPath completionBlock:(void(^)(id data, BOOL result))block{
self.outputFilePath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
NSURL *outputURL = [NSURL fileURLWithPath:self.outputFilePath];
[self compressVideoWithURL:self.movieURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession) {
}];
}
- (void)compressVideoWithURL:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
handler:(void (^)(AVAssetExportSession*))handler {
AVURLAsset *asset = [AVURLAsset assetWithURL:self.movieURL];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession.fileLengthLimit = 3000000;
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSData *newOutputData = [NSData dataWithContentsOfURL:outputURL];
NSLog(@"Size of New Video(bytes):%d",[newOutputData length]);
}];
}
我知道
self.movieUrl
不是nil
。但是当我打印与视频相关的 NSData
的大小(以字节为单位)时,它们前后是相同的,都是 30,000,000 字节。
但是根据这个问题,上面的代码应该可以工作。
我究竟做错了什么?
在 Swift 3.0 中
从相机胶卷中选择视频
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if info[UIImagePickerControllerMediaType] as? String == (kUTTypeMovie as? String) {
// here your video capture code
let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL!
let data = NSData(contentsOf: videoURL! as URL)!
print("File size before compression: \(Double(data.length / 1048576)) mb")
let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".m4v")
compressVideo(inputURL: videoURL as! URL, outputURL: compressedURL) { (exportSession) in
guard let session = exportSession else {
return
}
switch session.status {
case .unknown:
break
case .waiting:
break
case .exporting:
break
case .completed:
guard let compressedData = NSData(contentsOf: compressedURL) else {
return
}
print("File size after compression: \(Double(compressedData.length / 1048576)) mb")
case .failed:
break
case .cancelled:
break
}
}
}
self.dismiss(animated: true, completion: nil)
}
压缩类型:
AVAssetExportPresetLowQuality
AVAssetExportPresetMediumQuality
AVAssetExportPresetHighestQuality
AVAssetExportPreset640x480
AVAssetExportPreset960x540
压缩视频方法
func compressVideo(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) {
let urlAsset = AVURLAsset(url: inputURL, options: nil)
guard let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetLowQuality) else {
handler(nil)
return
}
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession.shouldOptimizeForNetworkUse = true
exportSession.exportAsynchronously { () -> Void in
handler(exportSession)
}
}
输出:
File size before compression: 25.0 mb
File size after compression: 7.0 mb
我已经弄清楚了,感谢这个问题(Swift 版本):IOS Video Compression Swift iOS 8 损坏的视频文件
我有 Objective C 版本。方法如下:
- (void)compressVideo:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
handler:(void (^)(AVAssetExportSession*))completion {
AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:urlAsset presetName:AVAssetExportPresetMediumQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
completion(exportSession);
}];
}
并调用该方法:
NSURL* uploadURL = [NSURL fileURLWithPath:
[NSTemporaryDirectory() stringByAppendingPathComponent:@"temporaryPreview.mov"]];
[self compressVideo:self.movieURL outputURL:uploadURL handler:^(AVAssetExportSession *completion) {
if (completion.status == AVAssetExportSessionStatusCompleted) {
NSData *newDataForUpload = [NSData dataWithContentsOfURL:uploadURL];
NSLog(@"Size of new Video after compression is (bytes):%d",[newDataForUpload length]);
}
}];
这将我的视频文件大小从 32 MB 减少到 1.5 MB。
您可以使用此方法进行视频压缩。
struct ReduceVideoSizeError: Error { }
func reduceVideoSize(inputURL: URL, outputURL: URL, completion: @escaping (Error?) -> Void) {
let asset = AVAsset(url: inputURL)
asset.loadTracks(withMediaType: .video) { videoTracks, error in
guard let videoTrack = videoTracks?.first else {
completion(NSError(domain: "YourAppDomain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to load video track"]))
return
}
asset.loadTracks(withMediaType: .audio) { audioTracks, error in
guard let audioTrack = audioTracks?.first else {
completion(NSError(domain: "YourAppDomain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to load audio track"]))
return
}
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else {
completion(NSError(domain: "YourAppDomain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create AVAssetExportSession"]))
return
}
let videoSettings: [String : AnyObject] = [
AVVideoCodecKey : AVVideoCodecType.h264 as AnyObject,
AVVideoWidthKey : videoTrack.naturalSize.width as AnyObject,
AVVideoHeightKey : videoTrack.naturalSize.height as AnyObject,
AVVideoCompressionPropertiesKey : [
AVVideoAverageBitRateKey: 600000 // Adjust bitrate as needed
] as AnyObject
]
let audioSettings: [String : AnyObject] = [
AVFormatIDKey: kAudioFormatMPEG4AAC as AnyObject,
AVNumberOfChannelsKey: 2 as AnyObject,
AVSampleRateKey: 44100 as AnyObject,
AVEncoderBitRateKey: 64000 as AnyObject
]
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.timeRange = CMTimeRange(start: .zero, duration: asset.duration)
exportSession.videoComposition = AVVideoComposition(asset: asset) { request in
let source = request.sourceImage.clampedToExtent()
request.finish(with: source, context: nil)
}
exportSession.audioMix = AVAudioMix() // Ensure audio settings are respected
exportSession.exportAsynchronously {
if exportSession.status == .completed {
completion(nil)
} else if let error = exportSession.error {
completion(error)
} else {
completion(NSError(domain: "YourAppDomain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unknown error"]))
}
}
}
}
}
private func getVideoWriterSettings(bitrate: Int, width: Int, height: Int) -> [String : AnyObject] {
let videoWriterCompressionSettings = [
AVVideoAverageBitRateKey: bitrate
]
let videoWriterSettings: [String : AnyObject] = [
AVVideoCodecKey: AVVideoCodecType.h264 as AnyObject,
AVVideoCompressionPropertiesKey: videoWriterCompressionSettings as AnyObject,
AVVideoWidthKey: width as AnyObject,
AVVideoHeightKey: height as AnyObject
]
return videoWriterSettings
}