この記事は ZOZOテクノロジーズ #1 Advent Calendar 2019 8日目の記事になります。
昨日の記事は @calorie さんによる「Firebaseを使ったTwitter認証をクライアント(Swift)からサーバ(Rails)までまるっと実装する」でした。Firebase を使った認証をクライアントからサーバーまで通して解説してあり、初心者でも非常に分かりやすいと思いますので、ぜひご覧ください。
#はじめに
アプリで何かの動画を再生させよう!という話になった時、こんな質問を受けます。
デザイナー:「シークバーって表示できる?」
私:「システム標準のやつならすぐできますよ」
デザイナー:「標準のやつってどんなの?」
私:「えーと・・・」
と言いながら、毎回スクリーンショットを探しても、最新のものがなかなか見つかりません。結局サンプルを作って、スクリーンショットを撮ったりしています。
そこで、この記事では、Xcode11 での動画の再生方法をまとめながら、Playback Controls のスクリーンショットを見ていきたいと思います。
確認環境は、Xcode 11.2.1 の iPhone 11 Pro 13.2.2 のシュミレーターを使います。
#動画の再生
動画再生用の UI(以降は便宜上、Playback Controls と呼びます)の話の前に、まず動画の再生方法について説明します。サードパーティのライブラリなどを使用せず実装する方法としては、次の3つがあります(2019年12月現在)。
- AVPlayer を使う
- AVPlayerViewController を使う
- WKWebView で video タグを使う
Playback Controls が提供されているのは、2と3になりますが、1はもっともシンプルな動画再生や、フルカスタムで Playback Controls を自作する際の基礎となるので、ここから説明します。
AVPlayer を使う
AVFoundation の AVPlayer を使って動画を再生します。
最小実装としては、こんな感じになると思います。
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else {
return
}
let player = AVPlayer(url: url)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
}
1つ1つ丁寧に説明すると、まず最初に動画の URL を作成します。
guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else {
return
}
この URL は Apple の「Creating a Basic Video Player」で指定している HTTP Live Streaming (HLS) のインデックスファイルになります。これはサーバーやローカルの MP4 ファイルにしても動作します。
次にこの URL をもとに AVPlayer を作成します。
let player = AVPlayer(url: url)
そして、そこから実際に動画を再生させるレイヤーを作成し、サイズを調整して、View ツリーに追加します。
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
そして、最後に AVPlayer の play メソッドを呼ぶだけです。
player.play()
非常に簡単ですね!
実行結果のスクリーンショットがこちらになります。
サンプル動画のせいでちょっと分かりにくいかもしれませんが、Playback Controls は一切表示されておらず、動画のみのシンプルな UI になります。
AVPlayerViewController を使う
次にいよいよ Playback Controls が表示できる AVKit の AVPlayerViewController を使います。
最小実装としては、こんな感じになると思います。
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else {
return
}
let player = AVPlayer(url: url)
let controller = AVPlayerViewController()
controller.player = player
controller.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 300)
self.addChild(controller)
self.view.addSubview(controller.view)
player.play()
}
AVPlayer との違いは、AVPlayerViewController を作成し、作成した AVPlayer をセットするところです。
let controller = AVPlayerViewController()
controller.player = player
全画面表示にならないように、高さを調整し、ViewController と View ツリーに追加します。
controller.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 300)
self.addChild(controller)
self.view.addSubview(controller.view)
実行結果のスクリーンショットがこちらになります。
左が最初に表示されて、タップするとこのように Playback Controls が表示されます。左上にある最大化ボタンを押すと右の画面になり、Playback Controls がより大きくなり UI が変わります。
WKWebView で video タグを使う
これは、おまけになりますが、WKWebView と video タグでも動画の再生と Playback Controls の表示ができます。コードはこんな感じになります。
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8") else {
return
}
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: self.view.bounds, configuration: config)
self.view.addSubview(webView)
let html = String(format:"<video id='video' width='950' height='700' src='%@' controls autoplay playsinline webkit-playsinline></video>", url.absoluteString)
webView.loadHTMLString(html, baseURL: nil)
}
video タグはくせがあるようですが、調べきっていないので、ここでの説明は割愛させていただきます。
実行するとこのようになります。
右の最大化した時の Playback Controls は AVPlayerViewController と同じですが、左の Playback Controls は注意深く見ると少し違います。字幕の設定オプションが無く、その代わりに 15 秒の巻き戻しと早く送りがあります。 |
まとめ
Xcode11 での動画の再生方法をまとめながら、Playback Controls を確認しました。動画再生の UI について検討するときにこの記事が少しでも役に立てば幸いです。
明日は、@sesta さんが公開予定です。そちらもぜひご覧下さい。