介绍词
无论苹果对封闭平台和生态系统本身有多大的责骂,他们的某些解决方案都是一个例外。 市场上有很多流媒体服务,但是在第三方产品中提供完整的用于流媒体的SDK的机会非常小,对于俄罗斯市场,正式可用的SDK的列表仅限于Deezer和Apple Music。 当然,当Spotify进入我们的市场时,将会有更多可用的SDK,但是到目前为止,有两个参与者,只有一个拥有广泛的用户基础。
碰巧,我有使用Android的Deezer SDK的经验,现在我正在积极使用iOS的Apple Music SDK( MusicKit )。 与Deezer体验的主要不同在于,MusicKit是冰山一角,它也是公开可用的API。 与Deezer不同,在其中重复官方应用程序的大部分功能只是一个漫长的过程,即使仅使用公共API也无法重复甚至Apple Music网页的功能。 即使Apple在其解决方案中使用了MusicKit,除此以外,它还使用了许多未公开的API请求和私有API,这些应用程序不允许凡人使用。
在本文中,我将从开发人员的角度讨论在实现“ 简单任务 ”的背景下如何使用MusicKit:搜索目录,在搜索结果中显示图片,获取歌曲,推荐甚至播放某种音乐。 展望未来,我要说的是,以上大部分内容对于在Android和Javascript中使用Apple Music都是正确的。
如有必要,我准备在评论中提供带有代码的详细答案。
肉饼和果肉分开
在iOS下使用MusicKit时,您将必须与以下实体进行交互:
另外,在连接到会员程序时,您可以请求访问Enterprise Partner Feed元数据转储,Apple建议使用它,而不是经常向iTunes Search API发送请求。
而且,以防万一,Music.app是iOS设备上的音乐应用程序,它是官方的Apple Music播放器。
信息源,按其效用从高到低的顺序:
- 官方文件
- 搜索所有 Apple 文档
- 使用HTTP API的科学实验方法1
- 您喜欢的浏览器中的开发者控制台,固定在Apple Music中感兴趣实体的网页上
- 苹果开发者论坛
- 堆栈溢出
搜索。 图片
检查您的应用程序中是否可以完成某些操作的最明显方法是,在官方应用程序中可以找到类似的信息。 这里以搜索为例。 我们正在寻找“警察” Music.app
,在Music.app
我们带着微笑的Sting Music.app
了一张Music.app
的照片:

很好,我们将使用搜索API 。 在发行中,我们为artwork
提供了带有嵌入式url
链接的artwork
密钥,适用于除艺术家以外的所有内容。 真奇怪 再次检查,在Music.app中所有内容都存在。 此外,Web界面还具有照片,并且在json搜索引擎API中提供了指向该网页的链接。
iTunes Search API也不artistLinkUrl
图像,但是它还包含网页地址, artistLinkUrl
包含artistLinkUrl
键。
好了,该怎么办,您必须下载该网页并从中获取图像地址,所幸,开发人员已注意并在元信息中注册了图像地址:
<meta property="og:image" content="https://is5-ssl.mzstatic.com/image/thumb/Features113/v4/bb/a2/66/bba266dd-570b-bff7-d7c6-777982582964/mzl.tdrwskof.jpg/1200x630cw.png" id="ember52310559" class="ember-view">
正式而言,我们已经违反了Apple禁止“抓取”其网页的规则。 实际上,除使用第三方服务查找图片的应用程序外,所有第三方应用程序都可以执行此操作。
还有一个减号:我们请求的页面大小为几百千字节。 对于已经驱动大量数据( 播放音乐 )的应用程序,它是可以忍受的( 特别是当您考虑以压缩形式传输数据时 ),但是通常情况下并不是那么容易。
图像的大小可以根据您的需要进行调整: url
有用于替换的模板( {w}
, {h}
),并且在网页上,图像的链接具有相同的格式,因此,获取合适尺寸的图像没有困难。 如果要获取舍入的图像,则需要在扩展名之前添加cw
。
关于要在播放器中显示的图片的奖励
在播放期间,来自Media Player
器在MPMediaItem
构造上运行,该构造特别提供了Artwork
对象。 在播放器中显示曲目的图片非常方便。 唯一的问题是,实际上,无论该对象怎么说,该对象都不提供流音乐( Apple Music中的任何音乐 )的图片,因此您必须“播放” MPMediaItem
播放的MPMediaItem
添加到队列中并下载的歌曲图像类似于相册。
按类型搜索
iTunes和Apple Music应用程序中都有类型和热门歌曲的列表。 寻找类型应该不难,因为我们可以搜索任何东西?
事实并非如此。 该API不会按流派进行搜索,并且不提供流派列表。 可以通过其标识符请求类型的信息( 从有用的名称 ),
但API中的大多数信息仅包含类型名称,而不包含标识符。
iTunes的好处是卸载了所有流派 ( 包括移动应用程序的“流派”在内的 所有流派 )。 流派的标识符( 如iTunes中的其他标识符 )完全对应于Apple Music中的标识符。 卸载适用于所有区域(该区域在cc
键中指示,而不是在Apple Music API中在storefront
指示 ),但实际上只有名称不同( 它们已翻译 )。 流派的结构是分层的,流派名称重复。
通常,必须按类型进行搜索,并且要记住,放克爵士乐,放克爵士乐和放克爵士乐是一回事。 并不困难,但没有要求搜索API按类型进行搜索那样简单。
找到一种流派后,您可以请求此流派的图表 ( 最受欢迎歌曲的列表 )。 对于罕见的流派,很有可能只发行3首歌曲。
有趣的事实:对于某些专辑和艺术家( 著名的Ed Sheeran ),仅一种流派简单地表明了“音乐”的顶级流派。 如果您要根据体裁提出建议,则应忽略此体裁。
歌手歌曲
当应用程序最需要播放艺术家( 音乐团体 )的歌曲时,这意味着有必要播放该团体的流行歌曲。 Apple Music可以请求歌手作为歌手的“歌曲” 2 链接 。 输出最多包含20首歌曲3 ,按流行程度清晰地排序。
有时您仍然想多听一些歌曲。 对于非常受欢迎的群组,可以选择获取播放列表,例如“ [艺术家姓名]: 基本 ”和“ [艺术家姓名]:详细信息 ”(“ [艺术家姓名]:后续步骤 “),但是通常,此选项不合适。 另一种选择:选取20首流行歌曲,然后从专辑中删除其余歌曲,Apple Music的好处是可以在一个请求中立即获取所有艺术家专辑( 如albums
链接 )和其中的所有歌曲( include="tracks"
)。
但是,如果您获得了歌手的所有歌曲,那么就会出现另一个问题:您需要从所有这些歌曲中选择流行歌曲。 不幸的是,流行度信息API没有提供4 。 您可以从整个列表中随机挑选歌曲,但实际上,这种方法会导致经常播放完全没意思的录音( 现场录音,排练录音,偏僻等等 ),这在非常受欢迎的人群中尤其明显5 。
让我们尝试以另一种方式获得热门歌曲。 甚至在MusicKit出现之前,Apple便开始在iTunes Store中提供搜索API 。 如前所述,Apple Music和iTunes Store中的目录是相同的6 ,因此,歌曲的标识符也相同。 默认情况下,此API返回50首歌曲,但您最多可以请求200首歌曲。 结果也按受欢迎程度排序。
有趣的是,Apple本身在其Web界面中未使用任何这些选项。 他们使用未公开的 ( 读取的,私有的 )API 7 ,该API发行时缺少所有内容,包括类型的标识符( 而不仅仅是名称 )和流行指数。 我不敢在实践8中使用此API,因为可以通过按类型名称9进行反向搜索来获得类型标识符,并且当您获得按流行度排序的歌曲列表时,数字流行度索引并不那么重要。
我称之为“ 休·劳瑞问题 ”的有趣事实是,苹果音乐目录中包含大量非音乐内容。 尤其是来自喜剧表演和站立表演的各种汇编。 一方面这很好( 我们为音乐付费,但我们还和Stephen Fry进行了有趣的对话,您可以在上床睡觉前收听 ),另一方面,当要求打开音乐时会引起一些chat不休。 因此,当应用程序的操作上下文直接指示用户想要听音乐时,必须从“ 歌曲 ”列表中独立删除那些流派被指定为“ 口语 ”和“ 喜剧 ”的用户。
推荐建议
播放推荐(它们也是“ 类似的歌曲 ”,“ 广播电台 ”,“ 您会喜欢 ”等)已经成为流媒体播放器的基本功能。 按照惯例,推荐可以分为两种类型10 :针对用户( 基于收听历史,购买和喜欢 )和针对音乐对象( 艺术家,曲目,不太频繁的专辑和播放列表 )。
根据Apple Music中用户的喜好,正式11一切都很好:您可以请求个人推荐列表 ,其中包括“ 个人混音 ”( 播放列表 )和推荐专辑。 从专辑中,可以使用API ( tracks
)类似地获取播放列表的歌曲列表。 请记住,曲目不仅可以包含歌曲( type = "songs"
),还可以包含视频剪辑,因此对接收到的数据进行其他过滤不会受到损害。
有了其他建议,一切都会变得更加复杂。 如果您查看Music.app,则那里会显示“ 相似的艺术家 ”,您可以为该艺术家打开“ 广播电台 ”。 后者失去了艺术家的推荐和推荐。

似乎一切都很简单:对于艺术家而言,可能存在“ 相似艺术家 ”之间的联系。 我赶紧难过,没有这种联系。 企业合作伙伴Feed数据架构中也没有相似性信息。
好的,所以我们可以为艺术家请求一个“ 广播电台 ”并获取歌曲列表? 再说一次,不,我们真的可以要求广播电台,它的标识符在艺术家的联系信息中。 但是在电台信息中,没有有关正在播放的歌曲,专辑或艺术家的信息,只有服务对象具有用于播放playParams
信息。 playParams
的想法playParams
简单:我们将字典12放入播放队列并收听。
如果您只想播放广播电台( 就像Music.app一样 ),那么这一切都很好,但是如果您想将广播电台13中的歌曲与其他歌曲混在一起怎么办? 显然,我们需要某种方式获得类似艺术家的名单。
在Media Player
,播放队列尤其是MPMusicPlayerControllerMutableQueue扮演着重要角色。 队列使您可以:在特定的可播放对象之后插入描述符,删除指定的对象,以及获取队列中所有对象的列表。 查询对象以进行输出时,我们应该从MPMediaItem
获得一个数组。 MPMediaItem
特别包括歌曲的标识符 。 只有一个问题:队列构造器不是公共API,我将翻译为: Media Player
可以提供一个现成的队列(有时是可编辑的 ),但是您无法自己创建它14 。
好吧,稍微拐杖会很有帮助。 如果Media Player
可以给我一个可变队列,那么我需要接受它。 为此,您必须与当前的( 单身 )播放器一起使用,因此您需要快速采取行动,否则用户可能会错失一些东西,并且播放器仍然有时间预加载到目前为止不需要的歌曲。 我们更改当前的播放队列( 添加站点描述符 ),查看发生了什么,使用新事务回滚队列中的更改( 删除实际添加到队列中的内容 )。
不幸的是,我们发现只有两个MPMediaItem
对象被MPMediaItem
到队列中。 两者看起来都像歌曲( 有艺术家的名字,曲目的名称,曲目的长度 ),但不包含歌曲的标识符。 如果您查看Music.app,我们发现那里一切都融合了:打开广播电台将播放歌曲,并且在队列中仅可播放一首歌曲。 当您移至下一首歌曲时,队列将更新。
尝试进一步建立带有广播电台的拐杖是没有意义的;您必须使用其他选项。
回想一下,在Music.app和Web界面中,显示了类似的艺术家。 同类歌手仅适用于最受欢迎的乐队15 。 同样,您必须诉诸于禁止解析网页的方法。 从专业人士那里:我们已经在下载网页以获取图片,因此我们可以立即从中获取相似的艺术家。
在html页面代码中,我们看到一个大的json对象,我们首先从中获取相似艺术家的标识符( ["data"]["relationships"]["artistContemporaries"]
):

然后使用这些标识符从同一个json(类型为lockup/artist
["included"]
获取艺术家数据:

有了艺术家的标识符,我们可以请求他们的足迹。 该API允许您在启用链接的单个请求中按其标识符请求多个艺术家 。 las,实际上,API返回错误,指示无法在结果中添加曲目列表。 这只能通过一次请求一个艺术家或直接请求单个艺术家的歌曲来完成。 在这种情况下,您可以使用已经提到的iTunes Search API,它将提供更多有用的信息。
Apple Music中的“ 类似艺术家 ”列表相当不错,但实际上,它们经常是空的。 在建议列表为空的情况下,您必须使用第三方服务。 经典-Last.fm,稍微复杂一点-Spotify。 两者的结果都需要与Apple Music目录中的对象匹配。 “在额头上”的解决方案是按名称搜索每个歌手 ,并给出一个准确的结果,然后如上所述接收歌曲。 这些解决方案有些有趣,但是使用musicbrainz进行匹配会更加昂贵。 Musicbrainz在其他服务中提供有关标识符16的信息,即 您可以将Spotify中的标识符与Apple Music中的标识符关联。 Last.fm的情况甚至更好:Last.fm从建议列表中的musicbrainz返回标识符。 开销在于对musicbrainz的使用限制,您需要大量流量来提高自己的musicbrainz克隆版本(幸运的是, 这是可能的 )或围绕数据库开发自己的API,可以轻松下载其转储。
对于新组,即使Last.fm也不会给出建议;替代选项将是“体裁”建议。 我们采用艺术家的流派( 根据名称,我们从已加载的所有流派列表中获取标识符 ),获得每种流派的图表,并混合接收到的歌曲。 总比没有好。
两件事是密不可分的:播放器和队列
Media Player负责在Apple Music中的iOS中播放;它允许您使用Apple Music中的音乐和用户的个人目录17 。 该框架是高级框架,在将流内容降至18以下的情况下将无法正常工作。
该框架为两个播放器提供了通用的软件界面: 一个直接在Music.app应用程序中播放音乐, 另一个则或多或少地独立工作。 用第一个严肃的东西毫无意义19 。 而且文件大胆地谎称第二个播放器在后台不工作20
从体系结构的角度来看,处理这个问题很简单:我们告诉播放器播放什么( 例如,基于一系列歌曲标识符填充队列 )并控制播放( 播放,暂停,下一个,上一个 )。
没有对播放队列的直接控制,您需要执行事务更改 ,这需要时间。 此外,通常会用超时错误来调用completionHandler
处理程序,该错误的含义是:“ 我不知道我是否能够做某事,或者是否正在做其他事情,但我厌倦了等待自己 。” 大多数情况下,事务处理良好,必须忽略处理程序中出现的错误。 可以在更高的级别上进行某些更改,但是,如果您已经必须使用事务性更改,那么最好将它们用于所有内容。
通常,队列是非常灵活的,并且如果您的应用程序不可能一次与其他流服务21一起工作 ,那么您可以对队列做很多有趣的事情,特别是指出什么时候开始播放什么元素以及持续多长时间。
在此高级方法的其他“ 缺点 ”中,值得注意的是无法处理用户操作。 将用户按在“ 下一首 ”按钮的耳机上不会导致对程序“ 我应该做什么 ”的请求,播放器会更好地知道该怎么做,并将自己切换歌曲。 因此,您只能捕获播放器状态中实际完成的更改,然后根据实际情况做出一些决策。
另一方面,您无需做太多事情:在锁定屏幕上播放信息就在那里,并且所有按钮都可以使用,Apple Watch和Siri可以控制播放,而通过AirPlay到Apple TV的流媒体播放则在第22栏中。
可以在您的应用程序中重复Music.app队列的功能和界面,但是实际上,队列中拖放元素的看似简单实际上是在变通事务以更改队列并同步所需的队列和23个播放器的真实队列。
实际上,在其他平台上使用API并没有什么不同,但SDK并未完全与iOS完全兼容,并且在某些地方更为方便24 ,尽管仍然保留了串联队列和播放器的一般概念。
因此,在Android下,您可以通过事务更改( 从队列中删除并用手指交叉将其添加到正确的位置 )来获取当前队列并移动该 队列中 的元素而无需花招。
MusicKit JS还提供了用于处理Apple Music API的特殊包装方法 ,
但是在使用包装器时,您必须阅读API本身的文档。 使用队列和播放器并没有比iOS SDK更方便 ,但是使用小的附加组件就可以忍受 。
关于模拟器的几句话
您只能在与HTTP API通信的上下文中使用MusicKit在模拟器中工作,但是即使在这种情况下,您也必须稳定用户的令牌来进行请求,而不是通过StoreKit来获取。 因为缺少Music.app应用程序,所以完全不可能在模拟器中播放Apple Music的音乐。
实际上,您必须在SDK上开发自己的附加组件,并且在模拟器中运行时,使用替代( 模拟 )实现。 实际上,在开发过程中,模拟器仅用于在用户界面上工作。 自己的抽象在应用程序的自动屏幕截图中( 以及实际上在使用模拟器创建屏幕截图时 )也很有用 ,因为在武器库中拥有两代“大型” iPad Pro只是为了在两个屏幕上都为您的播放器拍摄屏幕截图是极其无利且愚蠢的。
作为一个有趣但不太有用的实验,您可以基于MusicKit JS替代自己的高级播放器。
关于企业合作伙伴供稿
一方面,Apple可应要求提供元数据转储,并表示要使用它以减轻API的负担并获取API没有的信息。 另一方面,我们对鸡肉和鸡蛋存在明显的问题:通过指定应用程序的链接,可以访问Affiliate程序。 使用只能通过在App Store上发布的应用程序才能获得的数据来开发应用程序是非常困难的。
而且,当然,数据不会给第一个来者。 每个申请将在五个工作日内得到检查。 在撰写本文时,我还没有获得元数据转储。 Apple包装了我的应用程序,但未指定确切原因。 , - " Apple Music " , Apple . - , -, . , Apple , , .
, , . Apple Music ( , ), . , , Apple Music . , , .
Enterprise Partner Feed :
- Apple Music API iTunes Search API
- (" "), -
, - :
- . , , .
, . , - - - , , . , - , -.
- , SDK , . Apple 25 SDK 26 , , , API , SDK .
- , " code level " . " Q&A " " Tech Notes ", , - .
- . , , . API ( Last.fm, musicbrainz, iTunes Search API ) IP . Apple Music . " " , 27 .
- , Apple Music API, , . - App Store , ( ) , , ( ). 28 , , , 29 . Apple 30 .
- , - Apple Music — Ember. , , html DOM Javascript.
- -, , . , .
SDK, batch API, , « » Apple Music. , , SDK . SDK, .
, .
1 ( )
2 ,
3 , Music.app - ( ), API ( "" )
4 limit
: Specified limit for relationship 'songs' exceeds maximum of 20
5 The Beatles
6 , Apple Music iTunes Store. API iTunes Store `isStreamablez, Apple Music .
7 : https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewArtistSeeAll?cc=ru&ids=424279384§ion=0
8 , , , iTunes ( ) iTunes Store
9
10 , !
11 , Apple Music : , ,
12 , MPMusicPlayerPlayParametersQueueDescriptor
13 Apple Music , ( ) . .
14 , , App Store
15 ( ) ( ) ( ) ( ) . .
16 -,
17 , iTunes Store iTunes Match
18 API URL
19 — -, . , .
20 : ( When your app moves to the background, the music player stops playing the current media. ). AVPlayer
, , Info.plist
.
21 .
22 , MPMediaItem
23
24 , SDK , , . iOS Media Player
, API .
25 , — , .
26 SDK , Apple Music. Apple , .
27 , — . , Enterprise Partner Feed, musicbrainz, API. , ( ) . , .
28 RIP
29 API Bing
30