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
2
590
プロトコルを使って複数サービスを跨いだmusic playerを実装する
Hiroki Kumamoto
September 02, 2018
Tweet
Share
More Decks by Hiroki Kumamoto
See All by Hiroki Kumamoto
How to implement timetable view on iOS
kumabook
0
100
Promiseを実装してみよう
kumabook
0
320
bff_tips.pdf
kumabook
0
81
Tips of server-side rendering with react + redux
kumabook
0
79
emacs helm likeな WebExtensions を作った話
kumabook
0
160
merges sort
kumabook
0
79
lightweight introducing with reactive cocoa
kumabook
0
55
basic_sort
kumabook
0
72
git_peco_tips
kumabook
0
30
Featured
See All Featured
Making the Leap to Tech Lead
cromwellryan
135
9.5k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Done Done
chrislema
185
16k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Why Our Code Smells
bkeepers
PRO
339
57k
Building Applications with DynamoDB
mza
96
6.6k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Mobile First: as difficult as doing things right
swwweet
224
9.9k
Code Review Best Practice
trishagee
71
19k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3k
Writing Fast Ruby
sferik
628
62k
GitHub's CSS Performance
jonrohan
1032
460k
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