Palavras introdutórias
Não importa o quanto eles repreendam a Apple pela natureza fechada da plataforma e do próprio ecossistema, algumas de suas soluções são uma exceção. Existem muitos serviços de streaming no mercado, mas o fornecimento de um SDK completo para streaming em produtos de terceiros é extremamente pequeno; para o mercado russo, a lista de SDKs disponíveis oficialmente é limitada ao Deezer e à Apple Music. Obviamente, quando o Spotify chegar ao nosso mercado, haverá mais SDKs disponíveis, mas até agora existem dois players e apenas um deles possui uma ampla base de usuários.
Aconteceu que eu tinha experiência com o Deezer SDK para Android e agora estou trabalhando ativamente com o Apple Music SDK ( MusicKit ) para iOS. E a principal diferença da experiência com o Deezer é que o MusicKit é a ponta do iceberg, também é uma API disponível ao público. Ao contrário do Deezer, onde repetir a maior parte da funcionalidade do aplicativo oficial é apenas um processo demorado, é impossível repetir a funcionalidade das páginas da web do Apple Music usando apenas a API pública. Mesmo que a Apple use o MusicKit em suas soluções, além disso, ela usa uma série de solicitações de API não documentadas e APIs privadas que não são permitidas pelos mortais.
No artigo, falarei sobre como trabalhar com o MusicKit do ponto de vista do desenvolvedor no contexto da implementação de " tarefas simples ": pesquise no catálogo, mostre imagens nos resultados da pesquisa, obtenha músicas, recomendações e até toque algum tipo de música. Olhando para o futuro, direi que grande parte das opções acima será verdadeira para trabalhar com a Apple Music no Android e Javascript.
Se necessário, estou pronto para fornecer respostas detalhadas com um código para perguntas nos comentários.
Moscas separadas de costeletas
Ao trabalhar com o MusicKit no iOS, você precisará interagir com as seguintes entidades:
- StoreKit para autorização no Apple Music e para oferecer uma assinatura do serviço ( referência se você pode se inscrever no programa Afiliado )
- API HTTP para pesquisar e recuperar várias informações de um diretório
- API de Pesquisa do iTunes para pesquisar no diretório do iTunes (uma alternativa muito útil à API HTTP ). A Apple indica um limite de no máximo 20 solicitações por minuto, o que geralmente é suficiente ao fazer solicitações dos dispositivos dos usuários
- Media Player para reproduzir e gerenciar a fila
Além disso, ao se conectar a um programa de afiliados, você pode solicitar acesso ao dump de metadados do Enterprise Partner Feed , recomendado pela Apple, em vez de solicitações frequentes à API de pesquisa do iTunes.
E, por precaução, o Music.app é o aplicativo Music em dispositivos iOS, que é o player oficial da Apple Music.
Fontes de informação, em ordem decrescente de sua utilidade:
- Documentação oficial
- Pesquisar toda a documentação da Apple
- Método 1 da experiência científica com API HTTP
- Console do desenvolvedor no seu navegador favorito, associado à página da web da entidade de interesse no Apple Music
- Fóruns de desenvolvedores da Apple
- Stackoverflow
Pesquisar. Imagens
A maneira mais óbvia de verificar se algo pode ser feito em seu aplicativo é o fato de que algo assim esteja disponível no aplicativo oficial. Aqui tomamos, por exemplo, uma pesquisa. Estamos procurando o grupo "The Police" e no Music.app
temos uma foto do grupo com uma Sting sorridente:

Ótimo, usaremos a API de pesquisa . Na emissão, temos a chave da artwork
final com um link de url
incorporado para tudo, exceto artistas. Isso é estranho Verifique novamente, no Music.app está tudo lá. Além disso, a interface da web também possui uma fotografia e um link para a página da web está disponível na API do mecanismo de pesquisa json.
A API de pesquisa do iTunes também não artistLinkUrl
imagem, mas também inclui o endereço da página da web com a chave artistLinkUrl
na artistLinkUrl
.
Bem, o que fazer, você precisa baixar a página da Web e obter o endereço da imagem, felizmente, os desenvolvedores cuidaram e registraram o endereço da imagem na meta-informação:
<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">
Formalmente, já violamos as regras da Apple que proíbem "raspar" suas páginas da web. De fato, todos os aplicativos de terceiros fazem isso, exceto aqueles que procuram fotos usando serviços de terceiros.
Há mais um menos: solicitamos uma página com várias centenas de kilobytes de tamanho. Para um aplicativo que já gera grandes quantidades de dados ( tocando música ), é tolerável ( especialmente quando você considera que os dados são transmitidos em forma compactada ), mas, no caso geral, não é muito.
Os tamanhos das imagens podem ser ajustados às suas necessidades: no url
existem modelos para substituição ( {w}
, {h}
) e, na página da web, o link para a imagem tem o mesmo formato, portanto, não há dificuldade em obter a imagem do tamanho certo. Se você deseja obter uma imagem arredondada, adicione cw
antes da extensão.
Bônus sobre imagens a serem exibidas no player
Durante a reprodução, o player do Media Player
opera na construção MPMediaItem
, que, em particular, fornece um objeto Artwork
. É muito conveniente para exibir uma imagem de uma faixa no player. O único problema é que, na prática, esse objeto, o que quer que se diga, não fornece imagens para streaming de música ( que é qualquer música da Apple Music ), então você precisa "reproduzir" o MPMediaItem
reproduzido com músicas que foram adicionadas à fila e baixadas a imagem é semelhante aos álbuns.
Pesquisa por gênero
O iTunes e o aplicativo Apple Music têm listas de gêneros e músicas principais. Encontrar um gênero não deve ser difícil, porque podemos procurar alguma coisa?
Isso está longe de ser o caso. A API não pesquisa por gênero e não fornece uma lista de gêneros. É possível solicitar informações ( de nome útil ) de um gênero por seu identificador,
mas a maioria das informações na API contém apenas o nome do gênero, não o identificador.
O benefício para o iTunes é o descarregamento de todos os gêneros ( todos eles, incluindo os "gêneros" dos aplicativos móveis ). Identificadores de gêneros ( como outros identificadores do iTunes ) correspondem totalmente aos identificadores no Apple Music. O descarregamento está disponível para todas as regiões (a região é indicada na chave cc
, não na storefront
da storefront
como na Apple Music API ), mas, na verdade, apenas os nomes diferem ( eles são traduzidos ). A estrutura dos gêneros é hierárquica e há repetições dos nomes dos gêneros.
Em geral, uma pesquisa por gênero deve ser feita localmente, e lembre-se de que o funk jazz, o jazz funk e o jazz funk são a mesma coisa. Não é difícil, mas não tão simples quanto pedir à API de pesquisa para pesquisar por gênero.
Tendo encontrado um gênero, você pode solicitar um gráfico (uma lista das músicas mais populares ) para esse gênero. Para gêneros raros, é bem possível obter apenas 3 músicas.
Curiosidade: para alguns álbuns e artistas ( Ed Sheeran, do famoso ), apenas um dos gêneros indica simplesmente o gênero de nível superior de "Music". Se você deseja fazer recomendações com base em gêneros, esse gênero deve ser ignorado.
Canções de Artista
Quando um aplicativo precisa reproduzir músicas de um artista ( grupo musical ) com mais frequência, isso significa que é necessário reproduzir músicas populares desse grupo. O Apple Music possibilita solicitar músicas como um link "músicas" 2 para o artista. A saída tem no máximo 20 músicas 3 , claramente classificadas por popularidade.
Às vezes você ainda deseja obter um pouco mais de músicas. Com grupos muito populares, há uma opção para obter listas de reprodução como " [Nome do artista]: Essentials " e " [Nome do artista]: Detalhes " (" [Nome do artista]: próximas etapas "), mas em geral, esta opção não é adequada. Outra opção: pegue 20 músicas populares e finalize o restante dos álbuns, o benefício do Apple Music possibilita obter imediatamente todos os álbuns de artistas ( links como albums
) e todas as músicas neles ( include="tracks"
) em uma solicitação.
Mas se você receber todas as músicas do artista, surge outro problema: você precisa selecionar as músicas populares de todas essas músicas. Infelizmente, a API de informações de popularidade não fornece 4 . Você pode tirar músicas aleatórias de toda a lista, mas, na prática, essa abordagem leva à reprodução frequente de gravações completamente desinteressantes ( transcrições ao vivo, gravações de ensaios, eremitérios etc. ), o que é especialmente perceptível em grupos muito populares 5 .
Vamos tentar obter músicas populares de uma maneira diferente. Mesmo antes do advento do MusicKit, a Apple começou a fornecer APIs de pesquisa na iTunes Store. Como já mencionado, o catálogo na Apple Music e na iTunes Store são os mesmos 6 e, portanto, os identificadores das músicas também são os mesmos. Essa API retorna 50 músicas por padrão, mas você pode solicitar até 200 músicas. Os resultados também são classificados por popularidade.
Curiosamente, a própria Apple não usa nenhuma dessas opções em sua própria interface da web. Eles usam a API 7 não documentada ( leitura, privada ) 7 , cuja emissão está faltando, incluindo o identificador ( e não apenas o nome ) do gênero e o índice de popularidade. Não ousei usar essa API na prática 8 , pois os identificadores de gênero podem ser obtidos por pesquisa reversa pelos nomes de gênero 9 e o índice numérico de popularidade não é tão importante quando você obtém uma lista de músicas classificadas por popularidade.
O fato engraçado que chamo de " problema de Hugh Laurie " é que o catálogo da Apple Music tem toneladas de conteúdo não musical. Em particular, várias compilações de programas de comédia e stand-ups. Isso é bom, por um lado ( pagamos pela música, mas também tivemos diálogos engraçados com Stephen Fry, que você pode ouvir antes de ir para a cama ) e, por outro, isso leva a algum tipo de conversa quando solicitado a ativar a música. Por conseguinte, quando o contexto operacional do aplicativo indica diretamente que o usuário deseja ouvir música, é necessário remover independentemente da lista de " músicas " aquelas cujos gêneros são designados como " palavra falada " e " comédia ".
Recomendações
Recomendações de reprodução (também são " músicas semelhantes ", " estações de rádio ", " você vai gostar " etc.) tornaram-se a funcionalidade básica dos players de streaming. Convencionalmente, as recomendações podem ser divididas em dois tipos 10 : para o usuário (com base no histórico de audição, compras e curtidas ) e para o objeto musical ( artista, faixa, menos frequência, álbum e lista de reprodução ).
Com as preferências do usuário no Apple Music, 11 tudo está bem: você pode solicitar uma lista de recomendações pessoais, que incluem " mixagens pessoais " ( listas de reprodução ) e álbuns recomendados. Nos álbuns, é possível obter uma lista de músicas usando as API ( tracks
da API ( tracks
) , para listas de reprodução da mesma forma. Lembre-se de que as faixas podem incluir não apenas músicas ( type = "songs"
), mas também clipes de vídeo, para que a filtragem adicional dos dados recebidos não prejudique.
Com outras recomendações, tudo é um pouco mais complicado. Se você olhar para o Music.app, " artistas semelhantes " serão exibidos lá e você poderá ativar a " estação de rádio " desse artista. O último perde a mistura do artista e recomendações para ele.

Parece que tudo é simples: para artistas, provavelmente existe uma conexão de " artistas semelhantes ". Corro para chatear, não existe tal conexão. Também não há informações de similaridade no esquema de dados do Enterprise Partner Feed.
Ok, então podemos solicitar uma " estação de rádio " para o artista e obter uma lista de músicas? E, novamente, não, podemos realmente solicitar uma estação de rádio, seu identificador está na emissão das conexões do artista. Mas nas informações da estação não há informações sobre as músicas, álbuns ou artistas sendo reproduzidos, há apenas um objeto de serviço com informações para reproduzir playParams
. A idéia com playParams
simples: alimentamos esse dicionário 12 na fila de reprodução e ouvimos.
Tudo isso é bom se você deseja reproduzir apenas uma estação de rádio ( como o Music.app ), mas e se você quiser misturar músicas da estação de rádio 13 com outra coisa? Obviamente, precisamos de alguma forma obter uma lista de artistas semelhantes.
No Media Player
, as filas de reprodução desempenham um papel importante, em particular MPMusicPlayerControllerMutableQueue . A fila permite: inserir descritores após um determinado objeto reproduzível, excluir objetos especificados e também obter uma lista de todos os objetos na fila. Ao consultar objetos para saída, devemos obter uma matriz de MPMediaItem
. E o MPMediaItem
, em particular, inclui o identificador da música . Há apenas um problema: os construtores de filas não são uma API pública, traduzirei: o Media Player
pode fornecer uma fila pronta (às vezes editável ), mas é impossível criar você mesmo 14 .
Bem, cavar um pouco em direção às muletas pode ser útil. Se o Media Player
puder me fornecer uma fila variável, eu preciso aceitá-la. Para fazer isso, você terá que trabalhar com o atual ( singleton ) player, para que você precise agir rapidamente, caso contrário, o usuário poderá perder algo errado, e o player ainda terá tempo para pré-carregar as músicas que são desnecessárias até o momento. Mudamos a fila de reprodução atual ( adicionamos o descritor da estação ), olhamos o que aconteceu, reverte as alterações na fila com uma nova transação ( exclua o que realmente foi adicionado à fila ).
Infelizmente, descobrimos que apenas dois objetos MPMediaItem
são MPMediaItem
à fila. Ambos parecem músicas ( existe o nome do artista, o nome da faixa, o comprimento da faixa ), mas não incluem o identificador da música. Se você olhar para Music.app, descobrimos que tudo converge para lá: ligar a estação de rádio tocará a música e, na fila, haverá apenas uma música para tocar. Quando você passa para a próxima música, a fila é atualizada.
Não faz sentido tentar aumentar ainda mais as muletas com as estações de rádio; é preciso usar outras opções.
Lembre-se de que, no Music.app e na interface da web, artistas semelhantes são exibidos. Artistas semelhantes estão disponíveis apenas para as bandas mais populares 15 . Novamente, você deve recorrer ao método proibido de analisar uma página da web. Dos profissionais: já estamos baixando uma página da web para obter uma imagem, para que possamos obter artistas semelhantes imediatamente.
No código da página html, vemos um grande objeto json, do qual escolhemos primeiro os identificadores de artistas semelhantes ( ["data"]["relationships"]["artistContemporaries"]
):

e, usando esses identificadores, obtemos os dados do artista do mesmo json ( ["included"]
com o tipo lockup/artist
):

Tendo os identificadores dos artistas, podemos solicitar suas faixas. A API permite solicitar vários artistas por seus identificadores em uma única solicitação com os links ativados. Infelizmente, na prática, a API retorna um erro indicando a impossibilidade de adicionar uma lista de trilhas ao resultado. Isso só pode ser feito solicitando artistas um de cada vez ou solicitando diretamente músicas para um único artista. Nesse caso, você pode usar a API de pesquisa do iTunes já mencionada, que fornecerá informações um pouco mais úteis.
As listas de " artistas semelhantes " no Apple Music são muito boas, mas, na prática, muitas vezes acabam vazias. Na situação de uma lista vazia de recomendações, você precisa usar serviços de terceiros. Clássicos - Last.fm, um pouco mais sofisticado - Spotify. Os resultados de ambos precisam corresponder aos objetos no catálogo da Apple Music. A solução "na testa" é procurar cada artista pelo nome com exatamente um resultado e depois receber as músicas conforme descrito acima. As soluções são um pouco mais interessantes, mas é mais caro usar o musicbrainz para correspondência. O Musicbrainz fornece informações sobre os identificadores 16 em outros serviços, ou seja, Você pode associar um identificador no Spotify a um identificador no Apple Music. A situação com a Last.fm é ainda melhor: a Last.fm retorna identificadores de musicbrainz na lista de recomendações. A sobrecarga está nos limites do uso do musicbrainz, com muito tráfego que você precisa para criar seu próprio clone do musicbrainz (felizmente, isso é possível ) ou desenvolver sua própria API em torno de um banco de dados , cujos arquivos podem ser facilmente baixados.
Para novos grupos, até o Last.fm não dará recomendações; as opções alternativas são recomendações de "gênero". Pegamos os gêneros do artista ( com base no nome, obtemos identificadores da lista já carregada de todos os gêneros ), obtemos o gráfico de cada gênero, misturamos as músicas recebidas. Isso é melhor que nada.
Duas coisas são inseparáveis: jogador e fila
O Media Player é responsável pela reprodução no iOS do Apple Music; ele permite trabalhar com músicas do Apple Music e o diretório pessoal do usuário 17 . A estrutura é de alto nível e, na situação de trabalhar com conteúdo de streaming, descer para um nível abaixo de 18 não funcionará.
A estrutura fornece a dois players uma interface de software comum: um toca música diretamente no aplicativo Music.app e o outro funciona de maneira mais ou menos independente. Usar o primeiro para algo sério não faz sentido 19 . E a documentação descaradamente mente 20 que o segundo jogador não funciona em segundo plano
Do lado da arquitetura, trabalhar com esse assunto é simples: dizemos ao player o que tocar ( por exemplo, preenchendo a fila, com base em uma variedade de identificadores de música ) e controlamos a reprodução ( reproduzir, pausar, seguinte, anterior ).
Não há controle direto da fila de reprodução, é necessário executar uma alteração transacional , o que leva tempo. Além disso, muitas vezes o manipulador de completionHandler
é chamado com um erro de tempo limite, que se traduz como " Não sei se fui capaz de fazer algo ou se estou fazendo outra coisa, mas estou cansado de esperar por mim ". Na maioria das vezes, a transação vai bem e os erros que chegam ao manipulador precisam ser ignorados. Algumas das alterações podem ser feitas em um nível um pouco mais alto; no entanto, se você já precisou usar alterações transacionais, é melhor usá-las para tudo.
Em geral, as filas são bastante flexíveis e, se não for provável que seu aplicativo funcione com outros serviços de streaming 21 algum dia, você pode fazer muitas coisas interessantes com as filas, em particular, indicar a que horas o elemento começa a ser reproduzido e por quanto tempo.
Dos outros " desvios " dessa abordagem de alto nível, vale a pena notar a incapacidade de processar ações do usuário. Pressionar o usuário no fone de ouvido do botão " próxima faixa " não levará a uma solicitação do programa " o que devo fazer ", o jogador saberá melhor o que fazer e mudará a música. Portanto, você só pode capturar as alterações realmente concluídas no estado do jogador e tomar algumas decisões após o fato.
Por outro lado, você não precisa fazer muito: as informações sobre a reprodução na tela de bloqueio estão simplesmente lá e todos os botões funcionam, o Apple Watch e o Siri podem controlar a reprodução, e a transmissão via AirPlay para a Apple TV funciona fora da caixa 22 .
É possível repetir a funcionalidade e a interface da fila Music.app em seu aplicativo, mas a aparente simplicidade dos elementos de arrastar e soltar da fila acaba sendo transações de malabarismo para alterar a fila e sincronizar a fila desejada e a fila real de 23 jogadores.
De fato, trabalhar com a API não é diferente em outras plataformas, mas os SDKs não são completamente copiados em carbono com o iOS e, em alguns lugares, são mais convenientes 24 , embora a idéia geral de uma fila e um player tandem permaneçam.
Portanto, no Android, você pode obter a fila atual e mover os elementos da fila sem truques com uma mudança transacional ( removendo da fila e adicionando ao lugar certo com os dedos cruzados ).
O MusicKit JS também fornece métodos especiais de invólucro para trabalhar com a Apple Music API,
mas, ao usar wrappers, você não pode ficar sem ler a documentação da própria API. Trabalhar com a fila e o player não é mais conveniente que o SDK do iOS , mas com pequenos complementos, ele pode se tornar suportável .
Algumas palavras sobre o simulador
Você pode trabalhar no simulador com o MusicKit apenas no contexto da comunicação com a API HTTP, mas, mesmo nesse caso, será necessário estabilizar o token do usuário para a realização de solicitações e não obtê-lo através do StoreKit . É completamente impossível reproduzir música do Apple Music no simulador, porque o aplicativo Music.app está ausente.
De fato, você precisa desenvolver seus próprios complementos no SDK e, ao executar no simulador, usar implementações alternativas ( simuladas ). De fato, durante o desenvolvimento, o simulador é útil apenas para trabalhar na interface do usuário. A própria abstração também será útil em capturas de tela automatizadas para o aplicativo ( e, de fato, ao criar capturas de tela usando um simulador ), já que ter duas gerações de “grandes” profissionais de iPad no arsenal apenas para capturar capturas de tela do seu player em ambos é extremamente inútil e estúpido. .
Como um experimento interessante, mas não muito útil, você pode fazer uma implementação alternativa do seu próprio player de alto nível com base no MusicKit JS.
Sobre o feed do parceiro corporativo
Por um lado, a Apple fornece um despejo de metadados mediante solicitação e diz para usá-lo para reduzir a carga na API e obter informações que a API não possui. Por outro lado, temos um problema claro com frango e ovos: o acesso ao programa de afiliados é fornecido especificando um link para o aplicativo. É bastante difícil desenvolver um aplicativo usando os dados que podem ser obtidos apenas com o aplicativo publicado na App Store.
E, é claro, os dados não são os primeiros a chegar. Cada aplicativo é verificado dentro de cinco dias úteis. No momento da redação deste artigo, eu não consegui obter um despejo de metadados em minhas mãos. A Apple encerrou meu aplicativo sem especificar os motivos exatos. , - " 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