VisioninSDK是一个移动端的跨平台实时视频处理库,提供了视频磨皮美颜、视频滤镜、人脸实时关键点追踪、人脸实时整形(瘦脸、大眼睛等)、人脸动态贴纸等功能的库。
保证包含SDK库文件
#import "Visionin.h"
[Visionin initialize:@"xxx"];
- 其中xxx为应用的证书,应用证书的获取请在开发者中心新建应用
VSVideoFrame* videoFrame = [[VSVideoFrame alloc] initWithPosition:AVCaptureDevicePositionFront pixelFormat:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange view:self.view];
- Position:表示为前摄像头或者后摄像头,AVCaptureDevicePositionFront或者AVCaptureDevicePositionBack
- pixelFormat:输入视频帧格式,如果视频帧从摄像头来,则此处和摄像头的kCVPixelBufferPixelFormatTypeKey参数一致。目前支持格式类型:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange、kCVPixelFormatType_32BGRA、kCVPixelFormatType_32RGBA,注意:iphone摄像头没有kCVPixelFormatType_32RGBA,该格式用于从视频文件解析出的视频帧
- view:处理后视频预览窗口
[videoFrame startVideoFrame];
[videoFrame processVideoSampleBuffer:sampleBuffer];
如果关闭摄像头,需要调用stopVideoFrame函数。
- startVideoFrame与stopVideoFrame必须成对调用,否则会破坏状态机导致processVideoSampleBuffer函数不可用;
前后摄像头切换时候,需要设置cameraPosition
VisioninSDK默认为竖屏模式,屏幕旋转或者横屏等模式下,需要设置outputImageOrientation,支持以下屏幕方向参数:
- UIInterfaceOrientationMaskLandscapeRight
- UIInterfaceOrientationMaskLandscapeLeft
- UIInterfaceOrientationMaskPortrait
- UIInterfaceOrientationMaskPortraitUpsideDown
注意:此处方向为StatusBar方向,非Device方向,获取StatusBar方向:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]
VisioninSDK支持视频流、预览的镜像设置,可自由组合(不支持视频流镜像、预览非镜像的组合):
- mirrorFrontFacingCamera: 前置摄像头下视频流是否镜像
- mirrorBackFacingCamera: 后置摄像头下视频流是否镜像
- mirrorFrontPreview: 前置摄像头下预览是否镜像
- mirrorBackPreview:后置摄像头下是否镜像
磨皮:
[videoFrame setSmoothLevel:level];
- level的值介于0-1.0之间,为0时不磨皮,默认值0.5
美白:
[videoFrame setBrightenLevel:level];
- level的值介于0-1.0之间,为0时不美白,默认值0.5
如需关闭美颜,只要把所有参数设置为0即可
VisioninSDk支持多种数据格式的获取,包括BGRA、YUV420P、NV21、NV12格式;
- BGRA支持CVPixelBufferRef数据,其余格式只支持获取byte类型
- 要获取某种类型数据输出,需要设置对应的Block变量
- 不同的数据获取互斥,只能同时获取一种格式
下面以获取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];
目前支持的滤镜有:
- VS_GAUSSIAN_BLUR_FILTER 高斯模糊
- VS_MEDIAN_BLUR_FILTER 中值滤波,同样可实现模糊效果
- VS_FROSTED_BLUR_FILTER 类似毛玻璃的模糊效果
- VS_SATURATION_FILTER 饱和度
- 其他调色相关的滤镜:origin, nature, clean, vivid, fresh, sweety, rosy, lolita, sunset, grass, coral, pink,urban, crisp, valencia, beach, vintage, rococo, walden, brannan, inkwell
VisioninSDK提供了一个简单的摄像头,可以不使用VSVideoFrame直接使用VSVideoCamera,VSVideoCamera支持所有VSVideoFrame的功能
VSVideoCamera* videoCamera = [[VSVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh position:AVCaptureDevicePositionFront view:self.view];
- SessionPreset:分辨率,如AVCaptureSessionPresetHigh、AVCaptureSessionPreset1280x720或者AVCaptureSessionPreset640x480
- position:前摄像头或者后摄像头,AVCaptureDevicePositionFront或者AVCaptureDevicePositionBack
- view:视频预览窗口
如果需要从VSVideoCamera获取没有经过美颜的视频流,需要实现VSCameraSampleDelegate协议
VSCameraSampleDelegate:
- willOutputAudioSampleBuffer: 未经处理的音频流
- willOutputVideoSampleBuffer: 未经处理的视频流
调用VSVideoCamera的setSampleDelegate方法
[videoCamera startCameraCapture];
VisioninSDK支持国际通用的68个关键点的实时追踪,各个坐标序号如下所示:
开启人脸关键点的追踪的功能只需要调用VSFacer函数的startFaceTracking
VSFacer* facer = [VSFacer shareInstance];
[facer startFaceTracking];
获取关键点使用VSFacer的getFacerMarks接口
float* markers = [[VSFacer shareInstance] getFacerMarks];
- 如果此时没有人脸,markers返回nil;
- 如果有人脸,则markers是一个68*2个元素的数组,markers[0]和marker[1]是第一个关键点的x坐标和y坐标,依次类推
- 返回的人脸坐标为像素坐标,不是归一化坐标
[[VSFacer shareInstance] stopFaceTracking];
如果不再使用该功能,请及时调用此接口关闭
注意: 调用此接口可以停止整形功能,但是不能停止贴纸道具
[[VSFacer shareInstance] startShaper];
整形依赖人脸关键点追踪,如果没有开启人脸情况启动整形,则会自动开启人脸追踪
[[VSFacer shareInstance] setShapping:xxx strength:xxx];
整形强度0-1,目前支持的整形部位有:
- 大眼睛: SHAPER_CMD_EYE
- 瘦脸:SHAPER_CMD_FACE
- 瘦下巴:SHAPER_CMD_CHIN
- 瘦颧骨:SAHPER_CMD_CHEEK
[[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);
注意:
- 第一个参数为Context类型,需要注意context的生命周期,如果context销毁可能引起VisioninSDK的错误,最好的方法是在Application中调用,或者使用getApplicationContext()
- lisence与IOS sdk的lisence使用同一个即可,注意在__开发者中心中设置android的包名__
VSVideoFrame是VisioninSDK所有功能的入口类,依赖Surface创建Opengl Context。
- 一般使用SurfaceView来提供Surface,并将处理后的数据绘制到SurfaceView上。
- 使用surfaceTexture()方法新建SurfaceTexture
- 设置Camera的PreviewTexture,然后开始摄像头的预览
- VSVideoFrame的创建一定要放在SurfaceHolder回调方法中 ,不可以获取SurfaceView对象后直接用
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
方法设置摄像头
- 前摄像头:VSVideoFrame.CAMERA_FACING_FRONT
- 后摄像头:VSVideoFrame.CAMERA_FACING_BACK
VisioninSDK默认为竖屏模式,屏幕旋转或者横屏等模式下,需要调用setOutputImageOritation
方法设置方向,支持以下屏幕方向参数:
- 竖屏:Configuration.ORIENTATION_PORTRAIT
- 横屏:Configuration.ORIENTATION_LANDSCAPE
VisioninSDK支持视频流、预览的镜像设置,可自由组合(不支持视频流镜像、预览非镜像的组合):
setMirrorFrontVideo
方法: 前置摄像头下视频流是否镜像setMirrorBackVideo
: 后置摄像头下视频流是否镜像setMirrorFrontPreview
: 前置摄像头下预览是否镜像setMirrorBackPreview
:后置摄像头下是否镜像
磨皮:
videoFrame.setSmoothLevel(level);
- level的值介于0-1.0之间,为0时不磨皮,默认值0.5
美白:
videoFrame.setBrightenLevel(level);
- level的值介于0-1.0之间,为0时不美白,默认值0.5
如需关闭美颜,只要把所有参数设置为0即可
如果您要自己压缩bitmap并预览,则可以把VisioninSDK提供的预览关闭,方法为:
videoFrame.removeOutputView();
如果要再重新使用VisisioninSDK的预览,方法为:
videoFrame.setOutputView();
###1.3 获取经过美颜后的视频流
VisioninSDk支持多种数据格式的获取,包括RGBA、YUV420P、NV21、NV12格式;
- 要获取某种类型数据输出,需要设置对应的Callback参数
- 不同的数据获取互斥,只能同时获取一种格式
下面以获取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);
- 如果此时没有人脸,markers返回null;
- getFacerMarks的参数代表第几个人脸,0代表第一个人脸,依次类推,最多可支持8个人脸
- 如果有人脸,则markers是一个68*2个元素的数组,markers[0]和marker[1]是第一个关键点的x坐标和y坐标,依次类推
- 返回的人脸坐标为像素坐标,不是归一化坐标
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格式音频流 参数可调节