如何在特定时间内快速修剪视频

时间:2016-02-29 09:40:32

标签: ios swift trim avassetexportsession uivideoeditorcontroller

我正在处理一项任务,我必须将录制的视频从特定的起点修剪为用户输入或选择的特定终点。 我该怎么做呢因为我之前使用过UIVideoEditorController但我不想使用默认视图,我想直接修剪视频。

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!)

        }
    })

我试图用这个来实现我的目标,但没有成功。

错误讯息:

  

失败可选(错误域= NSURLErrorDomain代码= -1100“   在此服务器上找不到请求的URL。“   的UserInfo = {NSErrorFailingURLStringKey =文件:///var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3-C020CE4AA9D4/Documents/moment/jGq_9AUFa47s2ZiiPP4x.mp4,   NSErrorFailingURLKey =文件:///var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3-C020CE4AA9D4/Documents/moment/jGq_9AUFa47s2ZiiPP4x.mp4,   NSLocalizedDescription =未找到请求的URL   server。,NSUnderlyingError = 0x1553c220 {Error Domain = N

第二次出现错误:

  

失败可选(错误域= NSURLErrorDomain代码= -3000“不能   创建文件“UserInfo = {NSUnderlyingError = 0x14e00000 {错误   Domain = NSOSStatusErrorDomain Code = -12124“(null)”},   NSLocalizedDescription =无法创建文件})

3 个答案:

答案 0 :(得分:20)

我找到了使用这种方法的解决方案,它就像一个魅力......

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
            }
        }
    }
}

答案 1 :(得分:0)

func cropVideo1(_ sourceURL1: URL, statTime:Float, endTime:Float){
        let videoAsset: AVAsset = AVAsset(url: sourceURL1) as AVAsset
        let composition = AVMutableComposition()
        composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())

        let videoComposition = AVMutableVideoComposition()
        videoComposition.renderSize = CGSize(width: 1280, height: 768)
        videoComposition.frameDuration = CMTimeMake(8, 15)

        let instruction = AVMutableVideoCompositionInstruction()
        let length = Float(videoAsset.duration.value)
        print(length)

        instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))

        let start = statTime
        let end = endTime

        let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPresetHighestQuality)!
        exportSession.outputFileType = AVFileTypeMPEG4

        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

        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"

        let date = Date()

        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        let outputPath = "\(documentsPath)/\(formatter.string(from: date)).mp4"
        let outputURL = URL(fileURLWithPath: outputPath)

        exportSession.outputURL = outputURL
        exportSession.outputFileType = AVFileTypeQuickTimeMovie
        print("sucess")
        exportSession.exportAsynchronously(completionHandler: { () -> Void in
            DispatchQueue.main.async(execute: {
                self.exportDidFinish(exportSession)
                print("sucess")


            })
        })
    }
    func exportDidFinish(_ session: AVAssetExportSession) {

        if session.status == AVAssetExportSessionStatus.completed {
            let outputURL = session.outputURL
            let library = ALAssetsLibrary()
            if library.videoAtPathIs(compatibleWithSavedPhotosAlbum: outputURL) {
                library.writeVideoAtPath(toSavedPhotosAlbum: outputURL) { alAssetURL, error in
                    if error != nil {
                        DispatchQueue.main.async(execute: {
                            print("Failed to save video")
                        })
                    } else {
                        DispatchQueue.main.async(execute: {
                            Print("Sucessfully saved Video")
                        })
                    }
                    self.activityIndicator.stopAnimating()
                }
            }
        }
    }

答案 2 :(得分:0)

这项工作可以解决旋转问题。

extension AVAsset {
    func assetByTrimming(startTime: CMTime, endTime: CMTime) throws -> AVAsset {
        let duration = CMTimeSubtract(endTime, startTime)
        let timeRange = CMTimeRange(start: startTime, duration: duration)

        let composition = AVMutableComposition()

        do {
            for track in tracks {
                let compositionTrack = composition.addMutableTrack(withMediaType: track.mediaType, preferredTrackID: track.trackID)
                compositionTrack?.preferredTransform = track.preferredTransform
                try compositionTrack?.insertTimeRange(timeRange, of: track, at: CMTime.zero)
            }
        } catch let error {
            throw TrimError("error during composition", underlyingError: error)
        }

        return composition
    }

struct TrimError: Error {
    let description: String
    let underlyingError: Error?

    init(_ description: String, underlyingError: Error? = nil) {
        self.description = "TrimVideo: " + description
        self.underlyingError = underlyingError
    }
}