iPhoneで動作する映像フィルタをつくる:GPUImage+iOSのAVFoundationフレームワーク
こんにちはandyです。
引き続き映像フィルタの話です。
前回はGPUImageを使ってアプリケーションリソースに保存したMpeg4動画にフィルタ処理を追加して再生しましたが、このプログラムをもう少し発展させて2つのMpeg4動画を用意してそのファイルを編集でつなぎ、つないだ映像にフィルタを掛けてみたいと思います。
言葉で書くと大げさですが、結構簡単です。
iOSにはAVFoundationというフレームワークが用意されていて、このフレームワークを使って映像や音声の編集、合成が出来ます。
まずはソース
それでは完成ソースから。
- (void)showFilteringMovie { //解説-1 NSURL *fileURL1 = [[NSBundle mainBundle] URLForResource:@"videoviewdemo" withExtension:@"mp4"]; NSURL *fileURL2 = [[NSBundle mainBundle] URLForResource:@"sample3" withExtension:@"mp4"]; //解説-2 AVMutableComposition* composition = [AVMutableComposition composition]; AVMutableCompositionTrack* videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; //解説-3 AVURLAsset* firstMovie = [AVURLAsset URLAssetWithURL:fileURL1 options:nil]; AVURLAsset* secondMovie = [AVURLAsset URLAssetWithURL:fileURL2 options:nil]; //解説-4 AVAssetTrack* firstMovieVideo = [[firstMovie tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVAssetTrack* secondMovieVideo = [[secondMovie tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; //解説-5 [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstMovie.duration) ofTrack:firstMovieVideo atTime:kCMTimeZero error:nil]; [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, secondMovie.duration) ofTrack:secondMovieVideo atTime:firstMovie.duration error:nil]; GPUImageView *filterView = [[GPUImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)]; GPUImagePolkaDotFilter *filter = [[GPUImagePolkaDotFilter alloc] init]; //解説-6 movieFile = [[GPUImageMovie alloc] initWithAsset:composition]; movieFile.playAtActualSpeed = YES; [movieFile addTarget:filter]; [filter addTarget:filterView]; [self.view addSubview:filterView]; //解説-7 [NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector: @selector(play:) userInfo:nil repeats:NO]; } - (void)play:(id)sender { [movieFile startProcessing]; }
ソース解説していきます
解説-1
この部分は前回と同様ですが、Resourcesフォルダ内のMpeg4ファイルを2つ読み込んでいます。
解説-2
この部分はcompositionという映像と遠征を編集するための入れ物(ビデオ編集ソフトでいうところのタイムライン?)を用意しています。その後のvideoTrackで映像を入れるトラックをcompositionの中に作っています。
解説-3
この部分は解説-1で読み込んだファイルからAVURLAssetというオブジェクトを作っています。このオブジェクトが動画データのトラックやめた情報を管理する役目を果たします。
解説-4
この部分は解説-3で作ったAVURLAssetオブジェクトから映像トラックだけを取り出しAVAssetTrackというオブジェクトを作っています。映像のトラックはAVURLAsset内で複数保持できるため、最初の映像トラックを取得するために配列の最初の項目を指定しています(objectAtIndex:0の部分)。
解説-5
この部分は解説-2で出てきたvideoTrackに先ほど作ったAVAssetTrackを追加しています。ここでCMTimeという考えが出てくるのですが、CMTimeの考え方はこちらなどの解説や本家のリファレンスなどを参考にしてください。
で、何を指定しているかというと、insertTimeRangeの部分で追加するムービーの長さ、ofTrackで追加するAVAssetTrackのオブジェクト、atTimeでcompositionのどの時間から追加するかを指定しています。そのため、secondMovieのatTimeの部分はfirstMovieの終わった後という意味でfirstMovie.durationとなっています。
解説-6
この部分はcompositionをGPUImageMovieクラスに受け渡しています。前回のコードではinitWithURLとなっていましたが、initWithAssetとすることでAVMutableCompositionやAVURLAssetを渡すことが出来ます。
解説-7
この部分はタイマーを使ってフィルタリングのスタートを0.5秒ほど遅らしています。どうやらこうしないとファイルの読み込み終了が出来ずに映像が出ないようでした。ファイルサイズにもよるかもしれません。
今回は、2つの動画を繋げてから映像フィルタを掛けてみました。これが出来ると映像編集アプリを作ってフィルタ機能を付けるなんてことも出来そうです。
次回は何しようかな・・・
できれば映像や音声の合成をしたいと思ってますが、そこまでいけるか・・・
コメントをどうぞ