Ios AVAsset长度不正确

Ios AVAsset长度不正确,ios,mp3,avplayer,avasset,Ios,Mp3,Avplayer,Avasset,我需要在我的应用程序中播放远程mp3文件。我正在使用AVURLAsset和AVPlayer来实现这一点。一切正常,但某些文件的长度不正确。我需要正确的长度来显示曲目播放的进度条 以下是长度错误的mp3文件: 下面是我如何尝试获取轨迹长度的方法: AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];

我需要在我的应用程序中播放远程mp3文件。我正在使用AVURLAsset和AVPlayer来实现这一点。一切正常,但某些文件的长度不正确。我需要正确的长度来显示曲目播放的进度条

以下是长度错误的mp3文件:

下面是我如何尝试获取轨迹长度的方法:

AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];

Float64 assetDuration = CMTimeGetSeconds(asset.duration);
Float64 itemDuration = CMTimeGetSeconds(item.duration);
assetDuration和itemDuration均为~45秒。实际轨道长度约为30秒

如何获得mp3文件的实际长度?看起来mp3标签中有一个错误,因为我的Mac电脑上的预览工具也显示它是45秒。不过iTunes说这是30秒

我有一个想法,我可以得到HTTP响应的内容长度字段并计算磁道大小,但我需要得到比特率

更新

我更深入地尝试使用AudioToolbox:

AudioFileID fileID;
OSStatus result = AudioFileOpenURL((__bridge CFURLRef)url, kAudioFileReadPermission, 0, &fileID);
UInt32 bitrate = 0;
UInt32 bitrateSize = sizeof(UInt32);
result = AudioFileGetProperty(fileID, kAudioFilePropertyBitRate, &bitrateSize, &bitrate);

UInt64 size = 0;
UInt32 sizeSize = sizeof(UInt64);
result = AudioFileGetProperty(fileID, kAudioFilePropertyAudioDataByteCount, &sizeSize, &size);

AudioFileClose(fileID);

UInt64 seconds = size / (bitrate / 8);

又得到了错误的值。看起来这个文件在编码方面有一些问题。如果我能得到进一步的结果,我会更新这个问题。

我发现准确的是在当前项目的duration属性上使用KVO: 添加观察:

[item addObserver:self
               forKeyPath:@"duration"
                  options:0 
                  context:NULL];
@try {
        [item removeObserver:self forKeyPath:@"duration"];
    }
删除观察:

[item addObserver:self
               forKeyPath:@"duration"
                  options:0 
                  context:NULL];
@try {
        [item removeObserver:self forKeyPath:@"duration"];
    }
观察方法:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context{
    if ([keyPath isEqualToString:@"duration"] == YES){
        //playe item duration property should now be up to date
    }
}

以下是对上述解决方案的改进,包括位深度:

func determineDuration(url: NSURL) -> NSTimeInterval {
    var fileID: AudioFileID = AudioFileID()
    AudioFileOpenURL(url, AudioFilePermissions.ReadPermission, 0, &fileID)
    var bitrate: UInt32 = 0
    var bitrateSize: UInt32 = UInt32(sizeof(UInt32))
    AudioFileGetProperty(fileID, kAudioFilePropertyBitRate, &bitrateSize, &bitrate)

    var size: UInt64 = 0
    var sizeSize: UInt32 = UInt32(sizeof(UInt64))
    AudioFileGetProperty(fileID, kAudioFilePropertyAudioDataByteCount, &sizeSize, &size)

    var depth: UInt32 = 0
    var depthSize: UInt32 = UInt32(sizeof(UInt32))
    AudioFileGetProperty(fileID, kAudioFilePropertySourceBitDepth, &depthSize, &depth)

    AudioFileClose(fileID)

    return NSTimeInterval(size / UInt64(bitrate / depthSize))
}