我需要在我的应用中播放远程mp3文件。我正在使用AVURLAsset
和AVPlayer
来执行此操作。一切都很好,但有些文件的长度不正确。我需要正确的长度来显示曲目播放的进度条。
这是长度错误的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);
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);
再次出现错误的价值。因此看起来这些文件在编码方面存在一些问题。如果我能得到进一步的结果,我会更新这个问题。
答案 0 :(得分:0)
我发现准确的是在当前项目的持续时间属性上使用KVO: 添加观察:
[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
}
}
答案 1 :(得分:0)
以下是对上述解决方案的改进(包括位深度):
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))
}