У меня возникли некоторые проблемы при переносе проекта Obj-C на Swift.У меня есть метод, который предназначен для объединения массива видео.Однако проблема заключается в том, что когда я добавляю mutablevideocomposition к экспортеру, я получаю следующую ошибку.
Необязательно (Ошибка домена = AVFoundationErrorDomain Code = -11841 «Операция остановлена» UserInfo = {NSLocalizedFailureReason = Видео не можетсоставлятьвидео сливается вместе, но у меня нет инструкций по трансформации, и ориентация повсюду.Для простоты я добавил
var transform: CGAffineTransform = video.preferredTransform
вместо более сложного преобразования, но это все равно не имеет никакого значения.
// MARK: - MERGE THE VIDEOS
func mergeVideos( videoArray: [AVAsset] ){
// 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
let mixComposition = AVMutableComposition()
// Set the starting time
var currentTime = CMTime.zero;
let videoToAdd = mixComposition.addMutableTrack(withMediaType: AVMediaType.video,
preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
let audioToAdd = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio,
preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
var instructions: [AVVideoCompositionInstructionProtocol] = []
for video: AVAsset in videoArray {
do {
try videoToAdd!.insertTimeRange(CMTimeRange(start: CMTime.zero, duration: video.duration),
of: video.tracks(withMediaType: AVMediaType.video)[0],
at: currentTime)
} catch {
print("Failed to load first track")
return
}
do {
try audioToAdd?.insertTimeRange(CMTimeRange(start: CMTime.zero, duration: video.duration),
of: video.tracks(withMediaType: AVMediaType.audio)[0] ,
at: currentTime)
} catch {
print("Failed to load Audio track")
}
let videoCompositionInstruction = AVMutableVideoCompositionInstruction()
videoCompositionInstruction.timeRange = CMTimeRange(start: currentTime, duration: video.duration)
let layerInstruction = AVMutableVideoCompositionLayerInstruction()
var transform: CGAffineTransform = video.preferredTransform
layerInstruction.setTransform(transform, at: CMTime.zero)
videoCompositionInstruction.layerInstructions = [layerInstruction];
instructions.append(videoCompositionInstruction)
currentTime = CMTimeAdd(currentTime, video.duration)
}
// 4 - Get path
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first else {
return
}
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = dateFormatter.string(from: Date())
let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")
// 5 - Create Exporter
guard let exporter = AVAssetExportSession(asset: mixComposition,
presetName: AVAssetExportPresetHighestQuality) else {
return
}
// 6 - Setup The Video Composition
let mutableVideoComposition = AVMutableVideoComposition()
mutableVideoComposition.frameDuration = CMTime(seconds: 1, preferredTimescale: 12)
mutableVideoComposition.renderSize = CGSize(width: 1920, height: 1080)
mutableVideoComposition.instructions = instructions
exporter.outputURL = url
exporter.outputFileType = AVFileType.mov
exporter.shouldOptimizeForNetworkUse = true
exporter.videoComposition = mutableVideoComposition
// 6 - Perform the Export
exporter.exportAsynchronously() {
if(exporter.status == AVAssetExportSession.Status.completed){
DispatchQueue.main.async {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
//self.exportDidFinish(exporter)
}
}else {
print(exporter.status.rawValue)
print(exporter.error)
}
}
}