2
votes

I'm trying to use AVAssetExportSession on video selected in share extension and getting

Error Domain=NSURLErrorDomain Code=-3000 "Cannot create file" UserInfo={NSLocalizedDescription=Cannot create file, NSUnderlyingError=0x14811fdb0 {Error Domain=NSOSStatusErrorDomain Code=-12124 "(null)"}}

But I can create file manually at the same NSURL without an error. Here is a function I'm using

func reencodeVideo() {
    let videoAsset = AVURLAsset(URL: video.url)

    let videoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack
    print(videoTrack.estimatedDataRate)
    let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPreset1920x1080)
    guard let outputURL = uploadableFileURL else {
        return
    }
    let fileManager = NSFileManager.defaultManager()
    // let created = fileManager.createFileAtPath(outputURL.path!, contents: nil, attributes: nil)
    if let path = outputURL.path where fileManager.fileExistsAtPath(path) {
        print("file exists")
    }
    do {
        try fileManager.removeItemAtURL(outputURL)
        print("deleted")
    } catch {
        print(error)
    }
    exportSession?.outputURL = outputURL
    exportSession?.outputFileType = AVFileTypeQuickTimeMovie

    exportSession?.exportAsynchronouslyWithCompletionHandler{
        print(exportSession?.status)
    }
}

private var uploadableFileURL: NSURL? {
    guard let tempFileName = video.url.lastPathComponent else {
        return nil
    }
    let fileManager = NSFileManager.defaultManager()
    guard let containerURL = fileManager.containerURLForSecurityApplicationGroupIdentifier(Constants.appGroupIdentifier) else {
        return nil
    }
    return containerURL.URLByAppendingPathComponent("videoFile.mov")
}

I've successfully created file in the same directory, but AVAssetExportSession returns an error there. Any ideas what I'm doing wrong?

I've tried using AVAssetReader and AVAssetWriter, and AVAssetWriter returns same error when trying to start. Encode process completes successfully if I'm using Documents directory and fails only when using shared app group container.

2

2 Answers

3
votes

You're issue might be related to the use of the document folder and icloud sync. See https://forums.developer.apple.com/message/77495#77495

If you do something like :

guard let containerURL = fileManager.containerURLForSecurityApplicationGroupIdentifier(Constants.appGroupIdentifier) else {
        return nil
}

let libraryURL = containerURL.URLByAppendingPathComponent("Library", isDirectory: true)
let cachesURL = libraryURL.URLByAppendingPathComponent("Caches", isDirectory: true)
return cachesURL.URLByAppendingPathComponent("videoFile.mov")
-1
votes

I can't figure out from your code where your uploadableFileURL comes from, but the following works for me:

if let video = videoAsset {

    let fm = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask)
    let url = fm[0].URLByAppendingPathComponent("\(NSDate())").URLByAppendingPathExtension("mp4")

    let exporter = AVAssetExportSession(asset: video, presetName: AVAssetExportPreset3840x2160)
    exporter?.outputURL = url
    exporter?.outputFileType = AVFileTypeMPEG4
    exporter?.exportAsynchronouslyWithCompletionHandler() { _ in
    let data = NSData(contentsOfURL: url)
    }
}