web-dev-qa-db-fra.com

Comment obtenir la durée d'un fichier audio dans iOS?

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

À partir des clés d'attribut de fichier, vous pouvez obtenir la date, la taille, etc. Mais comment obtenez-vous la durée?

44
Namratha

Dans la 'File Attribute Keys' de la NSFileManager référence de classe vous pouvez voir qu'il n'y a pas de clé à utiliser qui retournera la durée d'une chanson. Toutes les informations que l'instance NSFileManager obtient sur un fichier concernent les propriétés du fichier lui-même dans le système d'exploitation, telles que son fichier - Taille. Le NSFileManager n'interprète pas réellement le fichier.

Afin d'obtenir la durée du fichier, vous devez utiliser une classe qui sait interpréter le fichier. Le cadre AVFoundation fournit la classe exacte dont vous avez besoin, AVAsset . Vous pouvez instancier une instance de cette classe abstraite en utilisant la sous-classe concrète AVURLAsset , puis lui fournir un [~ # ~] nsurl [~ # ~] qui pointe vers le fichier audio dont vous souhaitez obtenir la durée. Vous pouvez ensuite obtenir la durée de l'instance AVAsset en interrogeant sa propriété duration.

Par exemple:

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

Notez que AVFoundation est conçu comme un cadre fortement asynchrone afin d'améliorer les performances et l'expérience utilisateur globale. Même l'exécution de tâches simples telles que l'interrogation de la durée d'un fichier multimédia peut potentiellement prendre une longue période et entraîner le blocage de votre application. Vous devez utiliser le protocole AVAsynchronousKeyValueLoading pour charger de manière asynchrone la durée du morceau, puis mettre à jour votre interface utilisateur dans un bloc de gestionnaire d'achèvement. Vous devriez jeter un œil au 'Block Programming Guide' ainsi qu'à la vidéo WWDC2010 intitulée 'Discovering AV Foundation', qui est disponible gratuitement sur https://developer.Apple. com/vidéos/wwdc/201 .

126
James Bedford

Pour être complet - Il existe un autre moyen d'obtenir la durée d'un fichier mp3:

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

double duration = avAudioPlayer.duration; 
avAudioPlayer = nil;

Je l'ai utilisé sans délai discernable.

14
John Goodstadt

Vous pouvez obtenir la même chose dans Swift en utilisant:

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

Pour tous ceux qui recherchent toujours cela. Sur la base de la réponse, le code pour Swift 4 (y compris le chargement asynchrone des valeurs tirées de la documentation d'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
    }
}
6
nCr78

Swift 5.0 + iOS 12: C'est la seule façon dont cela a fonctionné pour moi (solution @John Goodstadt dans Swift). Actuellement, je ne sais pas pourquoi, mais il y a une différence de 0,2 seconde en moyenne entre un fichier audio enregistré (dans mon cas, un mémo vocal) et le fichier audio reçu en utilisant le code suivant.

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