Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プロトコルを使って複数サービスを跨いだmusic playerを実装する

Hiroki Kumamoto
September 02, 2018
410

プロトコルを使って複数サービスを跨いだmusic playerを実装する

Hiroki Kumamoto

September 02, 2018
Tweet

Transcript

  1. ϓϩτίϧΛ࢖ͬͯෳ਺αʔ
    ϏεΛލ͍ͩmusic playerΛ
    ࣮૷͢Δ
    iOSDC 2018/09/02
    Hiroki Kumamoto a.k.a kumabook

    View full-size slide

  2. ࣗݾ঺հ
    • Hiroki Kumamoto
    • a.k.a kumabook (twitter, github)
    • Software engineer at Spincoaster,
    Inc.
    • swift, JavaScript, ruby, rust ...

    View full-size slide

  3. ϦΞϧ ͳ
    Իָγʔϯͱ
    ग़ ѭ͏
    M U S I C C H A R T
    T OP 10 0

    View full-size slide

  4. TYPICA
    • ԻָϙʔλϧΞϓϦ
    • @TYPICA_JP
    • Web: typica.mu
    • iOSΞϓϦ
    • ʰϦΞϧͳԻָγʔϯͷՄࢹԽʱΛ໨ࢦͨ͠ԻָαʔϏε
    • Web্ͷԻָ৘ใΛΫϩʔϧͯ͠Ϩίϝϯυ
    • Իָʹؔ͢Δهࣄ΍ԻָαʔϏεͷۂɺΞϧόϜɺϓϨΠϦετ
    • TYPICA Top 100 (https://typica.mu/ja/chart/top100)
    • ಠࣗͷϥϯΩϯάγεςϜ

    View full-size slide

  5. ΞϓϦ಺ϓϨʔϠ
    • AppleMusic, Spotify, YouTube, SoundCloudʹର
    Ԡͨ͠ԻָϓϨʔϠ
    • αʔϏεؒΛލ͍Ͱ࿈ଓ࠶ੜՄೳ
    • ԻָϓϨʔϠ։ൃͷࡍʹ࡞ͬͨϥΠϒϥϦɾಘ
    ͨ஌ݟʹ͍ͭͯͷ࿩

    View full-size slide

  6. Apple Music΍SpotifyͳͲ

    ͷΑ͏ͳഭΓ্͕ΔϓϨʔϠ

    View full-size slide

  7. YouTube΍Spotifyͷۂ͕

    ࠞࡏ͍ͯͯ͠΋

    ಉ͡࿈ଓ࠶ੜ͕Մೳ
    ↑


    ϝΠϯͷ͓࿩

    View full-size slide

  8. Agenda
    • iOSͰԻָΛ࠶ੜ͢Δํ๏ͷ঺հ
    • ෳ਺αʔϏεʹ·͕ͨͬͯ࠶ੜ͠Α͏ͱ͢Δͱ
    ग़ͯ͘Δ՝୊
    • ࡞ͬͨϥΠϒϥϦʹ͍ͭͯ

    View full-size slide

  9. iOSͰԻָΛ࠶ੜ͢Δ
    • AVFoundation.AVPlayer
    • MediaPlayer.MPMusicPlayerController
    • WebView
    • Spotify iOS SDK
    • ௿ϨΠϠͷAPIΛ࢖͏ (ࠓճ͸είʔϓ֎)
    • CoreAudio, AudioUnit, OpenAL …

    View full-size slide

  10. AVFoundation.AV(Queue)Player
    • URLͰԻ੠΍ಈըϑΝΠϧΛࢦఆͯ͠࠶ੜ͢Δ
    • ಈըͷ৔߹͸viewͷlayerʹplayerΛηοτͯ͠
    ө૾Λදࣔ
    • ࢀߟ: ಈըΞϓϦΛͳΊΒ͔ʹಈ͔ٕ͢ज़

    View full-size slide

  11. MediaPlayer.MPMusicPlayerController
    • iTunesϥΠϒϥϦ or AppleMusic ͷۂΛ࠶ੜ
    • applicationMusicPlayer: ΞϓϦ಺ʹดͨ͡ϓ
    ϨʔϠ
    • systemMusicPlayer: MusicΞϓϦΛૢ࡞

    View full-size slide

  12. AppleMusicΛ࠶ੜ͢Δ
    • ϢʔβͷAppleMusicΞΧ΢ϯτͱ઀ଓ
    • AppleMusic API࢖ͬͯۂͷIDΛऔಘ
    • MPMusicPlayerController#setQueue(with:
    descriptor)
    • MPMusicPlayerController#play()

    View full-size slide

  13. AppleMusicΞΧ΢ϯτ઀ଓͷखॱ
    1. Info.plist ʹNSAppleMusicUsageDescriptionΛ௥Ճ
    2. SKCloudServiceController.authorizationStatusͰݱࡏͷঢ়ଶΛ֬

    3. SKCloudServiceController.requestAuthorizationͰ઀ଓཁٻ
    4. SKCloudServiceController#requestCapabilities

    Ͱ࠶ੜՄೳ͔ΛνΣοΫ
    5. SKCloudServiceController#requestStorefrontCountryCodeͰ
    StorefrontΛऔಘ

    View full-size slide

  14. Apple Music API
    • AppleMusicͷ৘ใΛऔಘ͢ΔͨΊͷWebAPI
    • αʔόͰ΋ར༻Մೳ
    • StorefrontΛࢦఆ
    • ݁Ռͷݴޠ͕มΘΔ
    • ̎छྨͷtoken
    • developer token
    • user token

    View full-size slide

  15. • Ϣʔβʹඥ͔ͮͳ͍σʔλ
    • ྫɿۂɾϓϨΠϦετΛݕࡧ
    • JSON Web Token (JWT)
    • ࠷௕6ϲ݄༗ޮͳ΋ͷΛੜ੒Մೳ
    developer token

    View full-size slide

  16. 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͸ຒΊࠐ·ͳ͍ํ͕ྑ͍

    View full-size slide

  17. • Ϣʔβσʔλ΁ΞΫηεͰ͖Δ
    • ྫɿ௚ۙͷ࠶ੜཤྺɺϓϨΠϦετ࡞੒ɾۂ
    Λ௥Ճ
    • MPMediaLibraryͰ΋ϓϨΠϦετ࡞੒ͳͲ͸Մ

    • requestUserToken(forDeveloperToken:completion
    Handler:)
    user token

    View full-size slide

  18. Apple Music Client
    • Web APIͳͷͰެࣜͷΫϥΠΞϯτ͸ͳ͍
    • Apple Music APIͷJSON͸݁ߏบ͕͋Δ
    • Φεεϝɿscottrhoyt/Cider

    View full-size slide

  19. WebView
    • UIWebView(WKWebView) ಺Ͱ࠶ੜ
    • +
    UIWebView#allowsInlineMediaPlayback
    • શը໘ʹͳΒͳ͘ͳΔ
    • iOS10͔ΒsafariͰ΋

    View full-size slide

  20. WebView: YouTube࠶ੜ
    • youtube/youtube-ios-player-helper
    • ެࣜͷYouTubeͷWebView wrapperϓϨΠϠʔ
    • YTPlayerView: JavaScriptͳ͠ʹૢ࡞Մೳ
    • ن໿Ͱ͜ΕҎ֎ͷ࠶ੜํ๏ΛೝΊ͍ͯͳ͍
    • ඇެࣜͳ࠶ੜํ๏͸…

    View full-size slide

  21. Spotify iOS SDK
    • spotify/ios-sdk
    • SpotifyͷۂΛ࠶ੜͰ͖Δ
    • ϓϨϛΞϜΞΧ΢ϯτͳΒ͹࠶ੜͰ͖Δ͕ɺ
    ҰൠΞΧ΢ϯτͩͱࢼௌ͔͠Ͱ͖ͳ͍
    • AppleMusic΋ಉ༷

    View full-size slide

  22. Spotify iOS SDK
    • Spotify accountͰOAuth ϩάΠϯ
    • SPTAudioStreamingControllerʹaccess tokenΛ
    ηοτ
    • ࠶ੜ͢ΔTrackͷuriΛWeb APIͳͲͰऔಘ
    • SPTAudioStreamingController#playSpotifyURI

    View full-size slide

  23. 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

    View full-size slide

  24. όοΫάϥϯυ࠶ੜ
    • Capabilities -> Background Modes -> Audio ,...
    ʹνΣοΫ
    • AVAudioSession#setCategory()
    • AVAudioSessionCategoryPlayback

    View full-size slide

  25. ίϯτϩʔϧηϯλʔ
    • ίϯτϩʔϥ͔ΒͷΠϕϯτ
    • MPRemoteCommandCenter
    • playCommand.addTarget
    • ίϯτϩʔϥ΁ͷදࣔ
    • MPNowPlayingInfoCenter#nowPlayingInfo

    View full-size slide

  26. αʔϏεؒΛލ͍ͩϓϨʔϠΛ࣮
    ૷͠Α͏ͱͨ࣌͠ʹग़͖ͯͨ՝୊

    View full-size slide

  27. αʔϏεͱϓϨʔϠʔ
    • SoundCloud
    • YouTube
    • Spotify
    • AppleMusic
    ← AVPlayer
    ← WebView
    ← spotify/ios-sdk
    ← MediaPlayer

    View full-size slide

  28. AVPlayer YouTubePlayer SpotifyPlayer AppleMusicPlayer
    ̐ͭͷϓϨʔϠΛ؅ཧ

    +
    ͦΕͧΕPlayer UIͱ࿈ܞ

    View full-size slide

  29. Πϕϯτͷ௨஌APIόϥόϥ
    • εςʔλε௨஌Πϕϯτ
    • ݱࡏͷ࠶ੜҐஔͷ௨஌Πϕϯτ

    View full-size slide

  30. εςʔλε௨஌Πϕϯτ
    AVPlayer
    NotificationCenter

    +

    KVO
    YTPlayerView YTPlayerViewDelegate
    MPMusicPlayerController NotificationCenter
    SPTAudioStreamingController SPTAudioStreamingPlaybackDelegate

    View full-size slide

  31. ݱࡏͷ࠶ੜҐஔͷ௨஌Πϕϯτ
    AVPlayer AVPlayer#addPeriodicTimeObserver
    YTPlayerView YTPlayerViewDelegate
    MPMusicPlayerController ͳ͍ʁ(ࣗલλΠϚʔ)
    SPTAudioStreamingController SPTAudioStreamingPlaybackDelegate

    View full-size slide

  32. ঢ়ଶ؅ཧ
    • ࠶ੜ͸ഉଞత
    • ϓϨʔϠΛࢭΊ͔ͯΒ࣍ͷϓϨʔϠΛ࠶ੜ
    • Ωϡʔͷ؅ཧʴ࣌ؒͷ؅ཧ
    • ผͷϓϨʔϠΛ࠶ੜͯ͠໭ͬͨͱ͖ʹલͷۂ
    ͕࠶ੜ͞Εͳ͍Α͏ʹঢ়ଶΛΫϦΞ

    View full-size slide

  33. ϥΠϒϥϦԽ
    • kumabook/PlayerKit
    • Example
    • APIࠩ෼Λٵऩͯ͠γϯϓϧͳIFΛఏڙ
    • ಺෦తʹ͸PlayerΛҰ୴protocolͰදݱͯ͠ɺ
    αʔϏεؒͷ੾Γସ͑Λڞ௨࣮૷
    • Player UI

    View full-size slide

  34. PlayerKit.QueuePlayer
    AVPlayer YouTubePlayer SpotifyPlayer
    AppleMusic
    Player

    View full-size slide

  35. QueuePlayer
    Player
    AVPlayer YouTubePlayer SpotifyPlayer AppleMusicPlayer
    QueuePlayerObserver
    Playlist

    View full-size slide

  36. Player protocol
    • ୯ҰͷτϥοΫΛ࠶ੜ͢ΔϓϨʔϠͷϓϩτίϧ
    • ϝϦοτɿίʔυ͕γϯϓϧʹ
    • σϝϦοτ: ͦΕͧΕͷϓϨʔϠ͕͍࣋ͬͯΔʮ࣍ͷۂͷϓϦϩʔυػೳʯ
    ͳͲ͕࢖͑ͳ͘ͳΔ

    View full-size slide

  37. init
    load
    loadTo
    Play
    play
    pause
    play(_: Track)
    prepare(_: Track)
    [complete loading]
    [complete loading]
    pause() play()
    [end to play]
    Playerͷঢ়ଶભҠ: PlayerState

    View full-size slide

  38. Player
    • var state: PlayerState { get }
    • func clearPlayer() : Πϕϯτ؂ࢹͷղ์ɺλΠ
    ϚʔͷΫϦΞ
    • func preparePlayer(): Πϕϯτ؂ࢹɺλΠϚʔε
    λʔτɺঢ়ଶΛॳظঢ়ଶ΁

    View full-size slide

  39. MPMusicPlayerControllerͷόʔ
    δϣϯ͝ͱͷڍಈͷࠩҟ
    • iOS11 ͔Βۂͷ࠶ੜ͕ऴΘͬͯ΋
    MPMusicPlayerControllerNowPlayingItemDidChan
    ge Πϕϯτ͕ඈΜͰ͜ͳ͘ͳͬͨ
    • →ۂͷऴྃΛײ஌Ͱ͖ͳ͘ͳͬͨ
    • issues/12
    • ࣗಈͰ࣍ͷۂʹߦ͔ͳ͘ͳͬͯ͠·ͬͨͷͰ୅ସ
    ҊΛ໛ࡧத

    View full-size slide

  40. QueuePlayer
    • PlaylistͷதͷTrackΛ֘౰͢ΔPlayerʹσΟεύον
    ͍ͯ͘͠
    • Track#playerType Ͱ൑ผ
    • Playerͷ಺෦ͷ࣮૷ʹ͸ґଘ͠ͳ͍
    • ݸʑͷPlayerΛಈతʹ௥Ճ͢Δ
    • queuePlayer.addPlayer(YouTubePlayer())

    View full-size slide

  41. init
    load
    loadTo
    Play
    play
    pause
    play(_: Track)
    prepare(_: Track)
    [complete loading]
    [complete loading]
    pause()
    play()
    [end (queue is empty)]
    QueuePlayerͷঢ়ଶભҠ
    next() 

    previous()

    [end]

    View full-size slide

  42. ࢼௌͱࢹௌ
    • SpotifyɾAppleMusic͸༗ྉձһͰͳ͍ͱ֎෦Ξ
    ϓϦͰ࠶ੜ͸Ͱ͖ͳ͍
    • ࢼௌͷURL
    • AppleMusic: Song previews[].url
    • Spotify: Track preview_url

    View full-size slide

  43. ࢼௌͱࢹௌΛ੾Γସ͑Δ
    • ಉ͡TrackͰ΋Ϣʔβͷঢ়ଶʹΑͬͯ࢖͏Player
    ͕ಈతʹม͑Δඞཁ͕͋Δ
    • Ϣʔβͷঢ়ଶ؅ཧ͸ΞϓϦͷ੹຿
    • Track#playerTypeͷฦ͢஋Λಈతʹ

    View full-size slide

  44. public var playerType: PlayerType {
    If SpotifyAPIClient.isPremiumUser {
    return .spotify
    }
    return .avPlayer
    }

    View full-size slide

  45. • AppleMusic΍SpotifyͷΑ͏ͳഭΓ্͕ΔϓϨʔ
    Ϡʔ
    • ࢀߟ: 8/31ͷηογϣϯ MusicΞϓϦͷ
    TransitionΛ࠶ݱ͢Δ
    • ࡉ੍͔͍ޚ͕͔ͨͬͨͨ͠Ί
    UIPresentationController͸࢖ΘͣࣗલͰ࣮૷
    Player UIͷ࣮૷

    View full-size slide

  46. YTPlayerViewͷ੾Γସ͑
    τϥϯδγϣϯ͕ऴΘͬͨ࣌ʹ

    YTPlayerViewΛҠಈͤͯ͞ϦαΠζ

    View full-size slide

  47. ·ͱΊ
    • iOSͰԻָΛ࠶ੜ͢Δํ๏ͷ঺հ
    • ෳ਺ͷϓϨʔϠʔΛ૊Έ߹Θͤ࢖͏ͨΊͷϥΠϒϥ
    ϦΛ࡞੒
    • ΠϯλϑΣʔεͱঢ়ଶભҠΛఆ͓͔ٛͨ͛͠Ͱϓ
    ϨʔϠಉ࢜Λ੾Γସ͑Δ෦෼͸ڞ௨ԽͰ͖ͨ
    • MPMusicPlayerControllerͷΠϕϯτAPIपΓʹ՝
    ୊͋Γ

    View full-size slide

  48. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View full-size slide

  49. ࢀߟϦϯΫ
    • AVFoundation.AVQueuePlayer
    • MediaPlayer.MPMusicPlayerController
    • youtube/youtube-ios-player-helper
    • spotify/ios-sdk

    View full-size slide

  50. ࢀߟϦϯΫ
    • Introducing MusicKit

    View full-size slide