视频中的 AVfoundation 模糊背景

Posted

技术标签:

【中文标题】视频中的 AVfoundation 模糊背景【英文标题】:AVfoundation blur background in Video 【发布时间】:2017-01-11 19:50:17 【问题描述】:

在我的应用程序中,我将合成渲染大小固定为 1280 x 720。因此,如果要导入任何纵向视频,那么我必须显示模糊背景,并在中间显示视频的填充和纵横框。像这样:

https://www.youtube.com/watch?v=yCOrqUA0ws4

我实现了使用AVMtableComposition 播放两个视频,但我不知道如何模糊特定的背景音轨。我在我的代码中做了以下操作:

self.composition = [AVMutableComposition composition];
AVAsset *firstAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ScreenFlow_Blend" ofType:@"mp4"]]];


[self addAsset:firstAsset toComposition:self.composition withTrackID:1];
[self addAsset:firstAsset toComposition:self.composition withTrackID:2];
//  [self addAsset:ThirdAsset toComposition:self.composition withTrackID:3];

AVAssetTrack *backVideoTrack = [firstAsset tracksWithMediaType:AVMediaTypeVideo][0];;

self.videoComposition = [AVMutableVideoComposition videoComposition];
self.videoComposition.renderSize = CGSizeMake(1280, 720);
self.videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = [backVideoTrack timeRange];

CGFloat scale = 1280/backVideoTrack.naturalSize.width;
CGAffineTransform t = CGAffineTransformMakeScale(scale, scale);
t = CGAffineTransformTranslate(t, 0, -backVideoTrack.naturalSize.height/2 + self.videoComposition.renderSize.height/2);

AVMutableVideoCompositionLayerInstruction *frontLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction];
frontLayerInstruction.trackID = 1;
[frontLayerInstruction setTransform:t atTime:kCMTimeZero];

CGFloat scaleSmall = 720/backVideoTrack.naturalSize.height;

CGAffineTransform  translate = CGAffineTransformMakeTranslation(self.videoComposition.renderSize.width/2 - ((backVideoTrack.naturalSize.width/2)*scaleSmall),0);

CGAffineTransform  scaleTransform = CGAffineTransformMakeScale(scaleSmall,scaleSmall);

CGAffineTransform finalTransform = CGAffineTransformConcat(scaleTransform, translate);


CGAffineTransform t1 = CGAffineTransformMakeScale(scaleSmall,scaleSmall);
t1 = CGAffineTransformTranslate(t1,1280, 0);

AVMutableVideoCompositionLayerInstruction *backLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction];
backLayerInstruction.trackID = 2;
[backLayerInstruction setTransform:finalTransform atTime:kCMTimeZero];


//    AVMutableVideoCompositionLayerInstruction *maskLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction];
//    maskLayerInstruction.trackID = 3;
//    [maskLayerInstruction setTransform:t atTime:kCMTimeZero];


instruction.layerInstructions = @[backLayerInstruction,frontLayerInstruction];

self.videoComposition.instructions = @[ instruction ];

AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:self.composition];
playerItem.videoComposition = self.videoComposition;
self.player = [AVPlayer playerWithPlayerItem:playerItem];

AVPlayerLayer *newPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:[self player]];
[newPlayerLayer setFrame:[[[self playerView] layer] bounds]];
// [newPlayerLayer setHidden:YES];

[[[self playerView] layer] addSublayer:newPlayerLayer];
[self setPlayerLayer:newPlayerLayer];

使用上面的代码我可以做到这一点:

https://drive.google.com/open?id=0B2jCvCt5fosyOVNOcGZ1MU1laEU

我知道 customVideoCompositor 过滤合成帧的类。我试过了,但如果我使用customVideoCompositor,那么我将失去对合成层的转换。另外,来自customVideoCompositor,我不知道如何过滤特定的track id。

如果有人有任何文档链接或建议,那么非常感谢您继续前进。

【问题讨论】:

你能展示你对addAsset:toComposition:setPlayerLayer:的实现吗? 你视频的backVideoTrack.naturalSize是什么? backVideoTrack,naturalSize 为 1920 x 1080 你找到解决办法了吗?我面临同样的问题@AmritTrivedi 解决了吗?我正在寻找解决方案@Amrit Trivedi 【参考方案1】:

实现这一目标的方法是使用 2 个不同的 AVPlayers 和一个 a blur overlay view:backgroundLayer -> bluer overlay view -> frontLayer。您只需要确保播放器同时开始和停止即可。

另一个选项是使用 1 AVPlayertime observer。在每一帧上提取frontLayer 的当前图像,将其模糊并显示在backgroundLayer 中。模糊功能可以在我上面提供的同一个链接中找到。

【讨论】:

请理解问题。他想在运行时使用AVMutablecomposition 你也明白他的问题了吗?他要求任何可以提供帮助的建议。而且他也没有提到他只想使用AVMutablecomposition【参考方案2】:

在添加位于屏幕中心的第二个视频层之前,添加此代码

UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];//Change the effect which you want.

UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];

visualEffectView.frame = self.view.bounds;
[self.view addSubview:visualEffectView];

在斯威夫特中

    let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light) //Change the style which suites you
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = view.bounds
    blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] // for supporting device rotation
    view.addSubview(blurEffectView)

【讨论】:

我想播放视频曲目。会有多个 5 个视频轨道。动态模糊将在运行时更改多个轨道和我想在最后导出为视频的相同内容。因此您的解决方案仅适用于 UI 处理模糊,不适用于实时视频编辑。 您需要在需要时检查和更改模糊效果,动态模糊将使用您自己的算法进行,以适应您的视觉效果。请参阅您发布的 youtube 视频链接有一个简单的模糊效果。你想要动态模糊,添加算法来弥补。

以上是关于视频中的 AVfoundation 模糊背景的主要内容,如果未能解决你的问题,请参考以下文章

视频轨道背后的AVFoundation UIImage

AVFoundation 或 MPMoviePlayerViewController ios 中的快速视频浏览

AVFoundation 将第一帧添加到视频

如何实现网站背景为视频的模糊?

什么应该是更好的方法,MPMoviePlayerController 或 AVFoundation

AVFoundation视频流处理