一、尝试思路
1、使用了GPUImageChromaKeyFilter,效果不太理想。
2、换用GPUImageChromaKeyBlendFilter,它通过将第一个源中setColorToReplaceRed中指定颜色的像素替换为第二个源中的像素来混合两个源。报错Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?
,暂无法解决,pass
3、使用GPUImageCropFilter和GPUImageMaskFilter组合,思路是剪切成两个视频,再mask混合。效果不太理想。
let filter1 = GPUImageCropFilter(cropRegion: CGRect(x: 0.5, y: 0, width: 0.5, height: 1))
let filter2 = GPUImageCropFilter(cropRegion: CGRect(x: 0, y: 0, width: 0.5, height: 1))
let filter = GPUImageMaskFilter()
4、使用自定义filter,系统内置的filter无法满足需求。打开GPUImageColorInvertFilter.m可以查看怎么实现GPUImage 自定义滤镜,自己实现一个AlphaFilter
#ifndef AlphaFilter_h
#define AlphaFilter_h
#import
@interface AlphaFilter : GPUImageFilter
@end
#endif /* AlphaFilter_h */
#import "AlphaFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageVideoAlphaShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;//这个对应下面的ST坐标,即右边视频的坐标
uniform sampler2D inputImageTexture;//这个是完整视频的纹理
const lowp vec2 leftW = vec2(-0.5,0.0);
void main()
{
//从右边的视频中拿RGB值,从左边的视频中拿Alpha值,然后返回一个新的RGBA.
lowp vec4 rightTextureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec2 leftTextureCoordinate = leftW + textureCoordinate;
lowp vec4 leftTextureColor = texture2D(inputImageTexture, leftW + textureCoordinate);
gl_FragColor = vec4(rightTextureColor.rgb, leftTextureColor.r);//leftTextureColor.r
}
);
#else
#endif
@implementation AlphaFilter
- (id)init {
if (!(self = [super initWithFragmentShaderFromString: kGPUImageVideoAlphaShaderString]))
{
return nil;
}
return self;
}
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates {
static const GLfloat posVertices[] = {
// x , y
-1, 1,
1, 1,
-1, -1,
1, -1,
};
/*
[0.0,0.0]----[0.5,0.0]----[1.0,0.0]
| | |
| | |
| | |
[0.0,0.5]----[0.5,0.5]----[1.0,0.5]
| | |
| | |
| | |
[0.0,1.0]----[0.5,1.0]----[1.0,1.0]
*/
static const GLfloat textVertices[] = {
// s , t
0.5, 1.0,
1.0, 1.0,
0.5, 0.0,
1.0, 0.0
};
// static const GLfloat textVertices[] = {
// // s , t
// 0.5, 1.0,
// 1.0, 1.0,
// 0.5, 0.5,
// 1.0, 0.5
// };
// 向缓冲区对象写入刚定义的顶点数据
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE, GL_ZERO);
[super renderToTextureWithVertices:posVertices textureCoordinates:textVertices];
glDisable(GL_BLEND);
}
@end
至此,GPUImage透明视频实现完毕。遗留个问题:没有声音,稍后解决。
参考:
自定义GPUImageFilter滤镜(类似抖音效果)
iOS基于GPUImage带Alpha的mp4播放方案
二、收获
1、百度不到的资料,去谷歌,真的太不一样。
,可搜索“礼物特效透明MP4”对比下效果。
2、少写了相关的看不懂的代码,肯定是不能正常工作的
,少写了init方法,死活出不来效果。
三、遇到的一些问题:
GPUImage github主页的说明中,自定义滤镜的方法.fsh好像不太好使,或者自己不会用。
GPUImage的GPUImageMovie调用本地视频,为什么没有声音
用url是没有声音的,用item就可以了,预览时不支持播放声音,需要自行添加声音播放功能,用AVPlayer吧
GPUImageVideoCamera: 从Camera获取的实时视频。
GPUImageStillCamera: 从Camera获取到的图片。
GPUImagePicture: 静态图片。
GPUImageMovie: 电影
fileType: AVFileType.mp4.rawValue
outputSettings: [AVVideoCodecKey : AVVideoCodecH264, AVVideoWidthKey : 1080, AVVideoHeightKey : 1080]
[AVAssetWriter initWithURL:fileType:error:] invalid parameter not satisfying: [outputURL isFileURL]’
原因:看一下初始化的GPUImageMovieWriter的MovieURL,是它:fileURLWithPath 不是:URLWithString
[AVAssetWriterInput appendSampleBuffer:] Cannot append sample buffer: Input buffer must be in an uncompressed format when outputSettings is not nil'
[AVAssetWriter startWriting] Cannot call method when status is 3'
滤镜使用:
let imgView = UIImageView(frame: view.bounds)
imgView.image = UIImage(named: "bg")
view.addSubview(imgView)
let inputUrl1 = URL(fileURLWithPath: Bundle.main.path(forResource: "two4", ofType: "mp4") ?? "")
let imageMovie1 = GPUImageMovie(url: inputUrl1)
imageMovie1?.shouldRepeat = true
let filter = AlphaFilter()
imageMovie1?.addTarget(filter)
let videoView = GPUImageView(frame: view.bounds)
videoView.backgroundColor = UIColor.clear
videoView.fillMode = .stretch
view.addSubview(videoView)
filter.addTarget(videoView)
imageMovie1?.startProcessing()
四、新问题
1、播放太快-设置成真实速率即可
2、后台重新进入,卡住了-前后台切换需要关闭和打开movie,否则会崩溃卡住
3、没声音
自己用AVPlayer播放无画面的mp4里的声音即可,注意AVPlayer播放MP4里的声音,必须有playerlayer,否则无法播放。
4、延迟了7秒才开始播放???
连接Xcode的话,首次加载会超长时间,测试机拔掉线单独运行没事
5、前后台切换,重新播放问题
6、子线程调UI问题