Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS-从Objective-C中的媒体获取[Explicit]和[Clean]标记_Objective C_Ios_Avfoundation_Explicit_Mpmediaquery - Fatal编程技术网

iOS-从Objective-C中的媒体获取[Explicit]和[Clean]标记

iOS-从Objective-C中的媒体获取[Explicit]和[Clean]标记,objective-c,ios,avfoundation,explicit,mpmediaquery,Objective C,Ios,Avfoundation,Explicit,Mpmediaquery,当我在iTunes中查看购买的音乐时,在歌曲列表中,显式歌曲旁边会显示一个红色的显式框。也就是说,购买歌曲时看到的显式标签会传递到iTunes库。itunes标记为clean的歌曲也是如此。我真的很想能够识别ios应用程序中明确显示的任何歌曲,但我找不到任何关于标签是否通过其他歌曲信息(MPMediaItemProperty)传递到ios设备的资源,如果是,如何获取它(我已经搜索了无数次!)一些歌曲包括“[明确]在他们的标题末尾,但这只是一些歌曲的情况,而不是全部。有人知道标签是否存在并且可以从

当我在iTunes中查看购买的音乐时,在歌曲列表中,显式歌曲旁边会显示一个红色的显式框。也就是说,购买歌曲时看到的显式标签会传递到iTunes库。itunes标记为clean的歌曲也是如此。我真的很想能够识别ios应用程序中明确显示的任何歌曲,但我找不到任何关于标签是否通过其他歌曲信息(MPMediaItemProperty)传递到ios设备的资源,如果是,如何获取它(我已经搜索了无数次!)一些歌曲包括“[明确]在他们的标题末尾,但这只是一些歌曲的情况,而不是全部。有人知道标签是否存在并且可以从Objective-C代码中读取吗?

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

概述 您需要的数据不容易通过标准通道访问(即MediaPlayer或AVFoundation框架中没有预定义的键来访问此元数据)。它可以通过大多数ID3标记编辑器使用,名称为
ITUNESADVISORY
。此标记可以取3个值:

0-无咨询信息

1-明确的

2-清洁

这就是我们要寻找的,但我们如何访问它。
MediaPlayer
框架的级别相当高,这意味着我们只能访问/使用哪些数据。为了更深入地查看媒体文件,我们还需要使用
AVFoundation
框架

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

  • 我需要获取一个包含我要检查的文件的
    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:...];
        ....
    }
    
  • 一旦我有了我的
    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];
        ....
    
  • 一旦我们拥有了资产,我们需要从中获取元数据。通过实验,这是iTunes元数据。因此,让我们从资产中提取它

    NSArray* metadata = [asset metadataForFormat:AVMetadataFormatiTunesMetadata];
    
  • 这就是有趣的、未记录的工作开始的地方。我们现在必须找到我们想要的正确元数据项。由于咨询键在苹果的任何文档中都没有声明为常量,经过多次尝试和错误,我发现它是
    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;
    }];
    
  • 一旦我们做到了这一点,我们需要确定它是什么。这相对简单,可以根据您自己的需要进行调整。我刚刚写了一个简单的切换语句,说明歌曲/媒体是什么类型的。(记住:媒体文件完全可能不包含咨询标签,因此我们必须检查索引是否存在)

  • 结论 这是一种判断歌曲是否清晰或明确的方法。因为这是使用一个静态数字来查找建议数据,并且没有链接到苹果标题中定义的任何常量,所以我不能保证这将适用于过去、现在和将来的所有iOS版本。我已经在iOS 6上进行了测试,并且看起来还可以。你的年龄可能会有所不同


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

    哇,非常感谢您解决了此问题。我想您一定是唯一发现此问题的人,因为在我所有的搜索中,我找不到任何人使用此功能。非常感谢!花了大量时间四处挖掘,并牺牲了一些我的音乐使其清晰/明确(!),但我很高兴能帮上忙:)@Adam你是在使用iTunes Match,还是在同步时为设备重新编码音乐?我今天实现了这一点,不幸的是,我发现这不是一个完整的解决方案,因为我的一些库显式歌曲没有该键,有些只有iTunes和iTunesMPB键。我想这可能意味着显式信息根本不存在对于所有曲目来说,这真是太丢脸了。我想可能是明确的标签实际上在iTunorm或iTunSMPB键的值范围内,对于使用它们而不是数字命名键(如1920233063)的歌曲来说,这是一种替代方式——不幸的是,我对这一领域一无所知。
    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;
        }
    }