2013-12-23 102 views
0

我需要在我的应用程序中播放远程mp3文件。我使用AVURLAssetAVPlayer来做到这一点。一切都很好,但有些文件的长度不正确。我需要正确的长度才能显示曲目播放的进度条。AVAsset长度不正确

这里是错误的长度的MP3文件: http://content.mts.stream.ru/files/melody/mp3/3828.mp3

这里是我试图让轨道长度:

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

Float64 assetDuration = CMTimeGetSeconds(asset.duration); 
Float64 itemDuration = CMTimeGetSeconds(item.duration); 

两个assetDurationitemDuration是〜45秒。真实的轨道长度约为30秒。

我怎样才能得到真正的MP3文件的长度?看起来像是mp3标签有错误,因为我的Mac上的预览工具也说它是45秒。然而iTunes说它是30秒。

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

UPDATE

我去更深,试图用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); 

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

回答

0

我发现了什么是对当前项目的持续时间属性使用志愿准确: 添加观察:

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

以上是对上述解决方案的改进(包括ng位深度):

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