AVAssetWriterのsample-writing sessionについて

やりたかったこと

カメラからリアルタイムに得られるCMSamplerBufferを、画像処理や音声処理でフィルタリングすることでAVAssetWriter(AVAssetWriterInput)に追加するかしないかを判定したかった。

つまりCMSampleBufferのサンプルを書き込むか捨てるかの取捨選択をリアルタイムに行いたかった。

(具体的には、24/7でカメラを撮りっぱなしにして、人間や動物が映っているシーンだけ or 人間の声が入っているときだけ記録するというのをやろうとしている)

考えていた実装方法

AVAssetWriter の startWriting()

→ AVAssetWriter の startSession(atSourceTime:)
→ AVAssetWriterInput の append(_:)
→ AVAssetWriterInput の append(_:)
...
→ AVAssetWriter の startSession(atSourceTime:)

→ AVAssetWriter の finishWriting() でファイル書き込み

書き込むTime RangeについてstartSession〜endSessionのところを繰り返す、というイメージだった。

結論

結論としてはこの方法はNG。二度目のstartSessionでAVAssetWriter の status プロパティの値が .failed になる。

エラー内容:

Error Domain=AVFoundationErrorDomain Code=-11862 "Cannot append media data after ending session"

別の方法を取るのだが、ドキュメントが紛らわしいと思ったので、一連の調べた内容をここに書いておく。

sample-writing session

AVAssetWriter の startSession(atSourceTime:)のドキュメントより。

Sequences of sample data appended to the asset writer inputs are considered to fall within “sample-writing sessions.” You must call this method to begin one of these sessions.

asset writer inputsに追加されたサンプルデータのシーケンスを"sample-writing sessions"と呼ぶ。

これらのセッションを開始するにはこのメソッド startSession(atSourceTime:) を呼ぶ。

AVAssetWriter の endSession(atSourceTime:)

このメソッドは呼ばなくてもOKなのだが、

You do not need to call this method;  (このメソッドを呼び出す必要はありません)

endSession〜のリファレンスにこういう記述がある。

The endTime defines the moment on the timeline of source samples at which the session ends. In the case of the QuickTime movie file format, each sample-writing session's startTime…endTime pair corresponds to a period of movie time into which the session's samples are inserted. Samples with later timestamps will be still be added to the media but will be edited out of the movie. So if the first session has duration D1 = endTime - startTime, it will be inserted into the movie at movie time 0 through D1; the second session would be inserted into the movie at movie time D1 through D1+D2, and so on.
(endTimeは、ソースサンプルのタイムライン上で、セッションが終了する瞬間を定義します。QuickTimeムービーファイルフォーマットの場合、各サンプルライティングセッションのstartTime...endTimeのペアは、セッションのサンプルが挿入されるムービーの時間に対応しています。それ以降のタイムスタンプを持つサンプルは、メディアには追加されますが、ムービーからは編集されます。つまり、最初のセッションのdurationがD1 = endTime - startTimeの場合、ムービータイム0からD1までの間に挿入され、2番目のセッションはムービータイムD1からD1+D2までの間に挿入されるということです。)

自分のやりたいこと的にはまさに

・最初のセッション 0〜D1
・2番目のセッション D1〜D2
...

という感じで挿入していきたいので、ドンピシャでその例がリファレンスで記述されているわけで、startSession〜endSessionを書き込みたいtime rangeごとに繰り返せばよさそうである。

しかし上に書いたとおり、二度目のstartSessionでエラーになる。

Multiple sample-writing sessions

ヘッダファイルにこのような記述があった。(リファレンスには書かれていない)

NOTE: Multiple sample-writing sessions are currently not supported. It is an error to call -startSessionAtSourceTime: a second time after calling -endSessionAtSourceTime:. (複数のサンプル書き込みセッションは現在サポートされていません。endSessionAtSourceTime:を呼び出した後、2回目に-startSessionAtSourceTime:を呼び出すとエラーになります。)

なるほどダメなのですね...😇

では上のD1〜D2みたいな説明は何...?

ここから先は

445字
文章やサンプルコードは多少荒削りかもしれませんが、ブログや書籍にはまだ書いていないことを日々大量に載せています。たったの400円で、すぐに購読解除してもその月は過去記事もさかのぼって読めるので、少しでも気になる内容がある方にはオトクかと思います。

技術的なメモやサンプルコード、思いついたアイデア、考えたこと、お金の話等々、頭をよぎった諸々を気軽に垂れ流しています。

最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/