8

Swift を使用して、AVPlayer のコンテンツをビューの AVPlayerLayer に表示しています。関連付けられた AVPlayerItem には videoComposition があり、それを作成するためのコードを少し単純化したバージョン (エラー チェックなどなし) は次のようになります。

playerItem.videoComposition = AVVideoComposition(asset: someAsset, applyingCIFiltersWithHandler: {
                [unowned self] (request: AVAsynchronousCIImageFilteringRequest) in

    let paramDict = << set up parameter dictionary based on class vars >>

    // filter the image
    let filter = self.ciFilterWithParamDict(paramDict) {
    filter.setValue(request.sourceImage, forKey: kCIInputImageKey)
    if let filteredImage = filter.outputImage {
        request.finishWithImage(filteredImage, context: nil)
    }
})

これは、AVPlayer が再生またはシークしているときに、すべて期待どおりに機能します。また、新しい videoComposition が作成されて読み込まれると、AVPlayerLayer が正しくレンダリングされます。

ただし、フィルターパラメーターの計算に使用する値の一部を変更したときに、AVPlayer/ AVPlayerItem/ AVVideoComposition を「トリガー」して再レンダリングする方法が見つかりませんでした。値を変更してから再生またはシークすると、正しくレンダリングされますが、再生またはシークの場合のみです。「その場で」レンダリングをトリガーする方法はありませんか?

4

5 に答える 5

6

これを行う最善の方法は、一時停止した AVPlayer で CIFilter 入力を編集するときに、AVPlayerItem の新しい AVVideoComposition インスタンスを単純に作成することです。私の経験では、プレーヤー アイテムを交換してプレーヤーに戻すよりも、はるかに高速でクリーンです。新しいビデオ コンポジションを作成するのは遅いと思うかもしれませんが、実際には、その特定のフレームでレンダリング パスを再定義するだけです。これは、変更によって影響を受けた Core Image キャッシュの一部を無効にするのとほぼ同じくらい効率的です。

ここで重要なのは、プレーヤー アイテムのビデオ コンポジションを何らかの方法で無効にして、再描画をトリガーする必要があることです。Core Image フィルタの入力パラメータを変更するだけでは、悲しいことに、問題の原因であるビデオ構成を無効にする方法はありません (私が知っていることです)。

AVPlayerItem の AVMutableVideoComposition インスタンスを作成し、一時停止時に編集するときに (命令、animationTool、frameDuration などを変更することによって) いくつかの方法で変更することで、さらに効率を高めることができます。

于 2017-08-17T05:25:13.743 に答える
4

ハックを使用して avPlayerItem を完全に置き換え、強制的に更新しました。しかし、avPlayerItem をトリガーして直接再レンダリングする方法があれば、はるかに優れています。

// If the video is paused, force the player to re-render the frame.
if (self.avPlayer.currentItem.asset && self.avPlayer.rate == 0) {
    CMTime currentTime = self.avPlayerItem.currentTime;

    [self.avPlayer replaceCurrentItemWithPlayerItem:nil];
    [self.avPlayer replaceCurrentItemWithPlayerItem:self.avPlayerItem];
    [self.avPlayerItem seekToTime:currentTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
于 2016-06-10T17:48:37.340 に答える
1

これはあなたを助けるかもしれません。

let currentTime = self.player.current()
self.player.play()
self.player.pause()
self.player.seek(to: currentTime, toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero)
于 2017-05-16T06:25:49.407 に答える