Xcode中AVPlayerItemTrack无法正确获取Shoutcast流的StreamTitle元数据
Fix: Shoutcast StreamTitle Metadata Only Shows 't' on Specific Servers
我明白你遇到的这个头疼问题了——同样的代码在大部分Shoutcast服务器上正常,偏偏某台服务器只显示个't',还没法用NSLog调试,确实折腾人。咱们来一步步解决它:
问题根源分析
先看你提供的服务器响应:
正常服务器响应最后一项:
StreamTitle : Rod Stewart - Lost In You
异常服务器响应最后一项:StreamUrl : t
你的现有代码是遍历所有元数据项,每次都把songInfo.text替换成当前项的内容,所以最后显示的必然是遍历到的最后一个元数据字段。正常服务器的最后一项刚好是StreamTitle,所以没问题;但异常服务器最后一项是StreamUrl(值为't'),自然就显示这个错误值了。
解决方案:精准提取StreamTitle字段
我们不需要遍历所有元数据项,而是直接定位到StreamTitle对应的字段。修改你的FetchMeta方法如下:
- (void)FetchMeta { // 先判断playerItem是否存在,避免空指针崩溃 AVPlayerItem *playerItem = player.currentItem; if (!playerItem) return; for (AVPlayerItemTrack *item in playerItem.tracks) { if ([item.assetTrack.mediaType isEqual:AVMediaTypeAudio]) { NSArray *metaArray = playerItem.timedMetadata; for (AVMetadataItem *metaItem in metaArray) { // 优先从extraAttributes中获取StreamTitle(Shoutcast元数据通常存在这里) NSString *streamTitle = metaItem.extraAttributes[@"StreamTitle"]; if (streamTitle && ![streamTitle isEqualToString:self.songInfo.text]) { self.songInfo.text = streamTitle; [self LoadArtistImage]; break; // 找到目标字段就停止遍历,避免被后续字段覆盖 } // 备选方案:如果extraAttributes中没有,尝试检查commonKey(适配部分兼容服务器) if ([metaItem.commonKey isEqualToString:@"title"]) { NSString *source = metaItem.stringValue; if (![source isEqualToString:self.songInfo.text]) { self.songInfo.text = source; [self LoadArtistImage]; break; } } } } } }
关键修改点:
- 精准定位字段:直接从
metaItem.extraAttributes字典中取出StreamTitle对应的值,这是Shoutcast服务器存储该元数据的标准位置。 - 找到即停止:拿到正确的
StreamTitle后立刻break循环,避免后续无关字段覆盖正确内容。 - 增加空判断:先检查
playerItem是否存在,防止崩溃。
替代NSLog的调试方案
既然Xcode里NSLog没法用,我们可以把调试信息写到本地文件里,方便排查:
// 自定义日志写入方法 - (void)writeDebugLog:(NSString *)logContent { NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *logPath = [docsDir stringByAppendingPathComponent:@"shoutcast_debug.log"]; NSString *formattedLog = [NSString stringWithFormat:@"%@\n%@\n", [NSDate date], logContent]; NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:logPath]; if (fileHandle) { [fileHandle seekToEndOfFile]; [fileHandle writeData:[formattedLog dataUsingEncoding:NSUTF8StringEncoding]]; [fileHandle closeFile]; } else { [[NSFileManager defaultManager] createFileAtPath:logPath contents:[formattedLog dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; } }
然后在代码里调用它来查看元数据详情:
// 在遍历元数据的循环里加入 [self writeDebugLog:[NSString stringWithFormat:@"Metadata Item: %@\nExtra Attributes: %@", metaItem.stringValue, metaItem.extraAttributes]];
之后你可以通过Xcode的Devices and Simulators窗口找到App的Documents目录,导出shoutcast_debug.log文件查看详细调试信息。
内容的提问来源于stack exchange,提问作者omega1
相关产品推荐
相关产品推荐

