0

更新されたコード サンプル、コンソール出力、および情報

ビデオ構成の合計時間を取得し、それを 10 で割り、切り上げてから、それらの間隔でビデオ構成をループしてスプライスしようとしています。

動作しますが、「currentDuration」が 60+ になると、「要求された URL はこのサーバーで見つかりませんでした」というメッセージがスローされます。

基本的に、9 つのクリップを生成する必要があると判断した場合、最初の 6 つが成功し、残りの 3 つが失敗します。

9 つのクリップすべてをエクスポートするためのヘルプ/洞察が欲しいです。

動画の長さが 60 秒未満の場合、成功率は 100% です。60 秒を超えるビデオを選択すると、7 番目のクリップで失敗します。

これが私の方法です:

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 メソッドは次のとおりです。

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

コンソール出力は次のとおりです。

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
4

1 に答える 1

1

わかりました、いくつかのニュース。

  1. ALAssetsLibrary は iOS 8 以降廃止され、Apple はこれを行うために全員を Photos Framework に移行しました。良いニュースは、AVAssetExportSession が廃止されていないことです。非推奨の API を引き続き使用することもできますが、そのexportDidFinish関数を書き直して新しい API を使用することをお勧めします。

  2. splitVideo 関数の while ループは、10 個の同時エクスポート操作をスローしています。正直なところ推測ですが、クリップ 6 に到達すると、リソースの競合が発生するのではないかと思います。

そのため、もう少しフレンドリーになるように再設計する必要があります。最善の策は、 を 1 に設定して使用することですNSOperationQueue(maxConcurrentOperationsCountつまり、シリアル キュー)。

何かのようなもの:

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

これの目的は、エクスポート操作が一度にすべて試行されるのではなく、一度に 1 つずつ実行されるようにすることです。maxConcurrentOperationsCountそれが成功した場合は、マルチスレッドを実行するためにを試してみることができます。

于 2016-08-20T18:51:42.447 に答える