如何在iOS中获取音频文件的持续时间?

时间:2011-03-07 11:53:39

标签: ios file audio nsdictionary duration

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

从文件属性键中,您可以获取日期,大小等。但是如何获得持续时间?

7 个答案:

答案 0 :(得分:125)

'File Attribute Keys' of the NSFileManager class reference中你可以看到没有使用的键可以返回歌曲的持续时间。 NSFileManager 实例获取文件的所有信息都与操作系统中实际文件本身的属性有关,例如文件大小。 NSFileManager 实际上并不解释该文件。

为了获取文件的持续时间,您需要使用知道如何解释文件的类。 AVFoundation 框架提供了您需要的确切类, AVAsset 。您可以使用具体的子类 AVURLAsset 实例化此抽象类的实例,然后为其提供 NSURL ,它指向您希望获得持续时间的音频文件。然后,您可以通过查询其duration属性从 AVAsset 实例获取持续时间。

例如:

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

请注意,AVFoundation被设计为一个高度异步的框架,以提高性能和整体用户体验。即使执行简单的任务(例如查询媒体文件的持续时间)也可能需要很长时间,并且可能导致应用程序挂起。您应该使用AVAsynchronousKeyValueLoading protocol异步加载歌曲的持续时间,然后在完成处理程序块中更新UI。您应该查看'Block Programming Guide'以及WWDC2010视频“发现AV基础”,该视频可在https://developer.apple.com/videos/wwdc/2010免费获得。

答案 1 :(得分:14)

为了完整性 - 还有另一种获取mp3文件持续时间的方法:

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

double duration = avAudioPlayer.duration; 
avAudioPlayer = nil;

我使用了这个没有明显的延迟。

答案 2 :(得分:8)

您可以使用以下方法在Swift中实现相同的目标:

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

答案 3 :(得分:4)

对于仍在寻找此事的人。 根据答案, Swift 4 的代码(包括从Apple&#39的文档中获取的异步加载值):

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
    }
}

答案 4 :(得分:0)

Swift 5.0 + iOS 12 :这是它为我工作的唯一方式(Swift中的@John Goodstadt解决方案)。目前,我不确定为什么,但是使用以下代码,录制的音频文件(在我的情况下为语音备忘录)与接收到的音频文件之间平均相差0.2秒。

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

答案 5 :(得分:0)

我通过AVAudioRecorder录制了线性PCM文件(.pcm)。我得到了Farhad Malekpour的帮助。也许这可以帮助您: iPhone: get duration of an audio file

NSURL *fileUrl = [NSURL fileURLWithPath:yourFilePath];
AudioFileID fileID;
OSStatus result = AudioFileOpenURL((__bridge CFURLRef)fileUrl,kAudioFileReadPermission, 0, &fileID);
Float64 duration = 0; //seconds. the duration of the audio.
UInt32 ioDataSize = sizeof(Float64);

result = AudioFileGetProperty(fileID, kAudioFilePropertyEstimatedDuration, 
&ioDataSize, &duration);
AudioFileClose(fileID);
if(0 == result) {
   //success
}
else {
  switch (result) {
    case kAudioFileUnspecifiedError:{
        //
    } break;
        // other cases...
    default:
        break;
  }
}

答案 6 :(得分:0)

我实际上发现您可以只使用“从音乐中获取详细信息”块并将其设置为“获取持续时间”,其中可以是来自提示的 mp3 输入、指向 mp3 的链接、来自共享表的 mp3等