Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/116.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将CIFilters切换到视频_Ios_Video_Swift5_Cifilter_Avvideocomposition - Fatal编程技术网

Ios 将CIFilters切换到视频

Ios 将CIFilters切换到视频,ios,video,swift5,cifilter,avvideocomposition,Ios,Video,Swift5,Cifilter,Avvideocomposition,有人能帮我理解在不重新启动视频播放器的情况下切换CIFilters的正确方法吗 我有一个本地视频在视图中播放。如果在“收藏”视图中点击某个单元格,视频将更改CIFilter 我的代码 let filter = CIFilter(name: "CIPhotoEffectNoir")! let asset = AVAsset(url: fooURL) let item = AVPlayerItem(asset: asset) item.videoComposition = AVVideoCompos

有人能帮我理解在不重新启动视频播放器的情况下切换CIFilters的正确方法吗

我有一个本地视频在视图中播放。如果在“收藏”视图中点击某个单元格,视频将更改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()
代码运行良好,效果正确

但我有一个集合视图,有很多过滤器。 点击某个单元格时,我无法找到切换与视频相关的过滤器的方法。 如果我用新的过滤器重新创建一个新的播放器,并将其作为当前“addsublayer”的替代品添加,则播放器将重新启动视频

@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"
    }
}
在不重新启动视频的情况下,将CIFilters更改为播放视频的最佳方法是什么 是否可以使用新的过滤器保存视频


谢谢

创建
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
即可轻松更改过滤器


(不过,您可能希望同步对筛选器的访问,以避免并发问题。)

创建
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
即可轻松更改过滤器


(不过,您可能希望同步对筛选器的访问,以避免并发问题。)

效果很好!!谢谢为了保存结果,我尝试使用AVMutableComposition作为AVPlayerItem的资产。。。。正确的方法是什么?要导出,最好使用
AVAssetExportSession
。它还可以使用
AVVideoComposition
,并将视频写入您指定的文件URL。我尝试将asset(让asset=AVAsset(URL:fooURL))传递给avassetxportsession。新视频保存正确,但不带过滤器。有什么想法吗?我使用let exporter=AVAssetExportSession(资产:资产!预设名称:AVAssetExportPresetHighestQuality)。谢谢你,弗兰克!!!您还必须设置导出会话的
videoComposition
,就像您对播放器项目所做的那样。非常好!!谢谢为了保存结果,我尝试使用AVMutableComposition作为AVPlayerItem的资产。。。。正确的方法是什么?要导出,最好使用
AVAssetExportSession
。它还可以使用
AVVideoComposition
,并将视频写入您指定的文件URL。我尝试将asset(让asset=AVAsset(URL:fooURL))传递给avassetxportsession。新视频保存正确,但不带过滤器。有什么想法吗?我使用let exporter=AVAssetExportSession(资产:资产!预设名称:AVAssetExportPresetHighestQuality)。谢谢你,弗兰克!!!您还必须设置导出会话的
视频合成
,就像您对播放器项目所做的那样。