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動画はこちらです。
