iosswifttrimavassetexportsessionuivideoeditorcontroller

how to trim a video in swift for a particular time


I am working on a task in which I have to trim the recorded video from particular start point to particular end point as entered or selected by user. How am I supposed to do that. As I used UIVideoEditorController before but I don't want to use the default view and I want to trim the video directly.

let FinalUrlTosave = NSURL(string: "\(newURL)")
    exportSession!.outputURL=FinalUrlTosave
    exportSession!.shouldOptimizeForNetworkUse = true
    // exportSession.outputFileType = AVFileTypeQuickTimeMovie
    exportSession!.outputFileType = AVFileTypeQuickTimeMovie;
    let start:CMTime
    let duration:CMTime
    var st = starttime.doubleValue
    var ed = endTime.doubleValue
    start = CMTimeMakeWithSeconds(st, 600)
    duration = CMTimeMakeWithSeconds(ed, 600)
    // let timeRangeForCurrentSlice = CMTimeRangeMake(start, duration)
    let range = CMTimeRangeMake(start, duration);
    exportSession!.timeRange = range

       exportSession!.exportAsynchronouslyWithCompletionHandler({
        switch exportSession!.status{
        case  AVAssetExportSessionStatus.Failed:

            print("failed \(exportSession!.error)")
        case AVAssetExportSessionStatus.Cancelled:
            print("cancelled \(exportSession!.error)")
        default:
            print("complete....complete")
            //                self.SaveVideoToPhotoLibrary(destinationURL1!)

        }
    })

I am trying to achieve my goal using this but not succeeding.

Error message:

failed Optional(Error Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo={NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3-C020CE4AA9D4/Documents/moment/jGq_9AUFa47s2ZiiPP4x.mp4, NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3-C020CE4AA9D4/Documents/moment/jGq_9AUFa47s2ZiiPP4x.mp4, NSLocalizedDescription=The requested URL was not found on this server., NSUnderlyingError=0x1553c220 {Error Domain=N

Error occured second time:

failed Optional(Error Domain=NSURLErrorDomain Code=-3000 "Cannot create file" UserInfo={NSUnderlyingError=0x14e00000 {Error Domain=NSOSStatusErrorDomain Code=-12124 "(null)"}, NSLocalizedDescription=Cannot create file})


Solution

  • I found my solution using this method and it works like a charm....

    func cropVideo(sourceURL1: NSURL, statTime:Float, endTime:Float)
    {
        let manager = NSFileManager.defaultManager()
        
        guard let documentDirectory = try? manager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) else {return}
        guard let mediaType = "mp4" as? String else {return}
        guard let url = sourceURL1 as? NSURL else {return}
        
        if mediaType == kUTTypeMovie as String || mediaType == "mp4" as String {
            let asset = AVAsset(URL: url)
            let length = Float(asset.duration.value) / Float(asset.duration.timescale)
            print("video length: \(length) seconds")
            
            let start = statTime
            let end = endTime
            
            var outputURL = documentDirectory.URLByAppendingPathComponent("output")
            do {
                try manager.createDirectoryAtURL(outputURL, withIntermediateDirectories: true, attributes: nil)
                let name = Moment.newName()
                outputURL = outputURL.URLByAppendingPathComponent("\(name).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)")
                   self.saveVideoTimeline(outputURL)
                case .Failed:
                    print("failed \(exportSession.error)")
                    
                case .Cancelled:
                    print("cancelled \(exportSession.error)")
                    
                default: break
                }
            }
        }
    }
    

    Swift 5

        func cropVideo(sourceURL1: URL, statTime:Float, endTime:Float)
    {
        let manager = FileManager.default
    
        guard let documentDirectory = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else {return}
        let mediaType = "mp4"
        if mediaType == kUTTypeMovie as String || mediaType == "mp4" as String {
            let asset = AVAsset(url: sourceURL1 as URL)
            let length = Float(asset.duration.value) / Float(asset.duration.timescale)
            print("video length: \(length) seconds")
    
            let start = statTime
            let end = endTime
    
            var outputURL = documentDirectory.appendingPathComponent("output")
            do {
                try manager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
                outputURL = outputURL.appendingPathComponent("\(UUID().uuidString).\(mediaType)")
            }catch let error {
                print(error)
            }
    
            //Remove existing file
            _ = try? manager.removeItem(at: outputURL)
    
    
            guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {return}
            exportSession.outputURL = outputURL
            exportSession.outputFileType = .mp4
    
            let startTime = CMTime(seconds: Double(start ), preferredTimescale: 1000)
            let endTime = CMTime(seconds: Double(end ), preferredTimescale: 1000)
            let timeRange = CMTimeRange(start: startTime, end: endTime)
    
            exportSession.timeRange = timeRange
            exportSession.exportAsynchronously{
                switch exportSession.status {
                case .completed:
                    print("exported at \(outputURL)")
                case .failed:
                    print("failed \(exportSession.error)")
    
                case .cancelled:
                    print("cancelled \(exportSession.error)")
    
                default: break
                }
            }
        }
    }