AVURLAsset возвращает пустой массив — попытка объединить два файла

Я пытаюсь объединить два (несколько) аудиофайлов. Я нашел соответствующий пост и решение по адресу Объединить два аудиофайла Swift< /а>

Вот решение:


func mergeAudioFiles(audioFileUrls: NSArray) {
    let composition = AVMutableComposition()

    for i in 0 ..< audioFileUrls.count {

        let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

        let asset = AVURLAsset(url: (audioFileUrls[i] as! NSURL) as URL)

        let track = asset.tracks(withMediaType: AVMediaTypeAudio)[0]

        let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: track.timeRange.duration)

        try! compositionAudioTrack.insertTimeRange(timeRange, of: track, at: composition.duration)
    }

    let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
    self.mergeAudioURL = documentDirectoryURL.appendingPathComponent("FinalAudio.m4a")! as URL as NSURL

    let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
    assetExport?.outputFileType = AVFileTypeAppleM4A
    assetExport?.outputURL = mergeAudioURL as URL
    assetExport?.exportAsynchronously(completionHandler:
        {
            switch assetExport!.status
            {
            case AVAssetExportSessionStatus.failed:
                print("failed \(assetExport?.error)")
            case AVAssetExportSessionStatus.cancelled:
                print("cancelled \(assetExport?.error)")
            case AVAssetExportSessionStatus.unknown:
                print("unknown\(assetExport?.error)")
            case AVAssetExportSessionStatus.waiting:
                print("waiting\(assetExport?.error)")
            case AVAssetExportSessionStatus.exporting:
                print("exporting\(assetExport?.error)")
            default:
                print("Audio Concatenation Complete")
            }
    })
}

Некоторые параметры устарели, и я использовал предложенные исправления из Xcode, в результате чего:

        let composition = AVMutableComposition()

        for i in 0 ..< audioFileUrls.count {

            let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!

            let asset : AVURLAsset = AVURLAsset(url: (audioFileUrls[i] as! NSURL) as URL)

            let track : AVAssetTrack = asset.tracks(withMediaType: AVMediaType.audio)[0]

            let timeRange = CMTimeRange(start: CMTimeMake(value: 0, timescale: 600), duration: track.timeRange.duration)
            try! compositionAudioTrack.insertTimeRange(timeRange, of: track, at: composition.duration)
        }

        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
        self.mergeAudioURL = documentDirectoryURL.appendingPathComponent("FinalAudio.m4a")! as URL as NSURL

        let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
        assetExport?.outputFileType = AVFileType.m4a
        assetExport?.outputURL = mergeAudioURL as URL
        assetExport?.exportAsynchronously(completionHandler:
            {
                switch assetExport!.status
                {
                case AVAssetExportSessionStatus.failed:
                    print("failed \(assetExport?.error)")
                case AVAssetExportSessionStatus.cancelled:
                    print("cancelled \(assetExport?.error)")
                case AVAssetExportSessionStatus.unknown:
                    print("unknown\(assetExport?.error)")
                case AVAssetExportSessionStatus.waiting:
                    print("waiting\(assetExport?.error)")
                case AVAssetExportSessionStatus.exporting:
                    print("exporting\(assetExport?.error)")
                default:
                    print("Audio Concatenation Complete")
                }
        })

        print("asset url \(mergeAudioURL)")
    }

когда я использовал решение, которое я получаю

2020-05-11 13:09:14.771381-0600 TimeCapsule[88538:12022916] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'

Ошибка возникает в строке let track = asset.tracks(withMediaType: AVMediaTypeAudio)[0]. Перед этой строкой распечатки показывают, что assets.tracks.count = 0 assets.trackGroups.count = 0. Когда я удаляю индекс [0] в конце строки, следующая строка выдает ошибку, что «дорожка не имеет члена 'временной интервал'". Я не могу понять, как добавить дорожку в мой недавно созданный актив, чтобы я мог использовать продолжительность звука активов. Любая помощь будет принята с благодарностью, я предполагаю, что это просто устаревший синтаксис для нового Swift.


person deafmutemagic    schedule 11.05.2020    source источник
comment
убедитесь, что ваш файл действителен   -  person Sh_Khan    schedule 11.05.2020


Ответы (2)


Ошибка ясна

let tracks = asset.tracks(withMediaType: AVMediaTypeAudio)
guard !tracks.isEmpty else { return }
let track = tracks.first!

файл, который вы пытаетесь объединить, не имеет звуковых дорожек, поэтому массив пуст

person Sh_Khan    schedule 11.05.2020
comment
Итак, как я могу добавить звуковую дорожку, чтобы она не возвращалась? NSURL — это сохраненный аудиофайл, поэтому я не знаю, как получить звуковую дорожку/почему она не является частью актива? - person deafmutemagic; 11.05.2020
comment
Вы пытались воспроизвести этот файл по этому URL-адресу как аудио?? и проверить, действительно ли это вообще? код правильный проблема в файле - person Sh_Khan; 11.05.2020

Обратите внимание, что среда песочницы будет меняться каждый раз, когда 'url', я сталкивался с этой проблемой раньше!

person 海涛乌    schedule 26.05.2020