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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5219379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:09:21  来源:igfitidea点击:

How to get the duration of an audio file in iOS?

iosfileaudionsdictionaryduration

提问by Namratha

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

From the file attribute keys, you can get the date, size, etc. But how do you get the duration?

从文件属性键,你可以得到日期、大小等。但是你如何得到持续时间呢?

回答by James Bedford

In the 'File Attribute Keys' of the NSFileManagerclass referenceyou can see that there is no key to use that will return the duration of a song. All the information that the NSFileManagerinstance gets about a file is to do with the properties of the actual file itself within the operating system, such as its file-size. The NSFileManagerdoesn't actually interpret the file.

NSFileManager类参考“文件属性键”中,您可以看到没有可使用的键来返回歌曲的持续时间。NSFileManager实例获取的关于文件的所有信息都与操作系统中实际文件本身的属性有关,例如它的文件大小。该的NSFileManager实际上并不解释文件。

In order to get the duration of the file, you need to use a class that knows how to interpret the file. The AVFoundationframework provides the exact class you need, AVAsset. You can instantiate an instance of this abstract class using the concrete subclass AVURLAsset, and then provide it an NSURLwhich points to the audio file you wish to get the duration. You can then get the duration from the AVAssetinstance by querying its durationproperty.

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

For example:

例如:

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

Note that AVFoundation is designed as a heavily asynchronous framework in order to improve performance and the overall user experience. Even performing simple tasks such as querying a media file's duration can potentially take a long period of time and can cause your application to hang. You should use the AVAsynchronousKeyValueLoading protocolto asynchronously load the duration of the song, and then update your UI in a completion handler block. You should take a look at the 'Block Programming Guide'as well as the WWDC2010 video titled, 'Discovering AV Foundation', which is available free at https://developer.apple.com/videos/wwdc/2010.

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

回答by John Goodstadt

For completeness - There is another way to get the duration for a mp3 file:

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

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

double duration = avAudioPlayer.duration; 
avAudioPlayer = nil;

I have used this with no discernible delay.

我已经使用了它,没有明显的延迟。

回答by Ashildr

You can achieve the same in Swift using :

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

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

回答by nCr78

For anyone still looking for this. Based on the answer, the code for Swift 4(including the async loading of values taken from Apple's documentation):

对于任何仍在寻找这个的人。根据答案,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
    }
}

回答by Baran Emre

Swift 5.0 + iOS 13: This is the only way it worked for me (@John Goodstadt solution in Swift). Currently I'm not sure why, but the there is a difference of average 0.2 seconds between a recorded audio file (in my case a voice memo) and the received audio file using the following code.

Swift 5.0 + iOS 13:这是对我有用的唯一方法(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
    }

回答by guozqzzu

I record a linear PCM file (.pcm) through AVAudioRecorder. I get the duration with the help of Farhad Malekpour. Maybe this can help you : iPhone: get duration of an audio file

我通过 .pcm 录制线性 PCM 文件 (.pcm) AVAudioRecorder。我在 Farhad Malekpour 的帮助下获得了持续时间。也许这可以帮助您: iPhone:获取音频文件的持续时间

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