AVAssetExportSession работает только первые 6 раз

Обновлен пример кода, вывод консоли и информация

Я пытаюсь получить общую продолжительность видеокомпозиции, разделить ее на 10, округлить, затем прокрутить и соединить видеокомпозицию с этими интервалами.

Это работает, но после того, как «currentDuration» становится 60+, он выдает «Запрошенный URL-адрес не найден на этом сервере».

По сути, если он определяет, что ему нужно создать 9 клипов, он преуспевает в первых 6 и терпит неудачу в остальных 3. Также мой numLoop не работает должным образом, кажется, что цикл while заканчивается до того, как будет предпринята попытка любого из 9 клипов.

Были бы рады получить помощь или советы по экспорту всех 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

person socca1157    schedule 20.08.2016    source источник
comment
Цикл while завершается до экспорта, потому что он запускает десять асинхронных операций экспорта. Поток не блокируется во время завершения, поэтому вы можете установить обработчик завершения. Что происходит в exportDidFinish? Мы можем видеть?   -  person ncke    schedule 20.08.2016
comment
@ncke Спасибо, я добавил метод exportDidFinish.   -  person socca1157    schedule 20.08.2016
comment
Спасибо, смотрю...   -  person ncke    schedule 20.08.2016
comment
Что случилось с экспортом... 0 и т. д. в журнале консоли, они появились или сразу под номером 6?   -  person ncke    schedule 20.08.2016
comment
@ncke Спасибо, это весь вывод консоли, начиная с 6 вместо 0. Сейчас читаю ваш ответ.   -  person socca1157    schedule 20.08.2016


Ответы (1)


Хорошо, немного новостей.

  1. ALAssetsLibrary устарела, начиная с iOS 8, и Apple перевела всех на Photos Framework, чтобы сделать это. Хорошей новостью является то, что AVAssetExportSession не устарела. Хотя вы можете продолжать использовать устаревший API, было бы неплохо переписать эту функцию exportDidFinish для использования нового API.

  2. Цикл while в функции splitVideo выбрасывает десять одновременных операций экспорта. Если честно, это немного догадка, но я подозреваю, что когда вы доберетесь до клипа 6, возникнет конфликт ресурсов.

Так что это нужно переделать, чтобы сделать его более дружелюбным. Лучше всего использовать 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

Это делается для того, чтобы операции экспорта выполнялись по одной, а не по одной попытке сразу. Если это удастся, вы можете поэкспериментировать с увеличением maxConcurrentOperationsCount, чтобы добиться многопоточности.

person ncke    schedule 20.08.2016
comment
Я ценю вашу помощь до сих пор. Я реализовал ваш пример, и вывод консоли показывает это, но, как ни странно, он все еще терпит неудачу 3/9 раз. Журнал консоли для ограничения количества символов здесь: justpaste.it/xiu0 - person socca1157; 20.08.2016
comment
В exportDidFinish вы можете изменить outputURL оператора if на outputURL.path следующим образом: if(library.videoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL.path)) и также добавить предложение else к этому оператору if для регистрации в случае несовместимости. - person ncke; 20.08.2016
comment
Мне пришлось немного изменить его для сборки, но я придумал: if(library.videoAtPathIsCompatibleWithSavedPhotosAlbum(NSURL(string: outputURL.path!))) Оператор else регистрирует последние 3 клипа с ошибкой. Тем не менее дает сообщение об ошибке не может быть найдено. - person socca1157; 21.08.2016
comment
Хмм хорошо. Не могли бы вы скинуть класс в justpaste? - person ncke; 21.08.2016
comment
Спасибо. Мне нужно отследить MP4 и попробовать это для себя. Здесь уже поздно (Великобритания), хорошо, если я вернусь к этому завтра? - person ncke; 21.08.2016
comment
Абсолютно, еще раз спасибо. Я также готов использовать AVFileTypeQuickTimeMovie, если он того стоит. - person socca1157; 21.08.2016
comment
Я заметил, что если видео длится менее 60 секунд, оно имеет 100% -ный успех. Любое видео, которое я выберу более 60 секунд, не будет работать на 7-м клипе. - person socca1157; 21.08.2016
comment
Пошел на миссию: я думаю, что это все, что я могу получить. pastebin.com/9KYMKEVZ - person ncke; 21.08.2016
comment
Спасибо за это, сейчас будем работать над интеграцией классов. - person socca1157; 22.08.2016