You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修改点:

  1. 精准定位字段:直接从metaItem.extraAttributes字典中取出StreamTitle对应的值,这是Shoutcast服务器存储该元数据的标准位置。
  2. 找到即停止:拿到正确的StreamTitle后立刻break循环,避免后续无关字段覆盖正确内容。
  3. 增加空判断:先检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:52:34