Trim video always fail when use AVAssetExportPresetPassthrough
I wrote anwer in another question, they have the same problem, but it different way. That's how I solved the problem
https://stackoverflow.com/a/70294032/7217629
How to trim video with AVAssetReader and AVAssetWriter
AVAssetReader
has a property named timeRange
- you can specify time range which you need to proceed, so this will allow you to trim your output file
Exporting mp4 through AVAssetExportSession fails
Seems like converting the AVAsset
instance in a AVMutableComposition
did the trick. If, please, anyone knows the reason why this works let me know.
This is the new _getDataFor(_:completion:)
method implementation
func _getDataFor(_ item: AVPlayerItem, completion: @escaping (Data?) -> ()) {
guard item.asset.isExportable else {
completion(nil)
return
}
let composition = AVMutableComposition()
let compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let sourceVideoTrack = item.asset.tracks(withMediaType: AVMediaTypeVideo).first!
let sourceAudioTrack = item.asset.tracks(withMediaType: AVMediaTypeAudio).first!
do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceVideoTrack, at: kCMTimeZero)
try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceAudioTrack, at: kCMTimeZero)
} catch(_) {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: composition)
var preset: String = AVAssetExportPresetPassthrough
if compatiblePresets.contains(AVAssetExportPreset1920x1080) { preset = AVAssetExportPreset1920x1080 }
guard
let exportSession = AVAssetExportSession(asset: composition, presetName: preset),
exportSession.supportedFileTypes.contains(AVFileTypeMPEG4) else {
completion(nil)
return
}
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTimeMake(0, 1)
let timeRange = CMTimeRangeMake(startTime, item.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print("\(tempFileUrl)")
print("\(exportSession.error)")
let data = try? Data(contentsOf: tempFileUrl)
_ = try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
EXC_BAD_ACCESS with AVAssetExportSession and AVMutableComposition
My crash was a simple issue. The bigger problem I had was using the wrong filename extension. I'm now using .mp4, AVFileTypeQuickTimeMovie and AVAssetExportPresetPassthrough.
How to trim the video file and convert to 15 seconds video with iOS SDK?
Objective-C
-(void)cropVideo:(NSURL*)videoToTrimURL{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:videoToTrimURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *outputURL = paths[0];
NSFileManager *manager = [NSFileManager defaultManager];
[manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil];
outputURL = [outputURL stringByAppendingPathComponent:@"output.mp4"];
// Remove Existing File
[manager removeItemAtPath:outputURL error:nil];
exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = CMTimeMakeWithSeconds(1.0, 600); // you will modify time range here
CMTime duration = CMTimeMakeWithSeconds(15.0, 600);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
[self writeVideoToPhotoLibrary:[NSURL fileURLWithPath:outputURL]];
NSLog(@"Export Complete %d %@", exportSession.status, exportSession.error);
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"Failed:%@",exportSession.error);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Canceled:%@",exportSession.error);
break;
default:
break;
}
//[exportSession release];
}];
}
In Swift 4.0
static func cropVideo(atURL url:URL) {
let asset = AVURLAsset(url: url)
let exportSession = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
var outputURL = URL(string:NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last!)
let fileManager = FileManager.default
do {
try fileManager.createDirectory(at: outputURL!, withIntermediateDirectories: true, attributes: nil)
} catch {
}
outputURL?.appendPathComponent("output.mp4")
// Remove existing file
do {
try fileManager.removeItem(at: outputURL!)
}
catch {
}
exportSession.outputURL = outputURL
exportSession.shouldOptimizeForNetworkUse = true
exportSession.outputFileType = AVFileTypeQuickTimeMovie
let start = CMTimeMakeWithSeconds(1.0, 600) // you will modify time range here
let duration = CMTimeMakeWithSeconds(15.0, 600)
let range = CMTimeRangeMake(start, duration)
exportSession.timeRange = range
exportSession.exportAsynchronously {
switch(exportSession.status) {
case .completed: break
//
case .failed: break
//
case .cancelled: break
//
default: break
}
}
}
Failed to initialize an AVAssetExportSession (iPhone XS, XR, XMax)
Apparently it's an apple bug... https://bugreport.apple.com/web/?problemID=44701489
Will report back once the original bug is closed.
EDIT: This issue has been fixed by Apple in iOS 10.1 SDK. You just update your xcode to 10.1.
AVAssetExportSession giving me a green border on right and bottom of output video
Usually green lines appear after video cropping, problem is in video renderSize width, it should be multiply of 16.
Here some links about this:
apple 1
apple 2
Related Topics
How to Cut a Hole in a Sprite Image or Texture to Show What Is Behind It Using Spritekit in Swift
iOS Coredata Compatible with Both iOS 9 and iOS 10
Adding Data to a Specific UId in Firebase
Can't Update Label from Other Class in Swift
How to Download Datas from Multiple Url in Concurrency Mode
Swift: How to Continuously Send an Action from a Nstextfield
Call Function on App Termination in Swift
Protocol Variable Implementing Another Protocol
Swift-Animate Cashapelayer Stroke Color
Exc_Badinstruction When Computing a Hash Value
Swiftui Conditional View Transitions Are Not Working
Using a Swiftui List Sidebar in a UIsplitviewcontroller
How to Bind My Array Controller to My Core Data Model
Calculating Delta in Spritekit Using Swift
What's The How to Access a Swift Package Item from Objective-C
Nstimer Scheduledtimerwithtimeinterval and Target Is "Class Level Function"