SwiftUI でYoutube動画プレイヤーを作ってみる
はじめに
SwiftUIでアプリを作っていても、どうしてもUIKitの資産を使いたい場面が出てくる事が多いですよね。UIKitむけの豊富なライブラリたちを使いたい場合などもたくさんあると思います。
今回はまさに、UIKitむけのYoutubeプレイヤーライブラリである YoutubeKit をSwiftUIのアプリに組み込んでみたいと思います。
とりあえずの完成形
今回はこんな感じのものを作ってみたいと思います。
GitHubはこちらです github.com
開発環境
参考書
SwiftUIの勉強には、この辺りの本が特におすすめです!
YoutubeKitを取り込む
今回はcocoapods
を使って、YoutubeKitを組み込んでいます。Swift Package Manager
を使いたかったのですが、なぜかビルドが通りませんでした...
pod 'YoutubeKit'
UIViewRepresentable
UIViewRepresentable
を使う事で、UIKitベースのViewをSwiftUIで利用可能なViewにラッピングできます。
今回は、YoutubeKitに含まれるYTSwiftyPlayer
を、SwiftUIで利用可能なPlayerView
としてラップします。
import SwiftUI import YoutubeKit struct PlayerView: UIViewRepresentable { typealias UIViewType = YTSwiftyPlayer // 初期化処理を記述. func makeUIView(context: Context) -> YTSwiftyPlayer { // 初期化処理・初期設定. let player = YTSwiftyPlayer() player.autoplay = true return player } // 更新処理を記述. func updateUIView(_ uiView: YTSwiftyPlayer, context: Context) { // 再生する動画の設定. uiView.setPlayerParameters([ .playsInline(true), .videoID("TST0CURe3wM"), ]) uiView.loadPlayer() } }
makeUIView
には、対象のUIViewを生成・初期化するための処理を記述します。今回はYTSwiftyPlayer
のインスタンスの生成を行っています。
updateUIView
には、PlayerViewが更新されるたびに呼び出される処理を記述します。今回は、再生する動画の設定と読み込み処理を行っています。事前に自動再生を有効にしているので、読み込みが終わり次第再生が開始されます。
ContentView
でこのPlayerView
を読み込んで動きを確認してみます。
struct ContentView: View { var body: some View { PlayerView() } }
出来上がりはこんな感じです。画面いっぱいにPlayerView
が広がって、固定で動画が再生されていますね。
プレイヤーの大きさを調整
このままだとプレイヤーの見た目が残念なので、ContentView
に色々と処理を追加し、PlayerView
のサイズを調整してみます。
プレイヤーの幅はデバイス幅に合わせ、高さは16:9になるように算出します。
@State private var playerSize: CGSize = .zero var body: some View { VStack { PlayerView() .frame( // 算出された値でサイズ指定. width: playerSize.width, height: playerSize.height ) } // onAppearでサイズの計算を行う. .onAppear { // windowサイズからplayerサイズを算出. let frame = UIApplication.shared.windows.first?.frame ?? .zero // 縦横比が16:9になるように高さを調整. playerSize = CGSize( width: frame.width, height: frame.width / 16 * 9 ) } }
それらしくなりましたね。
動画の切り替え機能を追加する
今は再生する動画が固定になっていますが、これを切り替えるための機能を追加します。
まずは切り替え対象となる動画の種類をenumVideo
として定義します。
enum Video: String, CaseIterable { case violin case guitar case amaiyume var videoId: String { switch self { case .violin: return "TST0CURe3wM" case .guitar: return "QW2TfV20FXY" case .amaiyume: return "Y-ou8d-wMoI" } } }
ContentView
には、選択された動画を保持する変数と動画切り替えのUIを追加します。
// 選択された動画を保持する変数を追加 @State private var selected: Video = .violin var body: some View { VStack { // ~省略~ // 動画切り替えのUIを追加. Picker("動画選択", selection: $selected) { ForEach(Video.allCases, id: \.self) { video in Text(video.rawValue.uppercased()) } } // picker style 色々. // .pickerStyle(InlinePickerStyle()) .pickerStyle(SegmentedPickerStyle()) // .pickerStyle(MenuPickerStyle()) } .onAppear { // ~省略~ } }
今回はPicker
をSegmentedPickerStyle()
で表示しましたが、iOS14からstyleが追加されているので、それらを試してみるのも面白いかもしれません。
- InlinePickerStyle()
- MenuPickerStyle()
選択された動画を再生する
切り替えのUIは作ったので、実際に動画を切り替える処理を追加します。
PlayerView
には、選択された動画のVideo
を@Binding
の変数として定義し、その値を利用して動画を再生するように修正します。
// 選択されたVideoを受け取る@Binding変数を追加. @Binding var video: Video // ~省略~ func updateUIView(_ uiView: YTSwiftyPlayer, context: Context) { // 再生する動画の設定. uiView.setPlayerParameters([ .playsInline(true), .videoID(video.videoId), // 選択された値のvideoIdを利用する. ]) uiView.loadPlayer() }
ContentView
では、PlayerView
に選択されたVideo
をbindingで渡します。
// コンストラクタに値を追加. PlayerView(video: $selected) .frame( width: playerSize.width, height: playerSize.height )
これで完成です!出来上がりはこんな感じです!
Youtube Data API
YoutubeKitには、他にもYoutube Data API を使うための機能など、他にもさまざまな機能が実装されています。今回は解説しませんが、これらと組み合わせる事でこんな感じのアプリも作れます!
また、今回はシミュレータを利用していますが、実機を利用すれば「ピクチャインピクチャ」を利用することもできるので、ぜひ試してみてください。
まとめ
UIViewRepresentable
を利用することで、UIKitの資産を使ったSwiftUIアプリを作る事ができます。先人たちによって作られた様々なライブラリやツールを使って、SwiftUIのアプリを作っていきましょう!
おまけ
今回使ったYoutube動画はこちらです。