musickit-audio について
Appleプラットフォームのアプリ開発者向けに、MusicKitとMediaPlayerの使い方を解説するスキルです。Apple Musicの検索や購読確認、アプリ内再生、Now Playing情報とリモート操作を扱います。
主な機能
- 01Apple Musicカタログの検索
- 02購読状況の確認
- 03ApplicationMusicPlayerでの再生
- 04再生キューの管理
- 05Now Playingメタデータの更新
- 06リモート再生命令の処理
活用シーン
- 01アプリ内でのApple Music楽曲検索
- 02購読状況に応じたカタログ再生の制御
- 03カスタム音声のロック画面情報表示
- 04AirPodsやCarPlayの操作への応答
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dpearson2699/ swift-ios-skills --skill musickit-audioインストール後、Claude Code で/musickit-audioを入力して読み込まれたか確認します。
同梱ファイルreferences/musickit-patterns.md
詳細
MusicKit + MediaPlayer
Apple Music カタログを検索し、ApplicationMusicPlayer で再生を管理し、サブスクリプションを確認して、MPNowPlayingInfoCenter
と MPRemoteCommandCenter を介して「再生中」のメタデータを公開します。対象は Swift 6.2 / iOS 26 以降です。
目次
- セットアップ
- 認証
- カタログ検索
- サブスクリプションの確認
- ApplicationMusicPlayer による再生
- キュー管理
- 再生中の情報
- リモートコマンドセンター
- よくある間違い
- レビュー用チェックリスト
- 参考資料
セットアップ
プロジェクトの設定
- Xcode で MusicKit ケイパビリティを有効にします(
com.apple.developer.musickitエンタイトルメントが追加されます) - Info.plist に
NSAppleMusicUsageDescriptionを追加し、アプリが Apple Music にアクセスする理由を説明します - バックグラウンド再生を行うには、
UIBackgroundModesにaudioバックグラウンドモードを追加します
インポート
import MusicKit // Catalog, auth, playback
import MediaPlayer // MPRemoteCommandCenter, MPNowPlayingInfoCenter
認証
ユーザーのミュージックデータにアクセスしたり、Apple Music のコンテンツを再生したりする前に、許可をリクエストします。認証プロンプトは、アプリのインストールごとに一度だけ表示されます。
func requestMusicAccess() async -> MusicAuthorization.Status {
let status = await MusicAuthorization.request()
switch status {
case .authorized:
// Full access to MusicKit APIs
break
case .denied, .restricted:
// Show guidance to enable in Settings
break
case .notDetermined:
break
@unknown default:
break
}
return status
}
// Check current status without prompting
let current = MusicAuthorization.currentStatus
カタログ検索
MusicCatalogSearchRequest を使用して Apple Music カタログを検索します。カタログ全体にアクセスするには、ユーザーが Apple Music に登録している必要があります。
func searchCatalog(term: String) async throws -> MusicItemCollection<Song> {
var request = MusicCatalogSearchRequest(term: term, types: [Song.self])
request.limit = 25
let response = try await request.response()
return response.songs
}
結果の表示
for song in songs {
print("\(song.title) by \(song.artistName)")
if let artwork = song.artwork {
let url = artwork.url(width: 300, height: 300)
// Load artwork from url
}
}
サブスクリプションの確認
再生機能を提供する前に、ユーザーが有効な Apple Music サブスクリプションに登録しているかどうかを確認します。
func checkSubscription() async throws -> Bool {
let subscription = try await MusicSubscription.current
return subscription.canPlayCatalogContent
}
// Observe subscription changes
func observeSubscription() async {
for await subscription in MusicSubscription.subscriptionUpdates {
if subscription.canPlayCatalogContent {
// Enable full playback UI
} else {
// Show subscription offer
}
}
}
Apple Music の案内
ユーザーが未登録の場合は、Apple Music のサブスクリプション案内シートを表示します。
import MusicKit
import SwiftUI
struct MusicOfferView: View {
@State private var showOffer = false
var body: some View {
Button("Subscribe to Apple Music") {
showOffer = true
}
.musicSubscriptionOffer(isPresented: $showOffer)
}
}
ApplicationMusicPlayer による再生
ApplicationMusicPlayer は、ミュージックアプリとは独立して Apple Music のコンテンツを再生します。システムプレーヤーの状態には影響しません。
let player = ApplicationMusicPlayer.shared
func playSong(_ song: Song) async throws {
player.queue = [song]
try await player.play()
}
func pause() {
player.pause()
}
func skipToNext() async throws {
try await player.skipToNextEntry()
}
再生状態の監視
func observePlayback() {
// player.state is an @Observable property
let state = player.state
switch state.playbackStatus {
case .playing:
break
case .paused:
break
case .stopped, .interrupted, .seekingForward, .seekingBackward:
break
@unknown default:
break
}
}
キュー管理
ApplicationMusicPlayer.Queue を使用して再生キューを作成、操作します。
// Initialize with multiple items
func playAlbum(_ album: Album) async throws {
player.queue = [album]
try await player.play()
}
// Append songs to the existing queue
func appendToQueue(_ songs: [Song]) async throws {
try await player.queue.insert(songs, position: .tail)
}
// Insert song to play next
func playNext(_ song: Song) async throws {
try await player.queue.insert(song, position: .afterCurrentEntry)
}
再生中の情報
MPNowPlayingInfoCenter を更新すると、ロック画面、コントロールセンター、CarPlay に現在のトラックのメタデータが表示されます。カスタムオーディオ(MusicKit 以外のソース)を再生する場合は必須です。Apple Music のコンテンツでは、ApplicationMusicPlayer がこの処理を自動的に行います。
import MediaPlayer
func updateNowPlaying(title: String, artist: String, duration: TimeInterval, elapsed: TimeInterval) {
var info = [String: Any]()
info[MPMediaItemPropertyTitle] = title
info[MPMediaItemPropertyArtist] = artist
info[MPMediaItemPropertyPlaybackDuration] = duration
info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsed
info[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.audio.rawValue
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
}
func clearNowPlaying() {
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
}
アートワークの追加
func setArtwork(_ image: UIImage) {
let artwork = MPMediaItemArtwork(boundsSize: image.size) { _ in image }
var info = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
info[MPMediaItemPropertyArtwork] = artwork
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
}
リモートコマンドセンター
MPRemoteCommandCenter のハンドラーを登録して、ロック画面のコントロール、AirPods のタップ操作、CarPlay のボタンに応答します。
func setupRemoteCommands() {
let center = MPRemoteCommandCenter.shared()
center.playCommand.addTarget { _ in
resumePlayback()
return .success
}
center.pauseCommand.addTarget { _ in
pausePlayback()
return .success
}
center.nextTrackCommand.addTarget { _ in
skipToNext()
return .success
}
center.previousTrackCommand.addTarget { _ in
skipToPrevious()
return .success
}
// Disable commands you do not support
center.seekForwardCommand.isEnabled = false
center.seekBackwardCommand.isEnabled = false
}
シーク操作のサポート
func enableScrubbing() {
let center = MPRemoteCommandCenter.shared()
center.changePlaybackPositionCommand.addTarget { event in
guard let positionEvent = event as? MPChangePlaybackPositionCommandEvent else {
return .commandFailed
}
seek(to: positionEvent.positionTime)
return .success
}
}
よくある間違い
やってはいけないこと:MusicKit エンタイトルメントまたは使用目的の説明を省略する
MusicKit エンタイトルメントがないと、認証時にアプリがクラッシュします。NSAppleMusicUsageDescription がない場合、App Review で申請が却下されます。
// WRONG: No entitlement configured
let status = await MusicAuthorization.request() // Crashes
// CORRECT: Enable MusicKit capability in Xcode first,
// then add NSAppleMusicUsageDescription to Info.plist
let status = await MusicAuthorization.request()
やってはいけないこと:再生前にサブスクリプションを確認し忘れる
サブスクリプションに登録せずにカタログのコンテンツを再生しようとすると、失敗が通知されずに再生されないか、エラーがスローされます。
// WRONG
func play(_ song: Song) async throws {
player.queue = [song]
try await player.play() // Fails if no subscription
}
// CORRECT
func play(_ song: Song) async throws {
let sub = try await MusicSubscription.current
guard sub.canPlayCatalogContent else {
showSubscriptionOffer()
return
}
player.queue = [song]
try await player.play()
}
やってはいけないこと:ApplicationMusicPlayer を使うべき場面で SystemMusicPlayer を使う
SystemMusicPlayer はミュージックアプリのグローバルキューを操作します。変更はユーザーのミュージックアプリの状態に影響します。アプリ内で完結する再生には ApplicationMusicPlayer を使用してください。
// WRONG: Modifies the user's Music app queue
let player = SystemMusicPlayer.shared
// CORRECT: App-scoped playback
let player = ApplicationMusicPlayer.shared
やってはいけないこと:トラック変更時に「再生中」の情報を更新し忘れる
ロック画面に古いメタデータが表示されると、ユーザーが混乱します。現在のトラックが変わるたびに、「再生中」の情報を更新してください。
// WRONG: Set once and forget
updateNowPlaying(title: firstSong.title, ...)
// CORRECT: Update on every track change
func onTrackChanged(_ song: Song) {
updateNowPlaying(
title: song.title,
artist: song.artistName,
duration: song.duration ?? 0,
elapsed: 0
)
}
やってはいけないこと:処理せずにリモートコマンドを登録する
コマンドを登録して .commandFailed を返すと、ロック画面のコントロールが機能しなくなります。サポートしていないコマンドは、代わりに無効にしてください。
// WRONG
center.skipForwardCommand.addTarget { _ in .commandFailed }
// CORRECT
center.skipForwardCommand.isEnabled = false
レビューチェックリスト
- Xcode プロジェクトで MusicKit の機能を有効化している
- Info.plist に
NSAppleMusicUsageDescriptionを追加している - MusicKit にアクセスする前に
MusicAuthorization.request()を呼び出している - カタログの再生を試みる前にサブスクリプションを確認している
- アプリ内での再生には
SystemMusicPlayerではなくApplicationMusicPlayerを使用している - 音楽をバックグラウンドで再生する場合は、バックグラウンドオーディオモードを有効にしている
- カスタムオーディオでは、トラックが変わるたびに再生中情報を更新している
- リモートコマンドのハンドラーが、対応するコマンドに対して
.successを返す - 対応していないリモートコマンドは
isEnabled = falseで無効にしている - ロック画面に表示するため、再生中情報にアートワークを設定している
- スクラバーの精度を保つため、再生経過時間を定期的に更新している
- ユーザーが Apple Music のサブスクリプションに登録していない場合、サブスクリプションの案内を表示している
参考資料
- 拡張パターン(SwiftUI との統合、ジャンルの閲覧、プレイリスト管理):
references/musickit-patterns.md - MusicKit フレームワーク
- MusicAuthorization
- ApplicationMusicPlayer
- MusicCatalogSearchRequest
- MusicSubscription
- MPRemoteCommandCenter
- MPNowPlayingInfoCenter
- NSAppleMusicUsageDescription