メディアデータの編集
一部の抜き出し

ここには、メディアデータを編集するときにつかったもののメモをする予定。

まずは、メディアファイルの一部を抜き出す方法。AVAsset のオブジェクトを作るか、すでにある AVAsset オブジェクトと、CMTime で startTime と duration を用意する。すべてをコピーする場合は、startTime に KCMTimeZero を指定して、duration を asset.duration で AVAsset オブジェクトの長さを使う。

asset = AVAsset.assetWithURL(url)

startTime = CMTimeMake(startValue,timescale)

duration = CMTimeMake(durationValue,timescale)

次に、抜き出したい部分を入れるために空の AVMutableComposition オブジェクトを composition で用意して、insertTimeRange(timeRange,ofAsset:asset,atTime:time,error:error) で抜き出した部分を入れる。

composition = AVMutableComposition.composition

composition.insertTimeRange(CMTimeRangeMake(startTime,duration),ofAsset:asset,atTime:KCMTimeZero,error:nil)

ここでは、startTime と duration から CMTimeRangeMake で CMTimeRange を作った range と、データを抜き出す元の asset を指定し、新しく作った AVMutableComposition オブジェクトの先頭からの部分に入れたいので、atTime に KCMTimeZero つまり CMTime の 0 の値を指定している。error は、戻り値が欲しければ、Pointer オブジェクトを作り指定するが、nil で構わない。ちなみに、Objective-C で書く場合は、kCMTimeZero だが、RubyMotion は Ruby なので、定数は大文字で始めるということで、k が大文字になっている。これは他の定数でも同じ。

error は nil にしてあるが、ポインタを用意する必要があるので、RubyMotion の場合は、error = Pointer.new('@') として(@ はオブジェクトを受け取る)error のところに入れておけばいい。

ここでできた AVMutableComposition オブジェクトは、AVAsset オブジェクトと同じように扱えるが、中身を確認するときはコピーしてからするように、というようなことが、Apple の developer ドキュメントの例にあったので、ここでの例もそうしている。

snapShot = composition.copy

snapShotPlayerItem = AVPlayerItem.alloc.initWithAsset(snapShot)

snapShotPlayer = AVPlayer.playerWithPlayerItem(snapShotPlayerItem)

@playerView.player = snapShotPlayer

何をしているかというと、snapShot に AVMutableComposition オブジェクトをコピーして、それから、AVPlayerItem オブジェクトを作り、さらにそれから AVPlayer オブジェクトを作って、用意しておいた AVPlayerView に表示させている。これで、もとの AVAsset から、指定した部分を抜き出して新たなメディアデータが準備できた。

あと、映像ファイルから、音声だけを取り出したい場合は、次のようにやったらできた。

composition = AVMutableComposition.composition

audioTrack = asset.tracksWithMediaType(AVMediaTypeAudio)[0]

newAudioTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio,preferredTrackID:KCMPersistentTrackID_Invalid)

newAudioTrack.insertTimeRange(CMTimeRangeMake(KCMTimeZero,audioTrack.timeRange.duration),ofTrack:audioTrack,atTime:KCMTimeZero,error:nil)

まずは、上と同じように、空の AVMutableComposition オブジェクトを composition で用意する。

そして、もとの AVAsset オブジェクトから tracksWithMediaType(mediaType) で mediaType に AVMediaTypeAudio を指定して、音声トラックを取り出す。ここでは、一番最初のトラックを取り出して処理している。複数の音声トラックがある場合は、取り出したい物を指定する。

つぎに、空の AVMutableComposition オブジェクトに、addMutableTrackWithMediaType(mediaType,preferredTrackID:id) で空の音声トラックを追加する。mediaType は、同じく AVMediaTypeAudio で、preferredTrackID は、決め打か、KCMPersistentTrackID_Invalid を指定して一番最後に追加する。

ここでできた newAudioTrack は AVMutableCompositionTrack オブジェクトなので、insertTimeRange(cmTimeRange,ofTrack:track,atTime:cmTime,error:error) で、追加したい音声トラックから指定した範囲を抜き出して追加する。ここでは、CMTimeRangeMake で、開始時間 (KCMTimeZero) と長さ (audioTrack.timeRange.duration) を指定して、元の音声トラックのすべてを追加している。atTime にも KCMTimeZero を指定することで、一番最初のところに入れている、ということになる。error は nil にしてある。

これで、composition を上と同じようにして、playerView に設定すると、音声だけが出るはず。

あとは、これを保存したり、さらに加工したり、できれば、layer を追加したりしたいが、それは今後の課題。