AVAssetExportSession无法从照片库转换.mov。为什么呢?

时间:2015-06-07 22:43:00

标签: ios swift video avfoundation

场景:
我希望减少iTouch照片库中单个视频的大小。

1.从库中收集视频资产。
2.获取PHAsset的缩略图 - 有效。
3.从库中获取实际视频。
4.从库中请求AVAssetForVideo。
5.通过ExportSessions转换视频...加载各种参数。
6.尝试将导出运行到tmp目录以供使用。
* FAILS *

这是调试输出:

enter image description here

这是错误信息:
enter image description here

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!)
        }
    }
}


我检查确保目标路径/文件存在;然后我添加了'AVFileTypeMPEG4'输出类型以匹配预期的.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

我还有问题:

  

*文件存在! *

     

可选(“操作无法完成”)

我做错了什么;缺少什么?

<小时/> 更新:
我能够在Objective-C中成功运行导出到我的NSHomeDirectory()vs NSTemporaryDictory()。

但是......用Swift编写的相同代码失败了。

我注意到Swift中目标输出的绝对路径发生了变化,而在Objective-C中找不到:
enter image description here

也许这是一个Swift 1.2 bug ???

2 个答案:

答案 0 :(得分:0)

我不确定你是否可以保存在temp目录的根目录中,我通常使用这个函数创建一个我可以使用的新临时目录:

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
    }
}

尝试在此函数返回的目录中进行转换。

我希望能帮到你!

答案 1 :(得分:0)

我不太明白代码的最后一部分是做什么的,你在哪里找出文件是否存在。您找到的是哪个文件?

由于我不明白,这可能无关紧要,但在您最顶层的代码中,我注意到您将filename设置为composition.mp4,但让outputURL为{{ 1}}。由于我缺乏Swiftness,我可能会遗漏一些东西,但在我看来,好像你根本没有使用文件名,并试图将文件写为一个文件夹。我相信设置一个合适的URL可能会解决问题,但我不确定。一个Objective-c例子可能是:

NSURL(string: NSTemporaryDirectory())

outputURL应该指向实际文件,而不是它所在的文件夹。我想...

无论如何,如果这不起作用我也会有一些其他的想法。 你在实际的设备上试过吗?模拟器可能存在问题。

另外,遗憾的是,我已经无数次地遇到了错误NSURL * outputURL = [[NSURL alloc] initFileURLWithPath:[NSString pathWithComponents: @[NSTemporaryDirectory(), @"composition.mp4"]]]; 不同的根问题,所以这并没有多大帮助。

而且,我看到你检查-12780,你检查了实际状态是什么吗?是if session.status == AVAssetExportSessionStatus.Completed还是.Failed?有几种状态。

这可能是一个很长的镜头,但在我的一个应用程序中,我使用相机捕获视频/音频,然后使用.Unknown对其进行编码/转换。开始录制时以及录制(导出)后都会出现奇怪的错误。我发现我可以更改AVAssetExportSession,这显然与设备如何处理媒体有关。 我不知道如何使用Swift,但这是我的代码(在相关视图的viewDidAppear中)

AVAudioSession

类别NSError *error; AVAudioSession *aSession = [AVAudioSession sharedInstance]; [aSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]; [aSession setMode:AVAudioSessionModeVideoRecording error:&error]; [aSession setActive: YES error: &error]; 让我能够更快地启动相机,并且可以摆脱偶尔的悬挂PlayAndRecord和偶尔的坠机AVAssetExportSessionStatus.Unknown(它也会使{{1} }} - 误差)