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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Hiroki Kumamoto
September 02, 2018
690
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
130
Promiseを実装してみよう
kumabook
0
370
bff_tips.pdf
kumabook
0
100
Tips of server-side rendering with react + redux
kumabook
0
110
emacs helm likeな WebExtensions を作った話
kumabook
0
180
merges sort
kumabook
0
92
lightweight introducing with reactive cocoa
kumabook
0
75
basic_sort
kumabook
0
80
git_peco_tips
kumabook
0
41
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
310
GraphQLとの向き合い方2022年版
quramy
50
15k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
400
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
57k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
WENDY [Excerpt]
tessaabrams
12
39k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
380
Game over? The fight for quality and originality in the time of robots
wayneb77
1
260
The browser strikes back
jonoalderson
0
1.6k
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