ちょっと話題の記事

[iOS] iOSで動画を再生する4つの方法

2016.06.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

iOSで動画を扱う場合、以下の4つの方法があります。

種類 プレーヤー 操作コントロール 対応OS 実装コスト
(a) UIWebView MPMoviePlayer/AVPlayer あり
(b) MPMoviePlayerController
MPMoviePlayerViewController
MPMoviePlayer あり iOS2以降(iOS9でdeprecated)
(c) AVPlayerViewController AVPlayer あり iOS8以降
(d) AVPlayer AVPlayer なし iOS4以降

上の表は、実装コストの小さいものから順に並べましたが、実装の自由度は、これに反比例し、操作コントロールまで全部を自前で実装する(d)が、最も自由に書くことができます。 また、(b)と(c)の使い分けは、対応OSによるという使い分けになるでしょう。

以下、それぞれについて動作を確認してみたいと思います。

なお、サンプル作成にあたり表示に使用した動画は、前回「HTTP Live Streaming」で配置したものを使用しております。
参考:HTTP Live Streamingで動画を配信してみる

2 UIWebView

iOSで動画を再生する最も簡単な方法は、UIWebViewを利用する方法です。

StoryboardでUiWebViewを配置して、下記のようなコードを記述するだけで利用できます。

003

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *videoUrl = @"http://hls-sample.s3-website-ap-northeast-1.amazonaws.com/index.m3u8";
    NSString *htmlString = [NSString stringWithFormat:@"<video id='video' width='300' height='200' src='%@' controls autoplay></video>",videoUrl];
    [_webView loadHTMLString:htmlString baseURL:nil];
}

004

コードの中で、<video>タグを使用して、動画を配置していますが、動画を操作するボタンなども自動的に使用できるようになっています。これで、動画再生の作業は終わっているとも言えます。

002 001

ただし、再生が開始するとデフォルトで全画面表示となってしまうことや、アプリからキメ細い再生指示などはできません。ある意味、UIWebViewに丸投げする感じでしょうか。

全画面表示したくない場合などは、少し工夫が必要です。
参考:[iOS]UIWebViewのVideoタグハンドリング iOS

また、iOS9以降では、ATSが有効になりますので、https以外のコンテンツを表示するには、info.plistに設定が必要です。
参考:[iOS 9] iOS 9 で追加された App Transport Security の概要

3 MPMoviePlayerController・MPMoviePlayerViewController

次は、MPMoviePlayerControllerを使用する方法です。 こちらは、iOS2以降で利用することが可能ですが、iOS9でdeprecatedになっていることから、古いバージョンへの対応が必要な場合以外は、今後、積極的に利用されることはないでしょう。

MediaPlayer.frameworkをリンクして、MediaPlayer/MediaPlayer.hをimportすることで利用可能です。

005

コードは、次のようになります。

#import "ViewController.h"
#import <MediaPlayer/MediaPlayer.h>

@interface ViewController ()

@property (nonatomic,strong) MPMoviePlayerController *player;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:@"https://s3-ap-northeast-1.amazonaws.com/hls-sample/index.m3u8"];
    self.player = [[MPMoviePlayerController alloc] initWithContentURL:url];
    self.player.controlStyle             = MPMovieControlStyleDefault;
    self.player.scalingMode              = MPMovieScalingModeAspectFit;
    self.player.shouldAutoplay           = NO;
    self.player.view.autoresizingMask    = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.player.view.autoresizesSubviews = YES;
    self.player.view.frame = CGRectMake(0, 0, self.view.bounds.size.width,300);
    [self.player prepareToPlay];
    [self.view addSubview:self.player.view];
}

@end

よく見比べてみると、操作ボタンは、UIWebViewとは、やや違うことがわかります。

006

画面の最大化は、ボタンが用意されており、勝手に最大化されるようなことはありません。

008 007

当然ですが、UIWebViewに比較すると、きめ細かく再生等を制御できます。
Media Player Framework Reference MPMoviePlayerController Class Reference

また、MPMoviePlayerを使用する方法としては、ViewControllerも含めたMPMoviePlayerViewControllerもあります。
Media Player Framework Reference MPMoviePlayerViewController Class Reference

4 AVPlayerViewController

iOS8以降で利用可能な動画コントローラーで、上記のMPMoviePlayerControllerの後継です。 利用方法もMPMoviePlayerControllerとほとんど同じですが、内部で利用されているプレイヤーは、AvPlayerに変わっています。

特にライブラリをリンクする必要はなく、AVFoundationAVKitをimportするだけで利用可能です。

#import "ViewController.h"
@import AVFoundation;
@import AVKit;

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:@"https://s3-ap-northeast-1.amazonaws.com/hls-sample/index.m3u8"];

    AVPlayer *avPlayer = [AVPlayer playerWithURL:url];
    AVPlayerViewController *controller = [[AVPlayerViewController alloc]init];
    controller.player = avPlayer;
    controller.view.frame = CGRectMake(0, 0, self.view.bounds.size.width,300);
    [self addChildViewController:controller]; // 最大画面になった時、これが使用される感じ
    [self.view addSubview:controller.view];
    [avPlayer play]; //再生
}

@end

実行時の様子です。

009

全画面は次の通り。

010 011 MPMoviePlayerControllerと比べて、少し、ボタンの位置などに違いがありますが、見た目上の差異はほとんどありません。

5 AVPlayer

上記までの利用方法と一線を画して、AVPlayerを、純粋にプレイヤーとしてだけ使用し、ビューや操作コントロールは、全部自前で実装します。 画面の最大化なども、ビュー自体を自前で準備していることから、大きさなどは自由に設計できます。

実装については、以下の手順になります。

(1) ビューの準備

最初にプレイヤーをセットするためのビューを準備します。

UIViewを継承したクラスを作成し、AVPlayerLayerクラスとして振る舞えるようにします。

AVPlayerView.h

#import <UIKit/UIKit.h>
@import AVFoundation;
@interface AVPlayerView : UIView
@end

AVPlayerView.m

#import "AVPlayerView.h"
@implementation AVPlayerView
+(Class)layerClass
{
    return [AVPlayerLayer class];
}
@end

(2) ビューとAVPlayerの生成

まずは、準備した上記のビュー(②)を生成し、AVPlayer(①)をlayoutプロパティにセットします(③)。そして、親ビューに追加します(④)。

ビュー(⑤)及びAVPlayer(⑥)は、今後の操作に必要なため、プロパティとして保持しています。

ViewController.m

@interface ViewController ()

@property (nonatomic,strong) AVPlayerView *playerView; // (⑤)自前で準備したビュー
@property (nonatomic, strong) AVPlayer *player; // (⑥)AVPlayer

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:@"https://s3-ap-northeast-1.amazonaws.com/hls-sample/index.m3u8"];
    _player = [[AVPlayer alloc]initWithURL:url];  // (①) AVPlayerの生成
    _playerView = [[AVPlayerView alloc]initWithFrame:CGRectMake(0,
                                                               20,
                                                               self.view.frame.size.width,
                                                               300)]; // (②) ビューのの生成
    [(AVPlayerLayer*)_playerView.layer setPlayer:_player]; // (③)AVPlayerをセット
    [self.view addSubview:_playerView]; // (④) ビューを追加
    [self.view bringSubviewToFront:_playerView]; // 追加したビューを最前面に持ってくる

・・・省略・・・

(3) AVPlayerの操作

以下のように、AVPlayerを操作するためのメソッドが準備されており、サンプルでは、それぞれのボタンで動画を操作しています。

[_player play]; // 再生開始
[_player seekToTime:time]; // 指定時間への移動(シーク)
[_player pause]; // 再生停止(ポーズ)

また、タイマー処理で、動画の現在の再生位置でスラダーのボタン位置を動かしています。

- (void)syncSeekBar
{
    // スライダーの位置合わせ
    Float64 duration = CMTimeGetSeconds(_player.currentItem.asset.duration);
    Float64 time     = CMTimeGetSeconds([_player currentTime]);
    Float64 value    = ( _slider.maximumValue - _slider.minimumValue ) * time / duration + _slider.minimumValue;
    [_slider setValue:value];
}

サンプルでは、実装していませんが、最初に出てきたビューのサイズを画面いっぱいにすることで、全画面表示になります。

用意されているAVPlayer操作のメソッドは、いろいろ細かく設定が可能で、自由な速度で再生することなどが可能です。

いろいろ触ってみてちょっと注意が必要だなと感じたのは、以下の2つです。

  • マイナス値を設定した逆方向の再生は、動画がローカルにある場合しか使用できない。
  • 音量設定は、現在のシステムの音量値を1として、その比率で指定できるが、システムの音量を変化させることはできない。

実行している様子は、次の通りです。

その他の詳しい操作については、リファレンスをご参照ください。
AVPlayer Class Reference

6 最後に

今回は、iOSで動画を再生する方法を、一通り試してみました。

一言でまとめてしまうと・・・「とりあえず簡単に表示するならUIWebView、もう少し、ちゃんと置くならAVPlayerController (iOS7以前ならMPMoviePlayerController)、そして、きめ細かく自由に設計するならAVPlayer」と言う感じでしょうか。

サンプルコードは、下記におきました。(動画のHTTP Live Streaming配信は停止しております。)
github [GitHub] UIWebView サンプル
github [GitHub] MPMoviePlayerController サンプル
github [GitHub] AvPlayerCntroller サンプル
github [GitHub] AVPlayer サンプル

※動画は、ATTRIBUTION LICENSE 3.0 で公開されている、Ricardo Mantilla氏のものを利用させて頂いております。
http://mazwai.com/#/videos/216

7 参考リンク


UIWebView Class Reference
MPMoviePlayerController Class Reference
MPMoviePlayerViewController Class Reference
AVPlayerController Class Reference
AVPlayer Class Reference
UIWebViewでYouTube動画を再生する
参考:[iOS]UIWebViewのVideoタグハンドリング iOS