类似faceu的移动端视频美颜、视频滤镜、人脸实时关键点追踪、实时整形(瘦脸大眼睛等)、动态贴纸
VisioninSDK是一个移动端的跨平台实时视频处理库,提供了视频磨皮美颜、视频滤镜、人脸实时关键点追踪、人脸实时整形(瘦脸、大眼睛等)、人脸动态贴纸等功能的库。
保证包含SDK库文件
#import "Visionin.h"
[Visionin initialize:@"xxx"];
VSVideoFrame* videoFrame = [[VSVideoFrame alloc] initWithPosition:AVCaptureDevicePositionFront pixelFormat:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange view:self.view];
[videoFrame startVideoFrame];
[videoFrame processVideoSampleBuffer:sampleBuffer];
如果关闭摄像头,需要调用stopVideoFrame函数。
前后摄像头切换时候,需要设置cameraPosition
VisioninSDK默认为竖屏模式,屏幕旋转或者横屏等模式下,需要设置outputImageOrientation,支持以下屏幕方向参数:
注意:此处方向为StatusBar方向,非Device方向,获取StatusBar方向:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]
VisioninSDK支持视频流、预览的镜像设置,可自由组合(不支持视频流镜像、预览非镜像的组合):
磨皮:
[videoFrame setSmoothLevel:level];
美白:
[videoFrame setBrightenLevel:level];
如需关闭美颜,只要把所有参数设置为0即可
VisioninSDk支持多种数据格式的获取,包括BGRA、YUV420P、NV21、NV12格式;
下面以获取BGRA格式的CVPixelBufferRef为例说明,并实现了一个封装为CMSampleBufferRef例子
[videoFrame setBgraPixelBlock:^(CVPixelBufferRef pixelBuffer, CMTime time) {
// 封装CMSampleBufferRef的例子
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
CVPixelBufferRetain(pixelBuffer);
CMSampleBufferRef sampleBuffer = NULL;
CMSampleTimingInfo timimgInfo = kCMTimingInfoInvalid;
CMVideoFormatDescriptionRef videoInfo = NULL;
CMVideoFormatDescriptionCreateForImageBuffer(
NULL, pixelBuffer, &videoInfo);
CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault,
pixelBuffer,
true,
NULL,
NULL,
videoInfo,
&timimgInfo,
&sampleBuffer);
CVImageBufferRef cvimgRef = CMSampleBufferGetImageBuffer(sampleBuffer);
float _width = CVPixelBufferGetWidth(cvimgRef);
float _height = CVPixelBufferGetHeight(cvimgRef);
NSLog(@"width:%lf height:%lf", _width, _height);
// 注意以下的释放代码
CFRelease(sampleBuffer);
}];
一般情况下,本地预览使用较高分辨率,而编码使用较低分辨率,VisioninSDK支持自定义输出视频流尺寸,如下:
[videoFrame setOutputSize:CGSizeMake(480, 640)];
VisioninSDK提供了丰富的滤镜,如果要使用滤镜功能,则调用如下
[videoFrame setExtraFilter:filterName];
如果要改动滤镜参数,如修改高斯模糊的半径,则调用如下:
[videoFrame setExtraParameter:para];
关闭滤镜
[videoFrame closeExtraFilter];
目前支持的滤镜有:
VisioninSDK提供了一个简单的摄像头,可以不使用VSVideoFrame直接使用VSVideoCamera,VSVideoCamera支持所有VSVideoFrame的功能
VSVideoCamera* videoCamera = [[VSVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh position:AVCaptureDevicePositionFront view:self.view];
如果需要从VSVideoCamera获取没有经过美颜的视频流,需要实现VSCameraSampleDelegate协议
VSCameraSampleDelegate:
调用VSVideoCamera的setSampleDelegate方法
[videoCamera startCameraCapture];
VisioninSDK支持国际通用的68个关键点的实时追踪,各个坐标序号如下所示:
开启人脸关键点的追踪的功能只需要调用VSFacer函数的startFaceTracking
VSFacer* facer = [VSFacer shareInstance];
[facer startFaceTracking];
获取关键点使用VSFacer的getFacerMarks接口
float* markers = [[VSFacer shareInstance] getFacerMarks];
[[VSFacer shareInstance] stopFaceTracking];
如果不再使用该功能,请及时调用此接口关闭
注意: 调用此接口可以停止整形功能,但是不能停止贴纸道具
[[VSFacer shareInstance] startShaper];
整形依赖人脸关键点追踪,如果没有开启人脸情况启动整形,则会自动开启人脸追踪
[[VSFacer shareInstance] setShapping:xxx strength:xxx];
整形强度0-1,目前支持的整形部位有:
[[VSFacer shareInstance] stopShaper];
如果不再使用该功能,请及时调用此接口关闭
AR互动道具可以在人脸上叠加各种好玩的道具,包括2D和3D道具
设置道具使用VSProps的startProps接口:
[[VSProps shareInstance] startLocalProps:propsPath mirror:mirror]
其中propsPath为道具包在本地的全路径,mirror为表示是否镜像加载
VisioninSDK支持同时添加2个道具,用于主播自己选择了一个道具,此时观众又赠送了一个道具的情况。使用第二个道具的方法:
[[VSProps shareInstance] startLocalProps2:propsPath mirror:mirror]
如果停止使用道具,则调用stopProps函数
[[VSProps shareInstance] stopProps]
停止第二个道具
[[VSProps shareInstance] stopProps2]
注意: 调用此接口不能停止人脸追踪和整形,要停止人脸追踪必须显示的调用stopFaceTracking接口
####调用全局初始化方法:
Visionin.initialize(context, lisence);
注意:
VSVideoFrame是VisioninSDK所有功能的入口类,依赖Surface创建Opengl Context。
surfaceView.getHolder().getSurface()
来创建。典型的VSVideoFrame的创建如下:
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
videoFrame = new VSVideoFrame(surfaceHolder.getSurface());
[videoFrame startVideoFrame];
} catch (Exception e) {
e.printStackTrace();
return;
}
try {
mCamera.setPreviewTexture(videoFrame.surfaceTexture());
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
videoFrame.start();
关闭摄像头,需要调用stop
函数
注意:start与stop必须成对调用,否则会破坏状态机导致SDK不可用
在程序进入后台时,需要销毁VSVideoFrame,在重新打开程序时候需要重新创建VSVideoFrame
销毁VSVideoFrame调用videoFrame.destroy()
前后摄像头切换时候,需要调用setCameraPosition
方法设置摄像头
VisioninSDK默认为竖屏模式,屏幕旋转或者横屏等模式下,需要调用setOutputImageOritation
方法设置方向,支持以下屏幕方向参数:
VisioninSDK支持视频流、预览的镜像设置,可自由组合(不支持视频流镜像、预览非镜像的组合):
setMirrorFrontVideo
方法: 前置摄像头下视频流是否镜像setMirrorBackVideo
: 后置摄像头下视频流是否镜像setMirrorFrontPreview
: 前置摄像头下预览是否镜像setMirrorBackPreview
:后置摄像头下是否镜像磨皮:
videoFrame.setSmoothLevel(level);
美白:
videoFrame.setBrightenLevel(level);
如需关闭美颜,只要把所有参数设置为0即可
如果您要自己压缩bitmap并预览,则可以把VisioninSDK提供的预览关闭,方法为:
videoFrame.removeOutputView();
如果要再重新使用VisisioninSDK的预览,方法为:
videoFrame.setOutputView();
###1.3 获取经过美颜后的视频流
VisioninSDk支持多种数据格式的获取,包括RGBA、YUV420P、NV21、NV12格式;
下面以获取NV21格式视频为例说明,并实现了一个封装为Bitmap例子
videoFrame.setNV21Callback(new VSRawBytesCallback() {
@Override
public void outputBytes(byte[] bytes) {
// width、height为输出视频尺寸,需提前设好
int frameSize = width * height;
int[] rgba = new int[frameSize];
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++) {
int y = (0xff & ((int) data[i * width + j]));
int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 0]));
int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1]));
y = y < 16 ? 16 : y;
int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128));
int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128));
r = r < 0 ? 0 : (r > 255 ? 255 : r);
g = g < 0 ? 0 : (g > 255 ? 255 : g);
b = b < 0 ? 0 : (b > 255 ? 255 : b);
rgba[i * width + j] = 0xff000000 + (r << 16) + (g << 8) + b;
}
}
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.setPixels(rgba, 0, width, 0, 0, width, height);
}
});
一般情况下,本地预览使用较高分辨率,而编码使用较低分辨率,VisioninSDK支持自定义输出视频流尺寸,如下:
videoFrame.setOutputSize(360, 640);
VisioninSDK提供了丰富的滤镜,如果要使用滤镜功能,则调用如下(以高斯模糊为例)
videoFrame.setExtraFilter(VSVideoFrame.VS_GAUSSIAN_BLUR_FILTER);
如果要改动滤镜参数,如修改高斯模糊的半径,则调用如下:
videoFrame.setExtraParameter(para);
关闭滤镜
videoFrame.closeExtraFilter()
支持的滤镜同ios
VisioninSDK支持国际通用的68个关键点的实时追踪,坐标序号同iOS
开启人脸关键点的追踪的功能,首先调用初始化函数,初始化函数只需要调用一次,然后调用VSFacer函数的startFaceTracking
VSFacer.initialize(Context);
VSFacer.startFacerTracking();
获取关键点使用VSFacer的getFacerMarks接口
float[] markers = VSFacer.getFacerMarks(face_index);
VSFacer.stopFaceTracking();
如果不再使用该功能,请及时调用此接口关闭
注意: 调用此接口可以停止整形功能,但是不能停止贴纸道具
VSFacer.startFacerShaper();
整形依赖人脸关键点追踪,如果没有开启人脸情况启动整形,则会自动开启人脸追踪
目前的人脸整形包括大眼睛和瘦脸,未来会加入更多的整形功能
VSFacer.stopFacerShaper();
如果不再使用该功能,请及时调用此接口关闭
AR互动道具可以在人脸上叠加各种好玩的道具,包括2D和3D道具
设置道具使用VSProps的startProps接口:
VSProps.startStProps(name);
name为道具名字
如果停止使用道具,则调用stopProps函数
VSProps.stopStProps();
注意: 调用此接口不能停止人脸追踪和整形,要停止人脸追踪必须显示的调用stopFaceTracking接口
VSAudioFrame是VisioninSDK音频功能的入口类,同VSVideoFrame类一样,需要先调用全局初始化方法,再创建VSAudioFrame对象:
VSAudioFrame audioFrame = new VSAudioFrame();
####调用start函数
audioFrame.start();
####关闭音频
关闭音频与MIC,需要调用stop
函数
注意:同VSVideoFrame一样,start与stop必须成对调用,否则会破坏状态机导致SDK不可用_
####声音特效功能
VisioninSDK提供了音频特效的功能,目前提供了改变声音音调的变音功能,具体调用如下:
audioFrame.openSoundEffects();
audioFrame.setMixerPitch(5);
openSoundEffects
为开启音频特效的方法,与之对应的有关闭音频特效的closeSoundEffects
方法。
setMixerPitch
为设置音调高低的方法,参数区间在-12到+12之间,值越大音调越高。
####背景音混音功能
VisioninSDK提供了音频输入与背景音的混音功能,具体流程如下:
用setMP3Accompany
方法选择并解码Mp3格式背景音文件,解码为耗时操作,如需在UI显示进度需要提前进行如下操作
*通过setmHandler
设置接收进度消息的Handler
*通过setProgressDialog
方法设置progressDialog和DecodeProgressListener
注意:setmHandler
方法需要在setMP3Accompany
之前被调用;setMP3Accompany
的两个String参数分别为背景音文件的路径和解码后的PCM格式文件的保存路径。
背景音文件解码完毕后,可以调用startAccompany
来开始播放背景音并做混音处理,并通过stopAccompany
方法来关闭背景音与混音。
其他具体操作与参数设置详见Demo。
####设置是否在录音时播放
通过setPlayWhileEncoding
设置是否在录音时播放录音。
####切换输出流编码格式
通过setOutputFormat
设置输出流的编码格式,目前提供AAC和PCM两种编码格式。VSAudioFrame类中以静态变量的形式提供了可用的参数,切换AAC流的参数为VSAudioFrame.OUTPUT_FORMAT_AAC;
切换PCM流的参数为VSAudioFrame.OUTPUT_FORMAT_PCM。
注意:设置应该在start方法前完成。
####获取音频格式信息
通过getSAMPLERATE
可以获取音频采样率
通过getFORMAT_BIT
可以获取音频采样大小
通过getCHANNELS
可以获取声道数
####获取输出的AAC格式音频流
通过调用VSSoundBytesCallback
接口可以获取到转码后的AAC格式音频流。
以下是一段获取AAC流,并作为写入AAC文件的示例代码:
audioFrame.setSoundBytesCallback(new VSSoundBytesCallback() {
@Override
public void outputBytes(byte[] bytes) {
if (bytes != null) {
try {
[your DataOutputStream].write(bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
####获取输出的PCM格式音频流
同获取AAC格式音频流 参数可调节