Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
プロトコルを使って複数サービスを跨いだmusic playerを実装する
Search
Hiroki Kumamoto
September 02, 2018
670
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
プロトコルを使って複数サービスを跨いだmusic playerを実装する
Hiroki Kumamoto
September 02, 2018
More Decks by Hiroki Kumamoto
See All by Hiroki Kumamoto
How to implement timetable view on iOS
kumabook
0
120
Promiseを実装してみよう
kumabook
0
350
bff_tips.pdf
kumabook
0
100
Tips of server-side rendering with react + redux
kumabook
0
100
emacs helm likeな WebExtensions を作った話
kumabook
0
180
merges sort
kumabook
0
89
lightweight introducing with reactive cocoa
kumabook
0
70
basic_sort
kumabook
0
79
git_peco_tips
kumabook
0
39
Featured
See All Featured
The agentic SEO stack - context over prompts
schlessera
0
820
Optimizing for Happiness
mojombo
378
71k
RailsConf 2023
tenderlove
30
1.5k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
150
Building Adaptive Systems
keathley
44
3.1k
Faster Mobile Websites
deanohume
310
31k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
540
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
950
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
71
40k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
270
Claude Code のすすめ
schroneko
67
230k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
170
Transcript
ϓϩτίϧΛͬͯෳαʔ ϏεΛލ͍ͩmusic playerΛ ࣮͢Δ iOSDC 2018/09/02 Hiroki Kumamoto a.k.a kumabook
ࣗݾհ • Hiroki Kumamoto • a.k.a kumabook (twitter, github) •
Software engineer at Spincoaster, Inc. • swift, JavaScript, ruby, rust ...
ϦΞϧ ͳ Իָγʔϯͱ ग़ ѭ͏ M U S I C
C H A R T T OP 10 0
TYPICA • ԻָϙʔλϧΞϓϦ • @TYPICA_JP • Web: typica.mu • iOSΞϓϦ
• ʰϦΞϧͳԻָγʔϯͷՄࢹԽʱΛࢦͨ͠ԻָαʔϏε • Web্ͷԻָใΛΫϩʔϧͯ͠Ϩίϝϯυ • Իָʹؔ͢ΔهࣄԻָαʔϏεͷۂɺΞϧόϜɺϓϨΠϦετ • TYPICA Top 100 (https://typica.mu/ja/chart/top100) • ಠࣗͷϥϯΩϯάγεςϜ
ΞϓϦϓϨʔϠ • AppleMusic, Spotify, YouTube, SoundCloudʹର Ԡͨ͠ԻָϓϨʔϠ • αʔϏεؒΛލ͍Ͱ࿈ଓ࠶ੜՄೳ •
ԻָϓϨʔϠ։ൃͷࡍʹ࡞ͬͨϥΠϒϥϦɾಘ ͨݟʹ͍ͭͯͷ
None
Apple MusicSpotifyͳͲ ͷΑ͏ͳഭΓ্͕ΔϓϨʔϠ
YouTubeSpotifyͷۂ͕ ࠞࡏ͍ͯͯ͠ ಉ͡࿈ଓ࠶ੜ͕Մೳ ↑ ϝΠϯͷ͓
Agenda • iOSͰԻָΛ࠶ੜ͢Δํ๏ͷհ • ෳαʔϏεʹ·͕ͨͬͯ࠶ੜ͠Α͏ͱ͢Δͱ ग़ͯ͘Δ՝ • ࡞ͬͨϥΠϒϥϦʹ͍ͭͯ
iOSͰԻָΛ࠶ੜ͢Δ • AVFoundation.AVPlayer • MediaPlayer.MPMusicPlayerController • WebView • Spotify iOS
SDK • ϨΠϠͷAPIΛ͏ (ࠓճείʔϓ֎) • CoreAudio, AudioUnit, OpenAL …
AVFoundation.AV(Queue)Player • URLͰԻಈըϑΝΠϧΛࢦఆͯ͠࠶ੜ͢Δ • ಈըͷ߹viewͷlayerʹplayerΛηοτͯ͠ ө૾Λදࣔ • ࢀߟ: ಈըΞϓϦΛͳΊΒ͔ʹಈ͔ٕ͢ज़
MediaPlayer.MPMusicPlayerController • iTunesϥΠϒϥϦ or AppleMusic ͷۂΛ࠶ੜ • applicationMusicPlayer: ΞϓϦʹดͨ͡ϓ ϨʔϠ
• systemMusicPlayer: MusicΞϓϦΛૢ࡞
AppleMusicΛ࠶ੜ͢Δ • ϢʔβͷAppleMusicΞΧϯτͱଓ • AppleMusic APIͬͯۂͷIDΛऔಘ • MPMusicPlayerController#setQueue(with: descriptor) •
MPMusicPlayerController#play()
AppleMusicΞΧϯτଓͷखॱ 1. Info.plist ʹNSAppleMusicUsageDescriptionΛՃ 2. SKCloudServiceController.authorizationStatusͰݱࡏͷঢ়ଶΛ֬ ೝ 3. SKCloudServiceController.requestAuthorizationͰଓཁٻ 4.
SKCloudServiceController#requestCapabilities Ͱ࠶ੜՄೳ͔ΛνΣοΫ 5. SKCloudServiceController#requestStorefrontCountryCodeͰ StorefrontΛऔಘ
Apple Music API • AppleMusicͷใΛऔಘ͢ΔͨΊͷWebAPI • αʔόͰར༻Մೳ • StorefrontΛࢦఆ •
݁Ռͷݴޠ͕มΘΔ • ̎छྨͷtoken • developer token • user token
• Ϣʔβʹඥ͔ͮͳ͍σʔλ • ྫɿۂɾϓϨΠϦετΛݕࡧ • JSON Web Token (JWT) •
࠷6ϲ݄༗ޮͳͷΛੜՄೳ developer token
developer tokenͷੜ • https://developer.apple.com/ -> Certificates, Identifiers & Profiles •
Identities -> Music IDͷ࡞ • Keys -> MusicKit private key ͷ࡞ • JWTͷੜ • elauimagineering/apple-music-token-generator • key idɾteam idɾprivate key • ΫϥΠΞϯτʹprivate keyຒΊࠐ·ͳ͍ํ͕ྑ͍
• ϢʔβσʔλΞΫηεͰ͖Δ • ྫɿۙͷ࠶ੜཤྺɺϓϨΠϦετ࡞ɾۂ ΛՃ • MPMediaLibraryͰϓϨΠϦετ࡞ͳͲՄ ೳ • requestUserToken(forDeveloperToken:completion
Handler:) user token
Apple Music Client • Web APIͳͷͰެࣜͷΫϥΠΞϯτͳ͍ • Apple Music APIͷJSON݁ߏบ͕͋Δ
• Φεεϝɿscottrhoyt/Cider
WebView • UIWebView(WKWebView) Ͱ࠶ੜ • <video playsinline /> + UIWebView#allowsInlineMediaPlayback
• શը໘ʹͳΒͳ͘ͳΔ • iOS10͔ΒsafariͰ
WebView: YouTube࠶ੜ • youtube/youtube-ios-player-helper • ެࣜͷYouTubeͷWebView wrapperϓϨΠϠʔ • YTPlayerView: JavaScriptͳ͠ʹૢ࡞Մೳ
• نͰ͜ΕҎ֎ͷ࠶ੜํ๏ΛೝΊ͍ͯͳ͍ • ඇެࣜͳ࠶ੜํ๏…
Spotify iOS SDK • spotify/ios-sdk • SpotifyͷۂΛ࠶ੜͰ͖Δ • ϓϨϛΞϜΞΧϯτͳΒ࠶ੜͰ͖Δ͕ɺ ҰൠΞΧϯτͩͱࢼௌ͔͠Ͱ͖ͳ͍
• AppleMusicಉ༷
Spotify iOS SDK • Spotify accountͰOAuth ϩάΠϯ • SPTAudioStreamingControllerʹaccess tokenΛ
ηοτ • ࠶ੜ͢ΔTrackͷuriΛWeb APIͳͲͰऔಘ • SPTAudioStreamingController#playSpotifyURI
SpotifyͷOAuthೝূ • oauthೝূʹtoken refresh༻ͷαʔόΛཱͯΔඞཁ͕͋Δ • https://developer.spotify.com/documentation/ios-sdk/guides/ token-swap-and-refresh/ • refresh͠ͳ͍ͱ̍࣌ؒͰࣦޮ •
̎ͭͷྫ • railsͰͷ࣮ྫ • AWS lambda+API GatewayͰͷ࣮ྫ: kumabook/spotify- token-swap-lambda
όοΫάϥϯυ࠶ੜ • Capabilities -> Background Modes -> Audio ,... ʹνΣοΫ
• AVAudioSession#setCategory() • AVAudioSessionCategoryPlayback
ίϯτϩʔϧηϯλʔ • ίϯτϩʔϥ͔ΒͷΠϕϯτ • MPRemoteCommandCenter • playCommand.addTarget • ίϯτϩʔϥͷදࣔ •
MPNowPlayingInfoCenter#nowPlayingInfo
αʔϏεؒΛލ͍ͩϓϨʔϠΛ࣮ ͠Α͏ͱͨ࣌͠ʹग़͖ͯͨ՝
αʔϏεͱϓϨʔϠʔ • SoundCloud • YouTube • Spotify • AppleMusic ←
AVPlayer ← WebView ← spotify/ios-sdk ← MediaPlayer
AVPlayer YouTubePlayer SpotifyPlayer AppleMusicPlayer ̐ͭͷϓϨʔϠΛཧ + ͦΕͧΕPlayer UIͱ࿈ܞ
Πϕϯτͷ௨APIόϥόϥ • εςʔλε௨Πϕϯτ • ݱࡏͷ࠶ੜҐஔͷ௨Πϕϯτ
εςʔλε௨Πϕϯτ AVPlayer NotificationCenter + KVO YTPlayerView YTPlayerViewDelegate MPMusicPlayerController NotificationCenter SPTAudioStreamingController
SPTAudioStreamingPlaybackDelegate
ݱࡏͷ࠶ੜҐஔͷ௨Πϕϯτ AVPlayer AVPlayer#addPeriodicTimeObserver YTPlayerView YTPlayerViewDelegate MPMusicPlayerController ͳ͍ʁ(ࣗલλΠϚʔ) SPTAudioStreamingController SPTAudioStreamingPlaybackDelegate
ঢ়ଶཧ • ࠶ੜഉଞత • ϓϨʔϠΛࢭΊ͔ͯΒ࣍ͷϓϨʔϠΛ࠶ੜ • Ωϡʔͷཧʴ࣌ؒͷཧ • ผͷϓϨʔϠΛ࠶ੜͯͬͨ͠ͱ͖ʹલͷۂ ͕࠶ੜ͞Εͳ͍Α͏ʹঢ়ଶΛΫϦΞ
ϥΠϒϥϦԽ • kumabook/PlayerKit • Example • APIࠩΛٵऩͯ͠γϯϓϧͳIFΛఏڙ • ෦తʹPlayerΛҰ୴protocolͰදݱͯ͠ɺ αʔϏεؒͷΓସ͑Λڞ௨࣮
• Player UI
PlayerKit.QueuePlayer AVPlayer YouTubePlayer SpotifyPlayer AppleMusic Player
QueuePlayer Player AVPlayer YouTubePlayer SpotifyPlayer AppleMusicPlayer QueuePlayerObserver Playlist
Player protocol • ୯ҰͷτϥοΫΛ࠶ੜ͢ΔϓϨʔϠͷϓϩτίϧ • ϝϦοτɿίʔυ͕γϯϓϧʹ • σϝϦοτ: ͦΕͧΕͷϓϨʔϠ͕͍࣋ͬͯΔʮ࣍ͷۂͷϓϦϩʔυػೳʯ ͳͲ͕͑ͳ͘ͳΔ
init load loadTo Play play pause play(_: Track) prepare(_: Track)
[complete loading] [complete loading] pause() play() [end to play] Playerͷঢ়ଶભҠ: PlayerState
Player • var state: PlayerState { get } • func
clearPlayer() : Πϕϯτࢹͷղ์ɺλΠ ϚʔͷΫϦΞ • func preparePlayer(): ΠϕϯτࢹɺλΠϚʔε λʔτɺঢ়ଶΛॳظঢ়ଶ
MPMusicPlayerControllerͷόʔ δϣϯ͝ͱͷڍಈͷࠩҟ • iOS11 ͔Βۂͷ࠶ੜ͕ऴΘͬͯ MPMusicPlayerControllerNowPlayingItemDidChan ge Πϕϯτ͕ඈΜͰ͜ͳ͘ͳͬͨ • →ۂͷऴྃΛײͰ͖ͳ͘ͳͬͨ
• issues/12 • ࣗಈͰ࣍ͷۂʹߦ͔ͳ͘ͳͬͯ͠·ͬͨͷͰସ ҊΛࡧத
QueuePlayer • PlaylistͷதͷTrackΛ֘͢ΔPlayerʹσΟεύον ͍ͯ͘͠ • Track#playerType Ͱผ • Playerͷ෦ͷ࣮ʹґଘ͠ͳ͍ •
ݸʑͷPlayerΛಈతʹՃ͢Δ • queuePlayer.addPlayer(YouTubePlayer())
init load loadTo Play play pause play(_: Track) prepare(_: Track)
[complete loading] [complete loading] pause() play() [end (queue is empty)] QueuePlayerͷঢ়ଶભҠ next() previous() [end]
ࢼௌͱࢹௌ • SpotifyɾAppleMusic༗ྉձһͰͳ͍ͱ֎෦Ξ ϓϦͰ࠶ੜͰ͖ͳ͍ • ࢼௌͷURL • AppleMusic: Song previews[].url
• Spotify: Track preview_url
ࢼௌͱࢹௌΛΓସ͑Δ • ಉ͡TrackͰϢʔβͷঢ়ଶʹΑͬͯ͏Player ͕ಈతʹม͑Δඞཁ͕͋Δ • Ϣʔβͷঢ়ଶཧΞϓϦͷ • Track#playerTypeͷฦ͢Λಈతʹ
public var playerType: PlayerType { If SpotifyAPIClient.isPremiumUser { return .spotify
} return .avPlayer }
• AppleMusicSpotifyͷΑ͏ͳഭΓ্͕ΔϓϨʔ Ϡʔ • ࢀߟ: 8/31ͷηογϣϯ MusicΞϓϦͷ TransitionΛ࠶ݱ͢Δ • ࡉ੍͔͍ޚ͕͔ͨͬͨͨ͠Ί
UIPresentationControllerΘͣࣗલͰ࣮ Player UIͷ࣮
YTPlayerViewͷΓସ͑ τϥϯδγϣϯ͕ऴΘͬͨ࣌ʹ YTPlayerViewΛҠಈͤͯ͞ϦαΠζ
·ͱΊ • iOSͰԻָΛ࠶ੜ͢Δํ๏ͷհ • ෳͷϓϨʔϠʔΛΈ߹Θͤ͏ͨΊͷϥΠϒϥ ϦΛ࡞ • ΠϯλϑΣʔεͱঢ়ଶભҠΛఆ͓͔ٛͨ͛͠Ͱϓ ϨʔϠಉ࢜ΛΓସ͑Δ෦ڞ௨ԽͰ͖ͨ •
MPMusicPlayerControllerͷΠϕϯτAPIपΓʹ՝ ͋Γ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
ࢀߟϦϯΫ • AVFoundation.AVQueuePlayer • MediaPlayer.MPMusicPlayerController • youtube/youtube-ios-player-helper • spotify/ios-sdk
ࢀߟϦϯΫ • Introducing MusicKit