首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVAssetExportSession只工作前6次

AVAssetExportSession只工作前6次
EN

Stack Overflow用户
提问于 2016-08-20 17:50:22
回答 1查看 711关注 0票数 0

更新的代码示例、控制台输出和信息

我试图得到一个视频构图的总持续时间,除以10,集合,然后按这些间隔循环并拼接视频构图。

它可以工作,但是在'currentDuration‘变成60+之后,它会抛出一个“在此服务器上找不到所请求的URL”。

基本上,如果它确定它需要生成9个剪辑,那么它成功了前6个,而失败了另外3个。而且,我的numLoop没有像预期的那样工作,在尝试这9个剪辑之前,while循环几乎完成了。

希望得到一些帮助/洞察力,使所有9个剪辑导出.

我注意到,如果视频长度小于60秒,它的成功率是100%。任何我选择超过60秒的视频都会在第7段失败。

以下是我的方法:

代码语言:javascript
复制
func splitVideo(videoComposition: AVMutableVideoComposition) {


let fileManager = NSFileManager.defaultManager()
let documentsPath : String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]

//grab total duration/number of splits
let exporter: AVAssetExportSession = AVAssetExportSession(asset: asset!, presetName:AVAssetExportPresetHighestQuality)!
let totalDuration = Float64(CMTimeGetSeconds(exporter.asset.duration))
let totalDurationPieces = (totalDuration/10)
var numberOfSplits=Int(ceil(Double(totalDurationPieces)))

//prepare for loop
var loopNum : Int = 0
var currentDuration : Float64 = 0
var sessionNumber = (arc4random()%1000)

let opQueue = NSOperationQueue()
    opQueue.maxConcurrentOperationCount = 1

    while loopNum < numberOfSplits {

        //new exporter
        var destinationPath: String = documentsPath + "/splitVideo-"+String(sessionNumber)
        destinationPath+="-"+String(Int(loopNum))+".mp4"

        let new_exporter = AVAssetExportSession(asset: asset!, presetName:AVAssetExportPresetHighestQuality)!

        new_exporter.outputURL = NSURL(fileURLWithPath: destinationPath as String)
        new_exporter.videoComposition = videoComposition
        new_exporter.outputFileType = AVFileTypeMPEG4
        new_exporter.shouldOptimizeForNetworkUse = false

        new_exporter.timeRange = CMTimeRangeMake(
            CMTimeMakeWithSeconds(currentDuration, framesPerSecond!),CMTimeMakeWithSeconds(Float64(10),framesPerSecond!))

        // Set up the exporter, then:
        opQueue.addOperationWithBlock { () -> Void in
            new_exporter.exportAsynchronouslyWithCompletionHandler({
                dispatch_async(dispatch_get_main_queue(),{
                    print("Exporting... \(loopNum)")
                    self.exportDidFinish(new_exporter, loopNum: loopNum)
                })
            }) // end completion handler
        } // end block



        //prepare for next loop
        loopNum = loopNum+1
        currentDuration = currentDuration+10

    if(loopNum>=numberOfSplits){
        self.allExportsDone(Int(numberOfSplits))
        }
} // end while


}

下面是exportDidFinish方法:

代码语言:javascript
复制
func exportDidFinish(session: AVAssetExportSession, loopNum: Int) {
let outputURL: NSURL = session.outputURL!
let library: ALAssetsLibrary = ALAssetsLibrary()
if(library.videoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL)) {
    library.writeVideoAtPathToSavedPhotosAlbum(outputURL, completionBlock: {(url, error) in
//done
print("Success on \(Int(loopNum))")
})
}
}

以下是控制台输出:

代码语言:javascript
复制
Exporting... 9
2016-08-20 13:39:27.980 TrimVideo[4776:1576022] Video /var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-6.mp4 cannot be saved to the saved photos album: Error Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo={NSUnderlyingError=0x1457f43f0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}, NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-6.mp4, NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-6.mp4, NSURL=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-6.mp4, NSLocalizedDescription=The requested URL was not found on this server.}
Exporting... 9
2016-08-20 13:39:27.984 TrimVideo[4776:1576022] Video /var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-7.mp4 cannot be saved to the saved photos album: Error Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo={NSUnderlyingError=0x1457f88c0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}, NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-7.mp4, NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-7.mp4, NSURL=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-7.mp4, NSLocalizedDescription=The requested URL was not found on this server.}
Exporting... 9
2016-08-20 13:39:27.988 TrimVideo[4776:1576022] Video /var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-8.mp4 cannot be saved to the saved photos album: Error Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo={NSUnderlyingError=0x14687cb30 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}, NSErrorFailingURLStringKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-8.mp4, NSErrorFailingURLKey=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-8.mp4, NSURL=file:///var/mobile/Containers/Data/Application/BE125EB7-AFC4-48B5-95C3-941B420BB71F/Documents/splitVideo-972-8.mp4, NSLocalizedDescription=The requested URL was not found on this server.}
Exporting... 9
Success on 9
Exporting... 9
Success on 9
Exporting... 9
Success on 9
Exporting... 9
Success on 9
Exporting... 9
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-20 18:51:42

好吧,一些消息。

  1. ALAssetsLibrary从iOS 8开始就不再受欢迎了,苹果把每个人都转移到Photos来做这件事。好消息是,AVAssetExportSession没有受到反对。虽然您可以继续使用不推荐的API,但重写该exportDidFinish函数以使用新API可能是个好主意。
  2. splitVideo函数中的while循环抛出十个并发导出操作。老实说,这只是一个猜测,但我怀疑,一旦到了第6段,就会出现一些资源争用。

因此,这需要重新设计,使之更加友好。最好的选择是使用NSOperationQueue,将maxConcurrentOperationsCount设置为1(即串行队列)。

类似于:

代码语言:javascript
复制
let opQueue = NSOperationQueue()
opQueue.maxConcurrentOperationsCount = 1

for loopNum in 0..<numberOfSplits {

   // Set up the exporter, then:

    opQueue.addOperationWithBlock { () -> Void in
        new_exporter.exportAsynchronouslyWithCompletionHandler({
            dispatch_async(dispatch_get_main_queue(),{
                print("Exporting... \(loopNum)")
                self.exportDidFinish(new_exporter, loopNum: loopNum)
            })
        } // end completion handler
    } // end block

} // end while

这样做的目的是确保每次只运行一个导出操作,而不是一次尝试。如果成功的话,您可以尝试提高maxConcurrentOperationsCount来进行多线程处理。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39057099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档