PHImageManager. requestExportSessionForVideoでiCloud動画のダウンロードに失敗する問題


PHImageManager. requestExportSessionForVideoでiCloud動画のダウンロードに失敗する問題

PHImageManager-requestExportSessionForVideo:options:exportPreset:resultHandler: でiCloudにある動画のExportに失敗することがあったのでメモ

確認環境

  • iPhone6s(ストレージ使用率 98%くらい)
  • 4G回線
  • iCloudフォトライブラリ:ON
    • ストレージ最適化:ON

問題のコード


let opt = PHVideoRequestOptions()
opt.networkAccessAllowed = true
opt.deliveryMode = .MediumQualityFormat

let exportPreset = AVAssetExportPreset960x540

PHImageManager.defaultManager().requestExportSessionForVideo(strongSelf, options: opt, exportPreset: exportPreset) { (session: AVAssetExportSession?, info: [NSObject : AnyObject]?) in
    if let error = info?[PHImageErrorKey] as? NSError {
        log.error(error.debugDescription)
        return
    }

    guard let session = session else { return }

    session.outputURL = outputURL
    session.outputFileType = AVFileTypeQuickTimeMovie
    session.shouldOptimizeForNetworkUse = true

    session.exportAsynchronouslyWithCompletionHandler({
        switch session.status {
        case .Completed:
            // 完了時の処理
        case .Failed:
            if let err = session.error {
                log.error("Failed to export video. cause=\(err.description)")
            }
            session.outputURL?.fileRemove()
        default:
            log.error("Unexpected export status found. status=\(session.status)")
        }
    })
}

iCloudにあると思われる動画(PHImageResultIsInCloudKey: 1となる)の場合、以下のようなエラーがでて AVAssetExportSessionnilになる

PHImageErrorKey: Error Domain=CloudPhotoLibraryErrorDomain Code=81 "Error fetching asset with identifier: XXXXXXXXXXXXXXXXXX (nonpartial failure)"
UserInfo={NSLocalizedDescription=Error fetching asset with identifier: XXXXXXXXXXXXXX (nonpartial failure), NSUnderlyingError=0x17004e2e0 {Error Domain=CKErrorDomain Code=3 "インターネット接続がオフラインのようです。"

そのほかの通信は問題なくできてるので、ネットワークにはつながっているはずなのに

PHVideoRequestOptions.deliveryMode = .Automatic にしても状況変わらず。
Wi-Fiに接続すると問題なくExportできる。

回避策: requestAVAssetForVideo:options:resultHandler: を使う

requestAVAssetForVideo:options:resultHandler: を使い、自前でExportSessionを生成することで、無事Exportできるようになった。

let opt = PHVideoRequestOptions()
opt.networkAccessAllowed = true
opt.deliveryMode = .MediumQualityFormat

PHImageManager.defaultManager().requestAVAssetForVideo(strongSelf, options: opt, resultHandler: { (avasset, avaudioMix, info) in
    if let error = info?[PHImageErrorKey] as? NSError {
        log.error(error.debugDescription)
        return
    }

    guard let avasset = avasset else {
        return
    }

    guard let session = AVAssetExportSession(asset: avasset, presetName: AVAssetExportPreset960x540) else {
        return
    }

    session.outputURL = outputURL
    session.outputFileType = AVFileTypeQuickTimeMovie
    session.shouldOptimizeForNetworkUse = true

    session.exportAsynchronouslyWithCompletionHandler({
        switch session.status {
        case .Completed:
            // 完了時の処理
        case .Failed:
            if let err = session.error {
                log.error("Failed to export video. cause=\(err.description)")
            }
            session.outputURL?.fileRemove()
        default:
            log.error("Unexpected export status found. status=\(session.status)")
        }
    })
}

所感

  • iCloudにある動画のダウンロードは写真.appでも不安定なのでなんかおかしいのかなー。

参考