Подтвердить что ты не робот

Как получить продолжительность аудиофайла в iOS?

NSDictionary* fileAttributes = 
    [[NSFileManager defaultManager] attributesOfItemAtPath:filename 
                                                     error:nil]

Из ключей атрибутов файла вы можете получить дату, размер и т.д. Но как вы получаете продолжительность?

4b9b3361

Ответ 1

В "Ключи атрибутов файла" ссылки на класс NSFileManager вы можете видеть, что нет ключа для использования, который вернет длительность песня. Вся информация, которую экземпляр NSFileManager получает о файле, относится к свойствам самого фактического файла в операционной системе, например размер файла. NSFileManager фактически не интерпретирует файл.

Чтобы получить длительность файла, вам нужно использовать класс, который знает, как интерпретировать файл. AVFoundation обеспечивает точный класс, который вам нужен, AVAsset. Вы можете создать экземпляр этого абстрактного класса, используя конкретный подкласс AVURLAsset, а затем предоставить ему NSURL, который указывает на аудиофайл, который вы хотите получить. Затем вы можете получить продолжительность из экземпляра AVAsset, запросив его свойство duration.

Например:

AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:audioFileURL options:nil];
CMTime audioDuration = audioAsset.duration;
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);

Обратите внимание, что AVFoundation спроектирована как сильно асинхронная структура, чтобы повысить производительность и общий пользовательский интерфейс. Даже выполнение простых задач, таких как запрос продолжительности медиафайла, может занять длительный период времени и может привести к зависанию приложения. Вы должны использовать протокол AVAsynchronousKeyValueLoading для асинхронной загрузки продолжительности песни, а затем обновите свой пользовательский интерфейс в блоке обработчика завершения. Вы должны взглянуть на "Руководство по программированию блоков" , а также видео WWDC2010 под названием "Открытие AV-фонда", которое доступно бесплатно на https://developer.apple.com/videos/wwdc/2010.

Ответ 2

Для полноты - есть еще один способ получить продолжительность mp3 файла:

NSURL * pathToMp3File = ...
NSError *error = nil;
AVAudioPlayer* avAudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:pathToMp3File error:&error];

double duration = avAudioPlayer.duration; 
avAudioPlayer = nil;

Я использовал это без заметной задержки.

Ответ 3

Вы можете добиться того же результата в Swift, используя:

let audioAsset = AVURLAsset.init(url: audioFileURL, options: nil)
let duration = audioAsset.duration
let durationInSeconds = CMTimeGetSeconds(duration)

Ответ 4

Для тех, кто все еще ищет это. Исходя из ответа, код для Swift 4 (включая асинхронную загрузку значений, взятых из документации Apple):

let audioAsset = AVURLAsset.init(url: yourURL, options: nil)

audioAsset.loadValuesAsynchronously(forKeys: ["duration"]) {
    var error: NSError? = nil
    let status = audioAsset.statusOfValue(forKey: "duration", error: &error)
    switch status {
    case .loaded: // Sucessfully loaded. Continue processing.
        let duration = audioAsset.duration
        let durationInSeconds = CMTimeGetSeconds(duration)
        print(Int(durationInSeconds))
        break              
    case .failed: break // Handle error
    case .cancelled: break // Terminate processing
    default: break // Handle all other cases
    }
}

Ответ 5

Swift 5.0 + iOS 12: это единственный способ, которым он работал для меня (решение @John Goodstadt в Swift). В настоящее время я не уверен, почему, но существует разница в среднем 0,2 секунды между записанным аудиофайлом (в моем случае голосовой заметкой) и полученным аудиофайлом, используя следующий код.

    do {
        let audioPlayer = try AVAudioPlayer(contentsOf: fileURL)
        return CGFloat(audioPlayer.duration)
    } catch {
        assertionFailure("Failed crating audio player: \(error).")
        return nil
    }