简体   繁体   中英

AVAssetExportSession fails to convert .mov from photo library. Why?

Scenario:
I wish to reduce the size of individual videos from my iTouch photo library.

1. Collect videoAssets from library.
2. Get a thumbnail of the PHAsset - works.
3. Get the actual video from the library.
4. Request the AVAssetForVideo from the library.
5. Convert the video via ExportSessions... loading assorted parameters.
6. Attempt to run the export into a tmp directory for use.
* FAILS *

Here's the debug output:

在此输入图像描述

Here's the error message:
在此输入图像描述

func getVideoFromPhotoLibrary() {
    let videoAssets =  PHAsset.fetchAssetsWithMediaType(.Video, options:nil)

    videoAssets.enumerateObjectsUsingBlock {
        (obj:AnyObject!, index:Int, stop:UnsafeMutablePointer<ObjCBool>) in
        let mySize = CGSizeMake(120,120)
        let myAsset = obj as! PHAsset

        let imageManager = PHImageManager.defaultManager()
        var myVideo:BlissMedium?

        // Request the poster frame or the image of the video
        imageManager.requestImageForAsset(myAsset, targetSize:mySize, contentMode: .AspectFit, options: nil) {
            (imageResult, info) in
            let thumbnail = UIImage(named:"videoRed")
            myVideo = BlissMedium(blissImage: imageResult, creationDate:myAsset.creationDate)
            myVideo!.mediumType = .video
        }

        // Actual Video:
        imageManager.requestAVAssetForVideo(myAsset, options: nil, resultHandler: {result, audio, info in
            let asset = result as! AVURLAsset
            let mediaURL = asset.URL
            let session = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality)
            let filename = "composition.mp4"


            session.outputURL = NSURL(string: NSTemporaryDirectory());
            session.outputFileType = AVFileTypeQuickTimeMovie;

            session.exportAsynchronouslyWithCompletionHandler({ () -> Void in
                dispatch_async(dispatch_get_main_queue(), {
                    if session.status == AVAssetExportSessionStatus.Completed {
                        println("Success")
                    }
                    else {
                        println(session.error?.localizedDescription)
                        //The requested URL was not found on this server.
                    }
                })
            })
        })

        if nil != myVideo {
            self.gBlissVideoMedia.append(myVideo!)
        }
    }
}


I checked to be sure the target path/file exist; then I added the 'AVFileTypeMPEG4' output type to match the intended .mp4:

let targetDir = createTempDirectory("bliss/composition.mp4") as String?

if NSFileManager.defaultManager().fileExistsAtPath(targetDir!) {
    println("*** file exists! ***")
} else {
    return
}
session.outputURL = NSURL(string: targetDir!);
session.outputFileType = AVFileTypeMPEG4

I'm still having problems:

* file exists! *

Optional("The operation could not be completed")

What am I doing wrong; what's missing?


Update:
I'm able to successfully run the export to my NSHomeDirectory() vs NSTemporaryDictory() in Objective-C.

However... the same code written in Swift fails.

I notice a change in absolute path to the target output in Swift, not found in Objective-C:
在此输入图像描述

Perhaps it's a Swift 1.2 bug???

I am not sure if you can save in the root of the temp directory, I normally use this function to create a new temp directory that I can use:

func createTempDirectory(myDir: String) -> String? {
    let tempDirectoryTemplate = NSTemporaryDirectory().stringByAppendingPathComponent(myDir)

    let fileManager = NSFileManager.defaultManager()

    var err: NSErrorPointer = nil
    if fileManager.createDirectoryAtPath(tempDirectoryTemplate, withIntermediateDirectories: true, attributes: nil, error: err) {
        return tempDirectoryTemplate
    } else {
        return nil
    }
}

Try to make your conversion in the directory returned by this function.

I hope that helps you!

I didn't quite understand what that last part of code did, where you find out if a file exists or not. Which file is it you are locating?

Since I didn't understand that then this might be irrelevant, but in your topmost code I notice that you set the filename to composition.mp4 , but let the outputURL be NSURL(string: NSTemporaryDirectory()) . With my lack of Swiftness I might be missing something, but it seems to me as if you're not using the filename at all, and are trying to write the file as a folder. I believe setting a proper URL might fix the problem but I'm not sure. An Objective-c-example of this could be:

NSURL * outputURL = [[NSURL alloc] 
    initFileURLWithPath:[NSString pathWithComponents:
    @[NSTemporaryDirectory(), @"composition.mp4"]]];

The outputURL is supposed to point to the actual file, not the folder it lies in. I think..

Anyway, if that doesn't work I do have a few other thoughts as well. Have you tried it on an actual device? There may be a problem with the simulator.

Also, sadly, I have gotten the error -12780 countless times with different root-problems, so that doesn't help very much.

And, I see you check if session.status == AVAssetExportSessionStatus.Completed , have you checked what the actual status is? Is it .Failed , or perhaps .Unknown ? There are several statuses.

This might be a long shot, but in one of my apps I am using the camera to capture video/audio, then encode/convert it using AVAssetExportSession . There were strange errors when starting to record, as well as after recording(exporting). I found out that I could change the AVAudioSession , which apparently has something to do with how the device handles media. I have no idea how to Swift, but here's my code (in viewDidAppear of the relevant view)

NSError *error;
AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];

[aSession setMode:AVAudioSessionModeVideoRecording error:&error];
[aSession setActive: YES error: &error];

The category PlayAndRecord allowed me to start the camera much faster, as well as getting rid of the occasional hanging AVAssetExportSessionStatus.Unknown and the occasional crash .Failed (which also threw the -12780 -error).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM