AVAssetExportSession gives me AVFoundationErrorDomain Code=-11800 - swift

I am facing the same issues in ios 13.3 in real device it is working in ios 13.2 simulator but gives below error.
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could
not be completed" UserInfo={NSLocalizedFailureReason=An unknown error
occurred (-17508), NSLocalizedDescription=The operation could not be
completed, NSUnderlyingError=0x2816d11d0 {Error
Domain=NSOSStatusErrorDomain Code=-17508 "(null)"}}
Here is my code I want to convert .mov file to mp4.
class func encodeVideo(at videoURL: String, completionHandler: ((URL?, Error?) -> Void)?) {
let avAsset = AVURLAsset(url: URL.init(fileURLWithPath: videoURL), options: nil)
let startDate = Date()
//Create Export session
guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) else {
completionHandler?(nil, nil)
return
}
//Creating temp path to save the converted video
let filename = "Video_\(Date().timeIntervalSince1970).mp4"
// Below Folder Path used tor getting directory path
let strfilePath = (FolderPath.temporaryDirectory.getDirectoryPath as NSString).appendingPathComponent(filename)
let filePath = URL.init(fileURLWithPath: strfilePath)
//Check if the file already exists then remove the previous file
if FileManager.default.fileExists(atPath: filePath.path) {
do {
try FileManager.default.removeItem(at: filePath)
} catch {
completionHandler?(nil, error)
}
}
exportSession.outputURL = filePath
exportSession.outputFileType = AVFileType.mp4
exportSession.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
exportSession.timeRange = range
exportSession.exportAsynchronously(completionHandler: {() -> Void in
switch exportSession.status {
case .failed:
print(exportSession.error ?? "NO ERROR")
completionHandler?(nil, exportSession.error)
case .cancelled:
print("Export canceled")
completionHandler?(nil, nil)
case .completed:
//Video conversion finished
let endDate = Date()
let time = endDate.timeIntervalSince(startDate)
print(time)
print("Successful!")
print(exportSession.outputURL ?? "NO OUTPUT URL")
completionHandler?(exportSession.outputURL, nil)
default: break
}
})
}

let strfilePath = (FolderPath.temporaryDirectory.getDirectoryPath as NSString).appendingPathComponent(filename)
you cannot store in that folder directly, but you need to store your file in a subfolder, e.g. like this:
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
let strfilePath = documentDirectoryURL.appendingPathComponent("Subfolder/filename.mp4") as URL
Further you can read this article

Finally, I solve my issues by using AVMutableComposition not directly using AVURL asset. I adding audio and video track in AVMutableComposition.

This is the code I use to convert .mov to .mp4
var outputURL: URL!
func exportVideo(key:String, inputurl: URL, presetName: String, outputFileType: AVFileType = .mp4, fileExtension: String = "mp4", then completion: #escaping (URL?) -> Void) {
let asset = AVAsset(url: inputurl)
outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(key)
if let session = AVAssetExportSession(asset: asset, presetName: presetName) {
session.outputURL = outputURL
session.outputFileType = outputFileType
session.shouldOptimizeForNetworkUse = true
session.exportAsynchronously {
switch session.status {
case .completed:
completion(self.outputURL)
case .cancelled:
debugPrint("Video export cancelled.")
completion(nil)
case .failed:
let errorMessage = session.error?.localizedDescription ?? "n/a"
debugPrint("Video export failed with error: \(errorMessage)")
completion(nil)
default:
break
}
}
} else {
completion(nil)
}
}
And then I call this function to get the output URL of the converted file and use it
exportVideo(key: key, inputurl: path, presetName: AVAssetExportPresetHighestQuality, outputFileType: .mp4, fileExtension: "mp4") { (outputURL) in
// do whatever with the file here
}

For anyone stuck in this frustrating error. Use a AVmutablecomposition as export asset.
Sample code for trimming a video:
let manager = FileManager.default
guard let documentDirectory = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else { print("TRIM Failed to access directory")
return}
let mediaType = "mp4"
if mediaType == kUTTypeMovie as String || mediaType == "mp4" as String {
let asset = AVAsset(url:videoURL!)
let length = Float(asset.duration.value) / Float(asset.duration.timescale)
print("TRIM video length: \(length) seconds")
let composition = AVMutableComposition()
let audioTrack: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)!
let videoTrack: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)!
var outURL_speed=documentDirectory.appendingPathComponent("output")
var outputURL = documentDirectory.appendingPathComponent("output")
do {
try audioTrack.insertTimeRange(CMTimeRangeFromTimeToTime(start: self.startTime, end: self.endTime), of: asset.tracks(withMediaType: AVMediaType.audio)[0], at: CMTime.zero)
try videoTrack.insertTimeRange(CMTimeRangeFromTimeToTime(start: self.startTime, end: self.endTime), of: asset.tracks(withMediaType: AVMediaType.video)[0], at: CMTime.zero)
try manager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
outputURL = outputURL.appendingPathComponent("preVideo-\(self.postID).\(mediaType)")
outURL_speed = outURL_speed.appendingPathComponent("Video-\(self.postID).\(mediaType)")
print("TRIM output dir: \(outputURL)")
}catch let error {
print(error)
}
_ = try? manager.removeItem(at: outputURL)
guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {return}
exportSession.outputURL = outputURL
exportSession.shouldOptimizeForNetworkUse = true
exportSession.outputFileType = .mp4
let timeRange = CMTimeRange(start: self.startTime, end: self.endTime)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously{
switch exportSession.status {
case .completed:
print("TRIM exported at \(outputURL)")
self.changeSpeed(url: outputURL,outUrl:outURL_speed)
case .failed:
print("TRIM failed \(exportSession.error)")
case .cancelled:
print("TRIM cancelled \(exportSession.error)")
default: break
}
}

Related

Swift AVFoundation instructions don't set the opacity

I have a function that merges videos. All videos merge properly and the first two videos will play perfectly but then only the audio for the third video plays. I am assuming the video is there, but it is just blocked by the second video. I am confused though because I am using instructions to set the opacity of each asset to 0 when the video is done, but it doesn't work. Also even if I don't set any instructions, the first video disappears to allow the second video to play, but the second video never disappears. What is going on!?
func mergeVideo(completion: #escaping (_ url: URL?, _ error: Error?) -> Void) {
let mixComposition = AVMutableComposition()
let videoComposition = AVMutableVideoComposition()
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
completion(nil, nil)
return
}
let outputURL = documentDirectory.appendingPathComponent("\(id).mov")
do {
if FileManager.default.fileExists(atPath: outputURL.path) {
try FileManager.default.removeItem(at: outputURL)
}
} catch {
print(error.localizedDescription)
}
// If there is only one video, save export time.
if let video = videos.first, videos.count == 1 {
do {
if let url = URL(string: video.videoURL) {
try FileManager().copyItem(at: url, to: outputURL)
completion(outputURL, nil)
mergedVideoURL = outputURL.lastPathComponent
}
} catch let error {
completion(nil, error)
}
return
}
var currentTime = CMTime.zero
let renderSize = CGSize(width: 1280.0, height: 720.0)
let mainInstruction = AVMutableVideoCompositionInstruction()
videos.enumerated().forEach { index, video in
if let vidURL = URL(string: video.videoURL)?.lastPathComponent {
let url = documentDirectory.appendingPathComponent(vidURL)
let asset = AVAsset(url: url)
guard let assetTrack = asset.tracks.first else { return }
mainInstruction.timeRange = CMTimeRangeMake(start: .zero, duration: CMTimeAdd(mixComposition.duration, asset.duration))
let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack)
instruction.setOpacity(0.0, at: asset.duration)
mainInstruction.layerInstructions.append(instruction)
do {
let timeRange = CMTimeRangeMake(start: .zero, duration: asset.duration)
try mixComposition.insertTimeRange(timeRange, of: asset, at: currentTime)
currentTime = CMTimeAdd(currentTime, asset.duration)
} catch let error {
completion(nil, error)
}
}
}//forEach
videoComposition.instructions = [mainInstruction]
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
videoComposition.renderSize = renderSize
guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetPassthrough) else {
completion(nil, nil)
return
}
exporter.outputURL = outputURL
exporter.outputFileType = .mov
// Pass Video Composition to the Exporter.
exporter.videoComposition = videoComposition
exporter.exportAsynchronously {
DispatchQueue.main.async {
switch exporter.status {
case .completed:
completion(exporter.outputURL, nil)
case .failed:
completion(exporter.outputURL, exporter.error)
case.cancelled:
completion(exporter.outputURL, exporter.error)
case .unknown:
completion(exporter.outputURL, exporter.error)
case .waiting:
print("waiting")
case .exporting:
print("exporting")
#unknown default:
completion(exporter.outputURL, exporter.error)
}
}
}
}

Swift - AVAssetExportSession exportSession.exportAsynchronously completion handler not called

I used this link and following code in my project but AVAssetExportSession - exportAsynchronously method completion handler doesn't called in my project:
StackLink
func encodeVideo(at videoURL: URL, completionHandler: ((URL?, Error?) -> ())?) {
let avAsset = AVURLAsset(url: videoURL, options: nil)
let startDate = Date()
//Create Export session
guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) else {
completionHandler?(nil, nil)
return
}
//Creating temp path to save the converted video
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("rendered-Video.mp4")
//Check if the file already exists then remove the previous file
if FileManager.default.fileExists(atPath: filePath.path) {
do {
try FileManager.default.removeItem(at: filePath)
} catch {
completionHandler?(nil, error)
}
}
exportSession.outputURL = filePath
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
exportSession.timeRange = range
exportSession.exportAsynchronously {
switch exportSession.status {
case .failed:
print(exportSession.error ?? "NO ERROR")
completionHandler?(nil, exportSession.error)
case .cancelled:
print("Export canceled")
completionHandler?(nil, nil)
case .completed:
//Video conversion finished
let endDate = Date()
let time = endDate.timeIntervalSince(startDate)
print(time)
print("Successful!")
print(exportSession.outputURL ?? "NO OUTPUT URL")
completionHandler?(exportSession.outputURL, nil)
case .unknown:
print("Export Unknown Error")
default: break
}
}
}
I also share my project on GitHub that you can check it,
thanks
GitRepo
I use Xcode 12.3
it was iOS bug even screen recording on my iOS device doesn't work, after i know this bug, I restart my phone and everything goes fine but this takes me some times to understand the solution.
I'm using iOS 14.3

Swift Export MP4 using AVAssetExportSession

I am trying to export an mp4 file within the documents directory. I am downloading that file from a remote URL and them attempting the trim it and create a new mp4 from the existing. Below is the code I am using the the exception that I am getting. This approach is working for .mov files and remote videos but not mp4.
func trimVideo(sourceURL: URL, startTime: Double, endTime: Double) {
let fileManager = FileManager.default
let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let asset = AVAsset(url: sourceURL)
let fileName = UUID().uuidString + ".mp4"
var outputURL = documentDirectory.appendingPathComponent("output")
do {
try fileManager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
outputURL = outputURL.appendingPathComponent(fileName)
}catch let error {
print(error)
}
//Remove existing file
try? fileManager.removeItem(at: outputURL)
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset640x480) else { return }
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileType.mp4
let timeRange = CMTimeRange(start: CMTime(seconds: startTime, preferredTimescale: 1000),
end: CMTime(seconds: endTime, preferredTimescale: 1000))
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
switch exportSession.status {
case .completed:
print(outputURL.absoluteString)
case .failed:
print("failed \(exportSession.error.debugDescription)")
case .cancelled:
print("cancelled \(exportSession.error.debugDescription)")
default: break
}
}
}
failed Optional(Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x600003f432a0 {Error Domain=NSOSStatusErrorDomain Code=-16979 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-16979), NSURL=PATH_TO_MY_FILE.mp4, NSLocalizedDescription=The operation could not be completed})
Surfacing Victor's own answer from his comment:
the problem was that I was not creating the url that I passed in with fileURLWithPath as follows. let fileURL = URL(fileURLWithPath: filePath)

Exporting mp4 through AVAssetExportSession fails

I start saying that I spent a lot of time searching through documentation, posts here and somewhere else, but I can't figure out the solution for this problem.
I'm using AVAssetExportSession for exporting an .mp4 file stored in a AVAsset instance.
What I do is:
I check the isExportable property of AVAsset
I then get an array of exportPresets compatible with the AVAsset instance
I take the AVAssetExportPreset1920x1080, or, if not existing I try to export the media with AVAssetExportPresetPassthrough (FYI, 100% of times, the preset I need is always contained in the list, but I tried also the passthrough option and it doesn't work anyway)
The outputFileType is AVFileTypeMPEG4 and I tried also by assigning the .mp4 extension to the file, but nothing makes it work.
I always receive this error
Error Domain=AVFoundationErrorDomain Code=-11838 "Operation Stopped"
UserInfo={NSUnderlyingError=0x600000658c30 {Error
Domain=NSOSStatusErrorDomain Code=-12109 "(null)"},
NSLocalizedFailureReason=The operation is not supported for this
media., NSLocalizedDescription=Operation Stopped}
Below is the code I'm using
func _getDataFor(_ item: AVPlayerItem, completion: #escaping (Data?) -> ()) {
guard item.asset.isExportable else {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: item.asset)
var preset: String = AVAssetExportPresetPassthrough
if compatiblePresets.contains(AVAssetExportPreset1920x1080) { preset = AVAssetExportPreset1920x1080 }
guard
let exportSession = AVAssetExportSession(asset: item.asset, presetName: preset),
exportSession.supportedFileTypes.contains(AVFileTypeMPEG4) else {
completion(nil)
return
}
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTimeMake(0, 1)
let timeRange = CMTimeRangeMake(startTime, item.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print("\(exportSession.error)")
let data = try? Data(contentsOf: tempFileUrl)
_ = try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
Seems like converting the AVAsset instance in a AVMutableComposition did the trick. If, please, anyone knows the reason why this works let me know.
This is the new _getDataFor(_:completion:) method implementation
func _getDataFor(_ item: AVPlayerItem, completion: #escaping (Data?) -> ()) {
guard item.asset.isExportable else {
completion(nil)
return
}
let composition = AVMutableComposition()
let compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let sourceVideoTrack = item.asset.tracks(withMediaType: AVMediaTypeVideo).first!
let sourceAudioTrack = item.asset.tracks(withMediaType: AVMediaTypeAudio).first!
do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceVideoTrack, at: kCMTimeZero)
try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, item.duration), of: sourceAudioTrack, at: kCMTimeZero)
} catch(_) {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: composition)
var preset: String = AVAssetExportPresetPassthrough
if compatiblePresets.contains(AVAssetExportPreset1920x1080) { preset = AVAssetExportPreset1920x1080 }
guard
let exportSession = AVAssetExportSession(asset: composition, presetName: preset),
exportSession.supportedFileTypes.contains(AVFileTypeMPEG4) else {
completion(nil)
return
}
var tempFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp_video_data.mp4", isDirectory: false)
tempFileUrl = URL(fileURLWithPath: tempFileUrl.path)
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTimeMake(0, 1)
let timeRange = CMTimeRangeMake(startTime, item.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print("\(tempFileUrl)")
print("\(exportSession.error)")
let data = try? Data(contentsOf: tempFileUrl)
_ = try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
Swift 5:
import Foundation
import AVKit
func getDataFor(_ asset: AVAsset, completion: #escaping (Data?) -> ()) {
guard asset.isExportable,
let sourceVideoTrack = asset.tracks(withMediaType: .video).first,
let sourceAudioTrack = asset.tracks(withMediaType: .audio).first else {
completion(nil)
return
}
let composition = AVMutableComposition()
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
do {
try compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: asset.duration), of: sourceVideoTrack, at: .zero)
try compositionAudioTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: asset.duration), of: sourceAudioTrack, at: .zero)
} catch {
completion(nil)
return
}
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: composition)
var preset = AVAssetExportPresetPassthrough
let preferredPreset = AVAssetExportPreset1920x1080
if compatiblePresets.contains(preferredPreset) {
preset = preferredPreset
}
let fileType: AVFileType = .mp4
guard let exportSession = AVAssetExportSession(asset: composition, presetName: preset),
exportSession.supportedFileTypes.contains(fileType) else {
completion(nil)
return
}
let tempFileUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("temp_video_data")
exportSession.outputURL = tempFileUrl
exportSession.outputFileType = fileType
let startTime = CMTimeMake(value: 0, timescale: 1)
let timeRange = CMTimeRangeMake(start: startTime, duration: asset.duration)
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
print(tempFileUrl)
print(String(describing: exportSession.error))
let data = try? Data(contentsOf: tempFileUrl)
try? FileManager.default.removeItem(at: tempFileUrl)
completion(data)
}
}
Check if you set delegate property for AVURLAsset correctly.
[self.playerAsset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
And conform to AVAssetResourceLoaderDelegate protocol.
That is all you need to do.
I had this same issue because I was adding an audio track to a video without audio. Removing the audio track fixed it.
I ran into this problem because the Microphone permission was off/denied. Once I set turned it on this error went away.
I solved this problem by removing the CompositionTrack with media type .audio and empty segments from the AVMutableComposition
if let audioTrack = exportComposition.tracks(withMediaType: .audio).first,
audioTrack.segments.isEmpty {
exportComposition.removeTrack(audioTrack)
}
I had the same error, when I try to ExportSession with AVAssetExportPresetPassthrough always fail and in my case I can't use another preset because I must have the same resolution like at origin video
I fixed
let asset = AVAsset(url: originUrl)
let videoTrack = asset.tracks( withMediaType: .video ).first! as AVAssetTrack
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(
width: videoTrack.naturalSize.width,
height: videoTrack.naturalSize.height
)
videoComposition.frameDuration = CMTime(
value: 1,
timescale: videoTrack.naturalTimeScale
)
let transformer = AVMutableVideoCompositionLayerInstruction(
assetTrack: videoTrack
)
transformer.setOpacity(1.0, at: CMTime.zero)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = timeRange
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
guard let exportSession = AVAssetExportSession(
asset: asset,
presetName: AVAssetExportPresetMediumQuality
) else {
return handleFailure(error: .mediaSavingError, completion: completion)
}
exportSession.videoComposition = videoComposition
exportSession.outputURL = outputUrl
exportSession.outputFileType = .mp4
exportSession.timeRange = timeRange
exportSession.exportAsynchronously { [weak self] in
"your code"
}
Forks great for me, and it's saved the same resolution as video before

Video Trimming failed with block AVAssetExportSessionStatus.Failed

I have converted this code to Swift language but i am getting this
Error: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x174278600 {NSUnderlyingError=0x170241d10 "The operation couldn’t be completed. (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed} in (case AVAssetExportSessionStatus.Failed).
Kindly help me to resolved this
func cropVideo(sourceURL: NSURL)
{
let asset = AVURLAsset(URL: sourceURL, options: nil)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)
var error : NSError?
let file = "Finaloutput.mp4"
/* let paths : AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]
let outputURL1 = paths[0] as? String*/
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
let outputURL1 = paths[0] as? String
let filemgr = NSFileManager.defaultManager()
filemgr.createDirectoryAtPath(outputURL1!, withIntermediateDirectories: true, attributes: nil, error: &error)
var outputURL = outputURL1!.stringByAppendingPathComponent(file)
filemgr.removeItemAtPath(outputURL, error: &error)
let FinalUrlTosave = NSURL(string: outputURL)
exportSession.outputURL=FinalUrlTosave
exportSession.shouldOptimizeForNetworkUse = true
// exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
let start:CMTime
let duration:CMTime
start = CMTimeMakeWithSeconds(1.0, 600)
duration = CMTimeMakeWithSeconds(19.0, 600)
// let timeRangeForCurrentSlice = CMTimeRangeMake(start, duration)
let range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range
let destinationURL1 = NSURL(string: outputURL)
exportSession.exportAsynchronouslyWithCompletionHandler({
switch exportSession.status{
case AVAssetExportSessionStatus.Failed:
println("failed \(exportSession.error)")
case AVAssetExportSessionStatus.Cancelled:
println("cancelled \(exportSession.error)")
default:
println("complete....complete")
self.SaveVideoToPhotoLibrary(destinationURL1!)
}
})
}
func SaveVideoToPhotoLibrary(outputFileURL: NSURL)
{
assetsLibrary = ALAssetsLibrary()
let videoURL = outputFileURL as NSURL?
if let library = assetsLibrary{
if let url = videoURL{
library.writeVideoAtPathToSavedPhotosAlbum(url,
completionBlock: {(url: NSURL!, error: NSError!) in
print(url)
if let theError = error{
print("Error happened while saving the video")
print("The error is = \(theError)")
} else {
print("no errors happened")
}
})
} else {
print("Could not find the video in the app bundle")
}
}
}
Found Solution :
I have change this line and it works for me
let FinalUrlTosave = NSURL(fileURLWithPath: outputURL)
instead of
let FinalUrlTosave = NSURL(string: outputURL)
I was not getting exact path.