【问题标题】:AVAssetExportSession with outputFileType m4a not working iOS13带有 outputFileType m4a 的 AVAssetExportSession 无法正常工作 iOS13
【发布时间】:2020-01-30 22:43:33
【问题描述】:

我怀疑 Xcode 11 和 iOS13 不能正常工作 Xcode 10.2.1 和 iOS12.2 工作正常

我试图将两个音频文件合并为一个音频文件。

下面的代码在 Xcode 10.2.1 和 iOS 12.2 上运行良好,但现在在 xcode 11 和 iOS13 上运行

   @objc func applyMergeAudio(){

        playmerge(audio1: Bundle.main.url(forResource: "audio0", withExtension: "mp3")!,audio2: Bundle.main.url(forResource: "Asteroid_Sound", withExtension: "mp3")!)
    }

    func playmerge(audio1: URL, audio2:  URL)
    {
        let composition = AVMutableComposition()
        let compositionAudioTrack1:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
        let compositionAudioTrack2:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!

        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let fileDestinationUrl = documentDirectoryURL.appendingPathComponent("resultmerge.m4a")

        let filemanager = FileManager.default
        if (!filemanager.fileExists(atPath: fileDestinationUrl.path))
        {
            do
            {
                try filemanager.removeItem(at: fileDestinationUrl)
            }
            catch let error as NSError
            {
                NSLog("Error: \(error)")
            }
        }

        let avAsset1 = AVURLAsset(url: audio1, options: nil)
        let avAsset2 = AVURLAsset(url: audio2, options: nil)

        var tracks1 = avAsset1.tracks(withMediaType: AVMediaType.audio)
        var tracks2 = avAsset2.tracks(withMediaType: AVMediaType.audio)

        let assetTrack1:AVAssetTrack = tracks1[0]
        let assetTrack2:AVAssetTrack = tracks2[0]

        let duration1: CMTime = assetTrack1.timeRange.duration
        let duration2: CMTime = assetTrack2.timeRange.duration

        let timeRange1 = CMTimeRangeMake(start: CMTime.zero, duration: duration1)
        let timeRange2 = CMTimeRangeMake(start: CMTime.zero, duration: duration2)
        do
        {
            try compositionAudioTrack1.insertTimeRange(timeRange1, of: assetTrack1, at: CMTime.zero)
            try compositionAudioTrack2.insertTimeRange(timeRange2, of: assetTrack2, at: CMTime.zero)
        }
        catch
        {
            print(error)
        }

        //below line force unwarp Version xcode 10.2.1 working fine with iOS12.2. but xcode 11 with iOS13 got crush . .
        let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
        assetExport?.outputFileType = AVFileType.m4a
        assetExport?.outputURL = fileDestinationUrl
        assetExport?.exportAsynchronously(completionHandler:
            {
                //xcode 11 with iOS13 not fire this block but xcode 10.2.1 with iOS12.2 working fine.
                print(fileDestinationUrl)
        })
    }

所以你会告诉我任何替代解决方案还是我错过了什么?

【问题讨论】:

    标签: ios swift xcode ios13 ios12


    【解决方案1】:

    与其说是一个答案,但很难将所有这些作为评论传达。

    Per AppleAVAssetExportSession 上有一个你可以调用名为 allExportPresets() 的函数,它将输出所有可用的预设。

    您还可以使用您的AVAsset 致电exportPresets(compatibleWith:),以查找与该特定资产兼容的产品。

    当我使用 iOS 12 调用 allExportPresets() 时,我得到以下输出:

    ["AVAssetExportPreset1920x1080", "AVAssetExportPresetLowQuality", "AVAssetExportPresetAppleM4A", "AVAssetExportPresetHEVCHighestQuality", "AVAssetExportPreset640x480", "AVAssetExportPreset3840x2160", "AVAssetExportPresetHEVC3840x2160", "AVAssetExportPresetHighestQuality", "AVAssetExportPreset1280x720", "AVAssetExportPresetMediumQuality", "AVAssetExportPreset960x540", "AVAssetExportPresetHEVC1920x1080"]

    虽然使用 iOS 13 调用相同的函数,但我得到:

    []

    但是,当我查看各种预设的支持页面时,我找不到任何说明它们已被弃用等的文档。

    我可以稍后尝试测试,看看是否可以添加。

    希望这至少可以为现在提供一些指导。

    【讨论】:

    【解决方案2】:

    试试这个功能,别忘了导入这些库:

    导入 AVFoundation
    导入 AVKit
    导入资产库

    func getAVMix(audioPath: String, videoPath: String, _ completionHandler: @escaping AVMIXResult) {

        let video = Bundle.main.url(forResource: videoPath, withExtension: fileExtension.mp4)! as NSURL
        let audio = Bundle.main.url(forResource: audioPath, withExtension: fileExtension.mp3)! as NSURL
        
        //Create the AVmutable composition to add tracks
        let composition = AVMutableComposition()
        //Create assests url for first video
        let video1 = AVURLAsset(url: video as URL, options: nil)
        
        //Create the mutable composition track with video media type. You can also create the tracks depending on your need if you want to merge audio files and other stuffs.
        let composedTrack: AVMutableCompositionTrack? = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
        //Set the video time ranges of both the videos in composition
        
        if video1.tracks(withMediaType: .video).count > 0 {
            do {
                try? composedTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video1.duration), of: video1.tracks (withMediaType: .video)[0], at: kCMTimeZero)
            } /*catch let error { print("Error by Developer ", error.localizedDescription) }*/
        }
        
        let audioAsset = AVAsset(url: audio as URL)
        
        let audioTrack: AVMutableCompositionTrack? = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        
        let anIndex = audioAsset.tracks(withMediaType: .audio)[0]
        try? audioTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, video1.duration), of: anIndex, at: kCMTimeZero)
        // Create a temp path to save the video in the documents dir.
        
        let url  = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(mergeFile)
        
        // Create the export session to merge and save the video
        let exporter        = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetMediumQuality)
        exporter?.outputURL = url
        
        exporter?.outputFileType                = AVFileType(exporterFileType)
        exporter?.shouldOptimizeForNetworkUse   = true
        
        exporter?.exportAsynchronously(completionHandler: {
            switch exporter?.status {
            case .failed?:
                FileManager().clearTmpDirectory()
                completionHandler("Merge failed", false)             //print("Failed to export video")
            case .cancelled?:
                FileManager().clearTmpDirectory()
                completionHandler("Merge cancelled", false)         //print("export cancelled")
            case .completed?:
                //Here you go you have got the merged video :)
                completionHandler(mergeFile, true)                //print("Merging completed")
            default:
                break
            }
        })
        
    }
    

    【讨论】:

    • @jrswgtr 请检查
    【解决方案3】:

    我遇到了与@nazmul 提到的相同的问题。

    这是 Xcode 11.1 中的一个问题。尝试在 Xcode 11.2 中运行相同的代码,它会正常工作。我也测试过。

    根据苹果 Xcode 11.2 的发行说明,他们已经解决了这个问题。

    在 AVAssetExportSession 中,allExportPresets() 类型方法现在返回 iPhone 11、iPhone 11 Pro 和 iPhone 11 Pro Max 模拟器中的预设。 (55659811)

    这是相同的参考链接。 https://developer.apple.com/documentation/xcode_release_notes/xcode_11_2_release_notes

    参考:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-26
      • 2018-11-03
      • 2020-05-17
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多