Come tagliare il video usando AVFoundation

Sono in grado di registrare il video utilizzando AVFoundation o UIImagePickerController. Ma non sono in grado di tagliare il video da un particolare secondo ad un altro particolare durata / tempo. Qualcuno può aiutarmi.

Grazie, Siva Krishna.

Puoi consentire a UIImagePickerController di abilitare il taglio

UIImagePickerController *videoRecorder = [[UIImagePickerController alloc]init]; NSArray *sourceTypes = [UIImagePickerController availableMediaTypesForSourceType:videoRecorder.sourceType]; NSLog(@"Available types for source as camera = %@", sourceTypes); if (![sourceTypes containsObject:(NSString*)kUTTypeMovie] ) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Device Not Supported for video Recording." delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No",nil]; [alert show]; [alert release]; return; } videoRecorder.allowsEditing = YES; 

Sfortunatamente dopo il ritorno da imagePickerController, sei costretto a convertire il video manualmente.

 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { if ([self.popoverLibraryBrowser isPopoverVisible]) { [self.popoverLibraryBrowser dismissPopoverAnimated:YES]; } NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; if ([type isEqualToString:(NSString *)kUTTypeVideo] || [type isEqualToString:(NSString *)kUTTypeMovie]) { // movie != video NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; NSNumber *start = [info objectForKey:@"_UIImagePickerControllerVideoEditingStart"]; NSNumber *end = [info objectForKey:@"_UIImagePickerControllerVideoEditingEnd"]; // if start and end are nil then clipping was not used. // You should use the entire video. int startMilliseconds = ([start doubleValue] * 1000); int endMilliseconds = ([end doubleValue] * 1000); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSFileManager *manager = [NSFileManager defaultManager]; NSString *outputURL = [documentsDirectory stringByAppendingPathComponent:@"output"] ; [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil]; outputURL = [outputURL stringByAppendingPathComponent:@"output.mp4"]; // Remove Existing File [manager removeItemAtPath:outputURL error:nil]; //[self loadAssetFromFile:videoURL]; [self.recorder dismissModalViewControllerAnimated:YES]; AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality]; exportSession.outputURL = [NSURL fileURLWithPath:outputURL]; exportSession.outputFileType = AVFileTypeQuickTimeMovie; CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(startMilliseconds, 1000), CMTimeMake(endMilliseconds - startMilliseconds, 1000)); exportSession.timeRange = timeRange; [exportSession exportAsynchronouslyWithCompletionHandler:^{ switch (exportSession.status) { case AVAssetExportSessionStatusCompleted: // Custom method to import the Exported Video [self loadAssetFromFile:exportSession.outputURL]; break; case AVAssetExportSessionStatusFailed: // NSLog(@"Failed:%@",exportSession.error); break; case AVAssetExportSessionStatusCancelled: // NSLog(@"Canceled:%@",exportSession.error); break; default: break; } }]; //NSData *videoData = [NSData dataWithContentsOfURL:videoURL]; //NSString *videoStoragePath;//Set your video storage path to this variable //[videoData writeToFile:videoStoragePath atomically:YES]; //You can store the path of the saved video file in sqlite/coredata here. } } 

Versione rapida di sopra

 import UIKit import AVFoundation import MobileCoreServices func pickVideo(){ if UIImagePickerController.isSourceTypeAvailable(.Camera) { let videoRecorder = UIImagePickerController() videoRecorder.sourceType = .Camera videoRecorder.mediaTypes = [kUTTypeMovie as String] videoRecorder.allowsEditing = true videoRecorder.delegate = self presentViewController(videoRecorder, animated: true, completion: nil) } } func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { picker.dismissViewControllerAnimated(true, completion: nil) let manager = NSFileManager.defaultManager() guard let documentDirectory = try? manager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) else {return} guard let mediaType = info[UIImagePickerControllerMediaType] as? String else {return} guard let url = info[UIImagePickerControllerMediaURL] as? NSURL else {return} if mediaType == kUTTypeMovie as String || mediaType == kUTTypeVideo as String { let asset = AVAsset(URL: url) let length = Float(asset.duration.value) / Float(asset.duration.timescale) print("video length: \(length) seconds") let start = info["_UIImagePickerControllerVideoEditingStart"] as? Float let end = info["_UIImagePickerControllerVideoEditingEnd"] as? Float var outputURL = documentDirectory.URLByAppendingPathComponent("output") do { try manager.createDirectoryAtURL(outputURL, withIntermediateDirectories: true, attributes: nil) outputURL = outputURL.URLByAppendingPathComponent("output.mp4") }catch let error { print(error) } //Remove existing file _ = try? manager.removeItemAtURL(outputURL) guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {return} exportSession.outputURL = outputURL exportSession.outputFileType = AVFileTypeMPEG4 let startTime = CMTime(seconds: Double(start ?? 0), preferredTimescale: 1000) let endTime = CMTime(seconds: Double(end ?? length), preferredTimescale: 1000) let timeRange = CMTimeRange(start: startTime, end: endTime) exportSession.timeRange = timeRange exportSession.exportAsynchronouslyWithCompletionHandler{ switch exportSession.status { case .Completed: print("exported at \(outputURL)") case .Failed: print("failed \(exportSession.error)") case .Cancelled: print("cancelled \(exportSession.error)") default: break } } } } 

La migliore soluzione per swift 4, l’ho trovata lì . L’ho risolto per i miei bisogni, ma è molto chiaro e comodo.

Il codice:

 import AVFoundation import Foundation extension FileManager { func removeFileIfNecessary(at url: URL) throws { guard fileExists(atPath: url.path) else { return } do { try removeItem(at: url) } catch let error { throw TrimError("Couldn't remove existing destination file: \(error)") } } } struct TrimError: Error { let description: String let underlyingError: Error? init(_ description: String, underlyingError: Error? = nil) { self.description = "TrimVideo: " + description self.underlyingError = underlyingError } } extension AVMutableComposition { convenience init(asset: AVAsset) { self.init() for track in asset.tracks { addMutableTrack(withMediaType: track.mediaType, preferredTrackID: track.trackID) } } func trim(timeOffStart: Double) { let duration = CMTime(seconds: timeOffStart, preferredTimescale: 1) let timeRange = CMTimeRange(start: kCMTimeZero, duration: duration) for track in tracks { track.removeTimeRange(timeRange) } removeTimeRange(timeRange) } } extension AVAsset { func assetByTrimming(timeOffStart: Double) throws -> AVAsset { let duration = CMTime(seconds: timeOffStart, preferredTimescale: 1) let timeRange = CMTimeRange(start: kCMTimeZero, duration: duration) let composition = AVMutableComposition() do { for track in tracks { let compositionTrack = composition.addMutableTrack(withMediaType: track.mediaType, preferredTrackID: track.trackID) try compositionTrack?.insertTimeRange(timeRange, of: track, at: kCMTimeZero) } } catch let error { throw TrimError("error during composition", underlyingError: error) } return composition } func export(to destination: URL) throws { guard let exportSession = AVAssetExportSession(asset: self, presetName: AVAssetExportPresetPassthrough) else { throw TrimError("Could not create an export session") } exportSession.outputURL = destination exportSession.outputFileType = AVFileType.m4v exportSession.shouldOptimizeForNetworkUse = true let group = DispatchGroup() group.enter() try FileManager.default.removeFileIfNecessary(at: destination) exportSession.exportAsynchronously { group.leave() } group.wait() if let error = exportSession.error { throw TrimError("error during export", underlyingError: error) } } } func time(_ operation: () throws -> ()) rethrows { let start = Date() try operation() let end = Date().timeIntervalSince(start) print(end) let sourceURL = URL(fileURLWithPath: CommandLine.arguments[1]) let destinationURL = URL(fileURLWithPath: CommandLine.arguments[2]) do { try time { let asset = AVURLAsset(url: sourceURL) let trimmedAsset = try asset.assetByTrimming(timeOffStart: 1.0) try trimmedAsset.export(to: destinationURL) } } catch let error { print("💩 \(error)") } } 

dovresti aggiungere kUTTypeMovie nella matrice setMediaTypes e funzionerà.