Jeffsuke is not a pen.

🏊‍♂️🚴‍♂️🏃‍♂️💻📱

iOSで動画ストリーミング。簡単で十分なやり方。

動画ストリーミングを実装する機会があったので、まとめる。

やり方は大きくわけて2つ

  • HTTP Live Streaming
  • Media Player framework

前者を用いた場合の再生方法は

  • AV Foundation framework
  • OpenAL framework

などがあります。

やりたいこと

UITableViewCell上でサーバー上にある動画を再生する。

f:id:jeffsuke:20150107163712g:plain

方針

今回の要件を満たすのには、Media Player frameworkで十分なので、これを使う。MPMoviePlayerControllerというクラスを用いる。これはiOS2.0からあるクラスなので、バージョン対応もバッチリ。

Media Player frameworkを使う上での注意点

  • Simulator上で動かすことが出来ない場合がある。
  • 複数の動画を同時に再生する事はできない。Media Player frameworkで新しい動画を再生し始めると、その直前に再生していた動画のキャッシュは削除される。
  • ビデオの長さが10分以上、5分間のデータ量が5MB以上であれば、HTTP Live Streamingを用いる必要がある。
  • アプリ側で動画をミュートできない

実装

まず、viewDidLoad にてMPMoviePlayerControllerを初期化する。

@interface JSKMainTableViewController ()
@property (nonatomic) MPMoviePlayerController *moviePlayer;
@end

static NSString *const kURLString = @"https://ia802302.us.archive.org/27/items/Pbtestfilemp4videotestmp4/video_test.mp4";

@implementation JSKMainTableViewController
- (void)viewDidLoad {
    [super viewDidLoad];
   
    self.moviePlayer = [[MPMoviePlayerController alloc] init];
   
    // ストリーミングするため
    self.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
    self.moviePlayer.contentURL = [NSURL URLWithString:kURLString];
   
    // UITableViewCell上に表示するため、動画操作パーツは非表示
    [self.moviePlayer setControlStyle:MPMovieControlStyleNone];
   
    // 動画をリピートする
    self.moviePlayer.repeatMode = MPMovieRepeatModeOne;
}

このmoviePlayerを、- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath にてCellに渡す。 CellForRowAtIndexPathで渡していないのは、Storyboard+Autolayoutを用い、UIViewの上に貼り付けているため、Viewが生成されるのを待つ必要があるため。

- (void)layoutWithUrl:(NSString *)url
{
    // 貼り付ける予定のUIViewのサイズを取得
    player.view.frame = _videoSuper.frame;
    [self.videoSuper addSubview: player.view];

    // 再生
    [player prepareToPlay];
    [player play];
}

以上で再生ができる。

Cellが表示している時のみ動画再生

今回はCellが出現するタイミングで再生を実施したかったので、UITableViewCell内の[player play];を削除し、UITableViewに以下を実装した。

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([cell.class isSubclassOfClass:JSKVideoTableViewCell.class]) {
        // 動画停止
        [self.moviePlayer pause];
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([cell.class isSubclassOfClass:JSKVideoTableViewCell.class]) {
             // 動画の貼り付け
        [(JSKVideoTableViewCell *)cell layoutWithPlayer:self.moviePlayer];

              // 動画再生
        [self.moviePlayer play];
    }
}

これにより、画面上にCellが表示されている時のみ動画が再生される。