переключить CIFilters на видео - PullRequest
0 голосов
/ 20 октября 2019

Может кто-нибудь помочь мне понять, как правильно переключать CIF-фильтры без перезапуска видеоплеера?

У меня есть локальное видео, воспроизводимое внутри вида. Если я коснусь ячейки в виде коллекции, видео изменит CIFilter.

мой код

let filter = CIFilter(name: "CIPhotoEffectNoir")!
let asset = AVAsset(url: fooURL)
let item = AVPlayerItem(asset: asset)
item.videoComposition = AVVideoComposition(asset: asset,  applyingCIFiltersWithHandler: { request in
    let source = request.sourceImage.clampedToExtent()
    filter.setValue(source, forKey: kCIInputImageKey)

    let output = filter.outputImage

    request.finish(with: output!, context: nil)
})

player = AVPlayer(playerItem: item)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = videoViewDetail.bounds
videoViewDetail.layer.addSublayer(playerLayer)
player?.play()

код работает отлично, и эффект правильный, примените

, но у меня есть просмотр коллекции со многими фильтрами CIF. При нажатии на ячейку я не могу найти способ переключить фильтр, связанный с видео. Если я заново создаю новый проигрыватель с новым фильтром и добавляю его вместо текущего «addublayer», проигрыватель перезапустит видео.

@IBAction func tap(_ sender: UITapGestureRecognizer) {

    let location = sender.location(in: self.collectionView)
    let indexPath = self.collectionView.indexPathForItem(at: location)

    if let index = indexPath {
        // code to switch to another CIFilter like for example "CISepiaTone"
    }
}

Каков наилучший способ изменить фильтры CIF на воспроизводимое видео безперезапустить видео Возможно ли сохранить видео с новым фильтром?

Спасибо!

1 Ответ

1 голос
/ 20 октября 2019

Блок обработчика, который вы предоставляете при создании AVVideoComposition, постоянно вызывается для каждого видеокадра, который показывает проигрыватель. Это означает, что вам просто нужно переключить фильтр, который используется внутри этого блока.

Самый простой способ добиться этого - обратиться к фильтру извне блока, а не захватывать его. Затем вы можете просто изменить ссылку во время выполнения.

Например, если ваш код выполняется внутри какого-либо метода контроллера представления, вы можете сделать следующее:

class MyViewController: UIViewController {

    var filter: CIFilter = CIFilter(name: "CIPhotoEffectNoir")!

    func createPlayer() {
        let asset = AVAsset(url: fooURL)
        let item = AVPlayerItem(asset: asset)
        item.videoComposition = AVVideoComposition(asset: asset,  applyingCIFiltersWithHandler: { [weak self] request in
            guard let self = self else {
                request.finish(with error: SomeError)
                return
            }
            let source = request.sourceImage.clampedToExtent()
            self.filter.setValue(source, forKey: kCIInputImageKey)

            let output = self.filter.outputImage

            request.finish(with: output!, context: nil)
        })

        player = AVPlayer(playerItem: item)
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = videoViewDetail.bounds
        videoViewDetail.layer.addSublayer(playerLayer)
        player?.play()
    }

    // ...

}

Затем вы можете легко изменитьФильтр, просто изменив self.filter.

(хотя вы можете синхронизировать доступ к фильтру, чтобы избежать проблем параллелизма.)

...