7

当我在 iTunes 中查看我购买的音乐时,明确的歌曲在歌曲列表中旁边会显示一个红色的明确框。即,您在购买歌曲时看到的显式标签会传递到 iTunes 库。对于标记为干净的歌曲 itunes 也是如此。我真的很希望能够识别我的 ios 应用程序中明确的任何歌曲,但我找不到任何关于标签是否与其他歌曲信息 (MPMediaItemProperty) 一起传递到 ios 设备的资源,如果是的话如何得到它(我已经无休止地搜索了!)有些歌曲在标题末尾包含“[Explicit],但这只是一些歌曲的情况,而不是全部。有谁知道标签是否存在并且可以从Objective读取-C 代码?

4

1 回答 1

8

好吧,这花了我好几个小时才找到!做好准备,它并不像使用MPMediaQuery.

概述

您需要的数据无法通过标准渠道轻松访问(即 MediaPlayer 或 AVFoundation 框架中没有预定义的密钥来访问此元数据)。它可以通过大多数 ID3 标签编辑器使用,名称为ITUNESADVISORY. 这个标签可以取 3 个值:

0 - 没有咨询信息

1 - 显式

2 - 清洁

这是我们正在寻找的,但是我们如何访问它。该MediaPlayer框架相当高级,这意味着我们可以访问/使用的数据受到限制。为了更深入地查看媒体文件,我们还需要使用AVFoundation框架。

如何

我不知道您使用的是什么确切的工作流程,但我希望您可以根据自己的需要进行调整。为了确定媒体文件是否是显式/干净的,我做了如下操作:

  1. 我需要获取一个MPMediaItem包含我要检查的文件的文件。我使用MPMediaPickerController、呈现它并通过它的委托方法检索选定的媒体项目:

    - (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
        // Do whatever is appropriate in your case to extract the media items
        MPMediaItem* item = [mediaItemCollection.items objectAtIndex:...];
        ....
    }
    
  2. 一旦我有了我的MPMediaItem,我需要得到等价的AVAsset,这样我就可以使用AVFoundation框架。为此,我可以使用媒体项中的 URL 路径来创建资产。

    MPMediaItem* item = ...;
    NSURL* path = [item valueForProperty:MPMediaItemPropertyAssetURL];
    
    // We have to check if a path exists, because a media item may not be present on the device. Blame iTunes Match.
    if (path) {
        AVAsset* asset = [AVAsset assetWithURL:path];
        ....
    
  3. 拥有资产后,我们需要从中获取元数据。根据实验,这是 iTunes 元数据。因此,让我们从我们的资产中提取它。

    NSArray* metadata = [asset metadataForFormat:AVMetadataFormatiTunesMetadata];
    
  4. 这是有趣的、无证工作的开始。我们现在必须为我们想要的找到正确的元数据项。由于在 Apple 的任何文档中都没有将咨询键声明为常量,因此经过大量试验和错误,我发现它是1920233063.

    为了得到正确的元数据项,我们需要对元数据数组进行过滤,如下所示:

    NSUInteger advisoryIndex = [metadata indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[AVMetadataItem class]]) {
            AVMetadataItem* metaItem = (AVMetadataItem*)obj;
            NSNumber* advisoryKeyTest = @(1920233063);
    
            if ([metaItem.key isEqual:advisoryKeyTest]) {
                *stop = YES;
                return YES;
            }
            return NO;
        }
        return NO;
    }];
    
  5. 一旦我们这样做了,那么我们需要确定它是什么。这个比较简单,可以根据自己的需要进行调整。我刚刚写了一个简单的 switch 语句,说明歌曲/媒体的类型。(记住:媒体文件完全有可能不包含advisory标签,所以我们必须检查索引是否存在)

    if (advisoryIndex != NSNotFound) {
        AVMetadataItem* metaItem = [metadata objectAtIndex:advisoryIndex];
    
        NSInteger advisoryValue = [metaItem.numberValue integerValue];
        switch (advisoryValue) {
            case 0:
                NSLog(@"%@", @"Unspecified");
                break;
            case 1:
                NSLog(@"%@", @"Explicit");
                break;
            case 2:
                NSLog(@"%@", @"Clean");
                break;
            default:
                NSLog(@"%@", @"Unexpected Value");
                break;
        }
    }
    

结论

你有它,一种方法来确定一首歌是干净的还是明确的,或者两者都不是。因为这是使用静态数字来查找咨询数据,并且没有链接到 Apple 标头中定义的任何常量,所以我不能保证这将适用于过去、现在和将来的所有 iOS 版本。我已经在 iOS 6 上对此进行了测试,它似乎没问题。您的里程可能会有所不同。

遗憾的是,Apple 没有开箱即用地提供此功能(即使他们只是提供了咨询密钥)。如果您愿意,可以将此功能放置在一个类别中。

于 2012-11-03T16:59:24.990 回答