9

What is the easiest way to get a duration of an audio file?

I could create an object of AVAudioPlayer, initialize it with URL and than get the duration, but this way is too long. Is there an easier way?

Thanks.

Ilya Suzdalnitski
  • 52,598
  • 51
  • 134
  • 168
  • Possible duplicate of [How to get the duration of an audio file in iOS?](http://stackoverflow.com/questions/5219379/how-to-get-the-duration-of-an-audio-file-in-ios) – user471651 Apr 21 '16 at 01:06

8 Answers8

15

Correct code is

NSURL *afUrl = [NSURL fileURLWithPath:soundPath];
AudioFileID fileID;
OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &fileID);
Float64 outDataSize = 0;
UInt32 thePropSize = sizeof(Float64);
result = AudioFileGetProperty(fileID, kAudioFilePropertyEstimatedDuration, &thePropSize, &outDataSize);
AudioFileClose(fileID);

outDataSize should be Float64 not UInt64.

Farhad Malekpour
  • 1,314
  • 13
  • 16
  • I've been coding objective-c for a day now so excuse the novice question. How do I get the outDataSize into an int that holds milliseconds. – Brett Sutton Jun 28 '20 at 02:48
10

You can use the Audio File Services functions. There's one property to get that should give you the estimated duration. Code:

    NSURL *afUrl = [NSURL fileURLWithPath:soundPath];
    AudioFileID fileID;
    OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &fileID);
    Float64 outDataSize = 0;
    UInt32 thePropSize = sizeof(Float64);
    result = AudioFileGetProperty(fileID, kAudioFilePropertyEstimatedDuration, &thePropSize, &outDataSize);
    AudioFileClose(fileID);

You can check the docs here

h3dkandi
  • 1,106
  • 1
  • 12
  • 27
pgb
  • 24,813
  • 12
  • 83
  • 113
2

If you know anything about the audio file in question (samplerate, bitdepth, channel count), and it's an uncompressed format (WAV/AIFF), then you can calculate the /approximate/ duration from the filesize:

length_in_seconds = (file_length-guess_100_bytes_for_header) / (samplerate*(bitdepth*channel_count/8))

Dave Gamble
  • 4,146
  • 23
  • 28
  • 100 bytes for the header? Whatever happened to the canonical 44? :) – MusiGenesis Aug 07 '09 at 20:02
  • I should know better after 14 years of this, but just last month I spent half a day trying to figure out where the little click at the beginning of my sound was coming from. I was using my quick-and-dirty method that assumed just the 44 byte header. I learned my lesson, yet again. – MusiGenesis Aug 07 '09 at 20:36
  • 1
    You can take dataOffset which I guess indicates the header size. `SInt64 dataOffset = 0; UInt32 dataOffsetSize = sizeof(dataOffset); AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataOffset, &dataOffsetSize, &dataOffset);` – pronebird May 11 '11 at 13:29
2

It depends on the file type. If it's a WAV file you can locate the file's header and determine the playback duration that way. If it's a compressed format (*.mp3 etc.) you're better off sticking to the method you mentioned.

MusiGenesis
  • 74,184
  • 40
  • 190
  • 334
2

Combining AVAudioPlayer with Swift becomes as easy as (I am migrating a Realm table below, but you get the idea):

import AVFoundation

let resource = old!["filename"] as? String
let afUrl = NSBundle.mainBundle().URLForResource(resource, withExtension: nil)
let player = try! AVAudioPlayer(contentsOfURL: afUrl!)

new!["duration"] = Double(player.duration)
Mazyod
  • 22,319
  • 10
  • 92
  • 157
1

In case anyone lands here looking for a way to get the duration for both audio and video files, have a look at this answer to another post, which instead uses AVAsset instead:

https://stackoverflow.com/a/7052147/381233

Using AudioFileGetProperty (like the other two main answers here) to get the duration of A/V files didn't work for a few .mov files on my device (result was always 0), while the solution using AVAsset got the duration for all audio and video files on my device.

(Interestingly enough, however, the duration from both solutions was sometimes 1 second more than that displayed in the UI of an actual AVAudioPlayer. Most likely the AVAudioPlayer uses a non-standard rounding routine for the displayed duration.)

Community
  • 1
  • 1
newenglander
  • 2,019
  • 24
  • 55
1

sample code from answer How to get the duration of an audio file in iOS?. This is the best answer.

AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:audioFileURL options:nil]; 
CMTime audioDuration = audioAsset.duration; 
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
Claudio
  • 5,078
  • 1
  • 22
  • 33
Nazir
  • 1,945
  • 24
  • 27
1
 AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:mp3_url options:nil];
                    [audioAsset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{
                        CMTime audioDuration = audioAsset.duration;
                        float audioDurationSeconds = CMTimeGetSeconds(audioDuration);

                        NSLog(@"duration:%f",audioDurationSeconds);
                    }];
Ishwar Hingu
  • 562
  • 7
  • 14