美摄SDK For Android
3.14.0
|
美摄SDK致力于解决移动端视频开发的技术门槛,使仅有android界面开发经验的程序员,都可以开发出性能优异、渲染效果丰富的的视频录制、编辑功能。我们的优势体现在:
美摄SDK的所有接口必须在UI线程调用,否则可能出现无法预料的错误。只有NvsVideoFrameRetriever类的getFrameAtTime()方法除外。
运行环境如下:android studio(必须),android4.4以上版本
目前,美摄SDK安卓版支持armeabi-v7a和arm64指令集的包。
使用时在gradle命令行加入
defaultConfig {
ndk {
abiFilters "armeabi-v7a",”arm64-v8a”
}
}
最后,如何查看程序包含有.so呢? 最简单的方法是使用解压工具将apk后缀修改为.zip,直接查看libs里是否含有.so。
如果没有Meishe SDK库,请从美摄官网:https://www.meishesdk.com/downloads下载最新SDK接入版本。导入库文件的方式有两种:
方式一: 直接复制。
创建工程后,将NvStreamingSdk_Android_***_***\lib\android_jar路径下jar包,复制到工程的libs路径下。同时在工程的jniLibs文件夹下(没有就创建同名文件夹),创建两个文件夹,armeabi-v7和arm64-v8a。
将NvStreamingSdk_Android_***_***\lib\android_armv7里的所有.so文件,复制到前面创建的armeabi-v7a文件夹,同理将android_arm64文件夹下的内容复制到arm64-v8a文件夹下。
方式二:通过配置gradle命令行方式导入库。
美摄SDK的samples都是通过配置命令行的方式导入库文件。
录制的相关接口是在NvsStreamingContext类里,包括采集预览(startCapturePreview()),录制(startRecording()),添加视频采集特效(appendBuiltinCaptureVideoFx())等。强调:美摄SDK所有的类都是以“Nvs”开头。
视频录制时需要注意以下两点:
如果查看录制视频的具体功能实现,建议参考samples里的SdkDemo的视频拍摄模块
录制前,录制的Activity需要实现NvsStreamingContext类的CaptureDeviceCallback接口并重写接口里的所有方法。实现代码如下:
//采集设备回调接口 public class MainActivity extends AppCompatActivity implements NvsStreamingContext.CaptureDeviceCallback { ......//请自行重写所有方法 }
NvsStreamingContext是美摄SDK的流媒体上下文类,可视作整个SDK框架的入口。在开始使用美摄SDK的时候,需要先初始化NvsStreamingContext类,然后在其它Activity里使用时 获取NvsStreamingContext的对象,NvsStreamingContext是单例类。在不再使用美摄SDK或者程序退出前销毁NvsStreamingContext类的对象,请务必保证不要中途销毁NvsStreamingContext 类的对象!!!NvsStreamingContext类init()方法的第二个参数为授权文件的路径,没有授权文件时给空字符串。
NvsStreamingContext初始化代码如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); m_streamingContext = NvsStreamingContext.init(this, null);//初始化Streaming Context setContentView(R.layout.activity_main); }
NvsStreamingContext销毁代码如下:
@Override protected void onDestroy() { //streamingContext销毁 m_streamingContext = null; NvsStreamingContext.close(); }
录制界面的xml文件里需要使用NvsLiveWindow控件,NvsLiveWindow是用来录制预览或者编辑预览的。xml文件设置如下:
<com.meicam.sdk.NvsLiveWindow android:layout_height="match_parent" android:id="@+id/liveWindow" android:layout_width="match_parent" />
NvsLiveWindow的宽高比应该是1:1,4:3,16:9,9:16等,最好与采集预览startCapturePreview()的参数aspectRatio值保持一致。否则,预览的图像是录制完的视频被裁剪后的图像。
NvsLiveWindow的填充模式:
public class NvsLiveWindow extends SurfaceView implements SurfaceHolder.Callback { //图像按比例均匀填充,必要时进行裁剪(默认模式) public static final int FILLMODE_PRESERVEASPECTCROP = 0; //图像均匀地缩放来适合窗口,没有裁剪 public static final int FILLMODE_PRESERVEASPECTFIT = 1; //图像被缩放来适合窗口 public static final int FILLMODE_STRETCH = 2; }
对于三种填充模式,图片展示如下:
另一种预览方式是通过与SurfaceTexture连接,在SurfaceView上预览显示。对应接口如下:
//连接时间线和一个SurfaceTexture对象,该时间线的渲染结果将会输出到这个SurfaceTexture对象上面 public boolean connectTimelineWithSurfaceTexture(NvsTimeline timeline, SurfaceTexture outputSurfaceTexture) //连接时间线和一个SurfaceTexture对象并设置代理级别,该时间线的渲染结果将会输出到这个SurfaceTexture对象上面 public boolean connectTimelineWithSurfaceTexture(NvsTimeline timeline, SurfaceTexture outputSurfaceTexture, NvsRational proxyScale)
//给Streaming Context设置采集设备回调接口(必须有) m_streamingContext.setCaptureDeviceCallback(this); if (m_streamingContext.getCaptureDeviceCount() == 0) return; // 将采集预览输出连接到NvsLiveWindow控件(必须有) if (!m_streamingContext.connectCapturePreviewWithLiveWindow(m_liveWindow)) { Log.e(TAG, "Failed to connect capture preview with livewindow!"); return; } //采集设备数量判定,如果采集设备是1,不能开启前置摄像头。 if (m_streamingContext.getCaptureDeviceCount() > 1) m_switchBackFacing.setEnabled(true); if (m_streamingContext.isCaptureDeviceBackFacing(0))//判断是否为后置采集设备 { ..... }
在启动视频录制之前,要进行视频采集预览。
//启动采集预览 m_streamingContext.startCapturePreview(m_currentDeviceIndex, NvsStreamingContext.VIDEO_CAPTURE_RESOLUTION_GRADE_SUPER_HIGH, 0, m_aspectRatio);
采集预览时,可以在预览画面上看到添加的美颜和滤镜。如果开启带特效录制,录制的文件则会带有美颜和滤镜。如果不开启,则录制的视频文件没有美颜和滤镜效果, 则可以在后续的编辑功能中,再添加美颜和滤镜。带特效录制,则必须将startCapturePreview()的flags参数值设为NvsStreamingContext.STREAMING_ENGINE_CAPTURE_FLAG_DONT_USE_SYSTEM_RECORDER,否则设为0。
更多信息请参考:https://www.meishesdk.com/android/doc_ch/html/content/videoRecorderMode_8md.html
录制输出文件.mov 或者.mp4。startRecording()开启录制,stopRecording()停止录制。startRecording()的参数outputFilePath是录制视频文件的路径。
m_streamingContext.startRecording(file.getAbsolutePath()); m_streamingContext.stopRecording();
设置闪光灯是否开启:
m_streamingContext.toggleFlash(true);
自动聚焦:
m_streamingContext.startAutoFocus(new RectF(50,50,100,100));
设置曝光补偿:
m_streamingContext.setExposureCompensation(40);
设置缩放:
m_streamingContext.setZoom(0.8);
添加美颜特效后,在预览窗口就可以看到美颜效果。录制视频时,用户需要根据手机性能任意选择带美颜录制或者不带美颜录制。 美颜特效可设置磨皮、美白,红润,基础美颜效果,基础美颜效果的程度,锐化。具体美颜效果可以参考SdkDemo的“视频拍摄”模块。
代码如下:
NvsCaptureVideoFx beautyFx = m_streamingContext.appendBeautyCaptureVideoFx();//添加美颜采集特效 beautyFx.setFloatVal("Strength", 0.5);//设置美颜磨皮值 beautyFx.setFloatVal("Whitening", 0.5);//设置美白强度值 beautyFx.setFloatVal("Reddening", 0.5);//设置红润强度值 beautyFx.setBooleanVal("Default Beauty Enabled", true);//设置基础美颜的开关 beautyFx.setBooleanVal("Default Sharpen Enabled", true);//设置锐化的开关 beautyFx.setFloatVal("Default Intensity", 0.5);//设置基础美颜的强度
采集特效分为两种,内建采集特效和扩展采集特效,扩展采集特效即通过资源包安装而得到的采集特效。
获取内建采集特效名称可以参考列表:https://www.meishesdk.com/android/doc_ch/html/content/FxNameList_8md.html。
添加与移除特效:
m_streamingContext.appendBuiltinCaptureVideoFx(fxName); m_streamingContext.removeAllCaptureVideoFx();
使用扩展采集特效,首先安装资源包,获取资源包ID值,然后添加扩展采集特效。例如,此处采用同步方式安装资源包,如果资源包尺寸太大或者根据需要可使用异步安装方式。 String package1Path = "assets:/7FFCF99A-5336-4464-BACD-9D32D5D2DC5E.videofx"; m_fxPackageId = new StringBuilder(); int error = m_streamingContext.getAssetPackageManager().installAssetPackage(package1Path, null, NvsAssetPackageManager.ASSET_PACKAGE_TYPE_VIDEOFX, true, m_fxPackageId); if (error != NvsAssetPackageManager.ASSET_PACKAGE_MANAGER_ERROR_NO_ERROR && error != NvsAssetPackageManager.ASSET_PACKAGE_MANAGER_ERROR_ALREADY_INSTALLED) { Log.e(TAG, "Failed to install asset package!"); }
//添加扩展采集特效 m_streamingContext.appendPackagedCaptureVideoFx(m_fxPackageId.toString());
实现视频编辑的一般步骤:
//NvsStreamingContext初始化 m_streamingContext = NvsStreamingContext.getInstance(); // m_streamingContext对象
创建timeline对于编辑是非常关键的,timeline的分辨率决定了生成视频文件的最大分辨率(尺寸)。请将timeline的分辨率和NvsLiveWindow的宽高比适配一致。
NvsVideoResolution videoEditRes = new NvsVideoResolution(); videoEditRes.imageWidth = 1280; /*视频分辨率的宽*/ videoEditRes.imageHeight = 720; /*视频分辨率的高*/ videoEditRes.imagePAR = new NvsRational(1, 1); /*像素比,设为1:1*/ NvsRational videoFps = new NvsRational(25, 1); /*帧速率,可以设25或30,也可设为30 */ NvsAudioResolution audioEditRes = new NvsAudioResolution(); audioEditRes.sampleRate = 44100; /*音频采样率,可以是44100,或者48000*/ audioEditRes.channelCount = 2; /*音频通道数,一般是2*/ /*创建时间线*/ m_timeline = m_streamingContext.createTimeline(videoEditRes, videoFps, audioEditRes); //将timeline连接到LiveWindow控件 m_streamingContext.connectTimelineWithLiveWindow(m_timeline,m_liveWindow); m_streamingContext.setCompileCallback(this);//设置生成回调接口 m_streamingContext.setPlaybackCallback(this);//设置播放回调接口
一般情况下创建一条视频轨道,然后往轨道上添加图片或者视频素材。添加到轨道上的素材,我们称它为片段(clip)。图片和视频素材都是通过文件路径添加到轨道上的。 请注意:如果图片素材尺寸过大,需要降低图片尺寸,降低尺寸后的图片和创建timeline的分辨率的尺寸大小匹配最好。
添加视频轨道: m_videoTrack = m_timeline.appendVideoTrack();
添加音频轨道: m_audioTrack = m_timeline.appendAudioTrack();
添加片段: for(int i = 0; i < pathList.size(); i++) { NvsVideoClip clip = m_videoTrack.appendClip(pathList.get(i)); }
对于播放与定位预览接口,其参数videoSizeMode建议设置为NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_LIVEWINDOW_SIZE。若无特殊需求,设为NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_FULLSIZE的模式会影响性能。 preload是预加载,设为true。注意:美摄SDK的时间单位是微秒,1/1000000秒。
视频播放,playbackTimeline()的参数endTime,值可以是_timeline.duration或者-1。
m_streamingContext.playbackTimeline(m_timeline, m_streamingContext.getTimelineCurrentPosition(m_timeline), -1, NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_LIVEWINDOW_SIZE, true, 0);
视频定位预览:
m_streamingContext.seekTimeline(m_timeline, 0, NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_LIVEWINDOW_SIZE, 0);
改变片段的入出点,裁剪片段。
NvsVideoClip clip = m_videoTrack.getClipByIndex(0); clip.changeTrimInPoint((long)trim_in, true); clip.changeTrimOutPoint((long)trim_out, true);
移除片段:
m_videoTrack.removeClip(0, false);
轨道上的片段可以互换位置,moveClip()的参数clipIndex和destClipIndex分别代表互换的两个素材的位置索引。
m_videoTrack.moveClip(0,3);
NvsVideoTrack类提供appendClip(String filePath, long trimIn, long trimOut)可以根据需要自由设定图片时长。 filePath是图片素材的路径,trimIn设置0,trimOut设置为8000000,则图片显示为8秒。
m_videoTrack.appendClip(pathList.get(i),0,8000000);
如果通过appendClip(String filePath)添加图片,则图片默认显示时长是4秒。
创建的时间线,添加的视频轨道和音频轨道,如果当前不再需要,则要进行移除。操作如下:
移除时间线:
m_streamingContext.removeTimeline(m_timeline);
移除视频轨道:
m_timeline.removeVideoTrack(0);
移除音频轨道:
m_timeline.removeAudioTrack(0);
给视频添加音乐是通过音频轨道添加音频片段实现的。创建时间线后,通过appendAudioTrack()添加音频轨道,然后把音乐文件以音频片段的形式添加到音频轨道上即可。可以添加多段音乐,音乐会连续播放。
m_audioTrack = m_timeline.appendAudioTrack(); m_audioTrack.appendClip(pathList.get(i));
音乐裁剪与视频裁剪是一样的,也是通过设置入出点的方式进行裁剪。
NvsAudioClip clip = m_audioTrack.getClipByIndex(0); clip.changeTrimInPoint((long)trim_in, true); clip.changeTrimOutPoint((long)trim_out, true);
添加,删除以及获取字幕都是在时间线(timeline)上进行执行的,可以参考SdkDemo示例的字幕编辑模块。
添加字幕,可设置字幕显示的时长。
NvsTimelineCaption m_timelineCapion = m_timeline.addCaption("Meishe SDK", 0, m_timeline.getDuration(), null);
移除字幕,返回下一个时间线字幕对象。如果没有下一个字幕,则返回null。
NvsTimelineCaption nextCaption = m_timeline.removeCaption(m_timelineCapion);
有多种方式获取字幕:
//获得时间线上的第一个字幕 NvsTimelineCaption firstCaption = m_timeline.getFirstCaption(); //获得时间线上的最后一个字幕 NvsTimelineCaption lastCaption = m_timeline.getLastCaption(); //获得时间线上的当前字幕的前一个字幕 NvsTimelineCaption prevCaption = m_timeline.getPrevCaption(currentCaption); //获得时间线上的当前字幕的后一个字幕 NvsTimelineCaption lastCaption = m_timeline.getNextCaption(currentCaption);
根据时间线上的位置获得字幕,返回保存当前位置字幕的List集合。获取的字幕列表排序规则如下:
1.添加时字幕入点不同,按入点的先后顺序排列;
2.添加时字幕入点相同,按添加字幕的先后顺序排列。
List<NvsTimelineCaption> cpationList = m_timeline.getCaptionsByTimelinePosition(1000000);
修改字幕属性可通过NvsTimelineCaption类的方法实现。获取字幕后,可设置字幕文本,颜色,加粗,斜体,描边等。
以修改字幕文本为例:
currentCaption.setText("Meishe SDK");
如果是全景图字幕,还可以设置字幕中心点的极角,字幕中心点的方位角等。以设置字幕中心点的极角为例:
currentCaption.setCenterPolarAngle(1.2);
获取字幕后,可以修改字幕在时间线上的入点,出点以及偏移值。
//改变入点 currentCaption.changeInPoint(1000000); //改变出点 currentCaption.changeOutPoint(5000000); //改变显示位置(入点和出点同时偏移offset值) currentCaption.movePosition(1000000);
添加,删除以及获取动画贴纸也是在时间线(timeline)上进行执行的,可以参考SdkDemo示例的贴纸模块。
添加动画贴纸:
m_timeline.addAnimatedSticker(0, m_timeline.getDuration(), m_stickerId.toString());
移除动画贴纸,返回当前贴纸的下一个贴纸。如果没有下一下贴纸,则返回null。
NvsTimelineAnimatedSticker nextSticker = m_timeline.removeAnimatedSticker(currentSticker);
有多种方式获取时间线上添加的动画贴纸。
//获取时间线上第一个动画贴纸 NvsTimelineAnimatedSticker firstSticker = m_timeline.getFirstAnimatedSticker(); //获取时间线上最后一个动画贴纸 NvsTimelineAnimatedSticker lastSticker = m_timeline.getLastAnimatedSticker(); //获取时间线当前动画贴纸的前一个动画贴纸 NvsTimelineAnimatedSticker prevSticker = m_timeline.getPrevAnimatedSticker(currentSticker); //获取时间线当前动画贴纸的后一个动画贴纸 NvsTimelineAnimatedSticker nextSticker = m_timeline.getNextAnimatedSticker(currentSticker);
根据时间线上的位置获得动画贴纸,返回保存当前位置动画贴纸对象的List集合。 获取的动画贴纸列表排序规则如下: 1.添加时入点不同,按入点的先后顺序排列; 2.添加时入点相同,按添加动画贴纸的先后顺序排列。
List<NvsTimelineAnimatedSticker> stickerList = m_timeline.getAnimatedStickersByTimelinePosition(1000000);
修改贴纸属性可通过NvsTimelineAnimatedSticker类的方法实现。获取贴纸后,可设置缩放值,水平翻转,旋转角度,平移等。
以修改贴纸缩放为例:
currentSticker.setScale(1.2);
如果是全景图动画贴纸,则还可以设置贴纸中心点的极角,中心点的方位角等。以设置中心点的极角为例:
currentSticker.setCenterPolarAngle(1.2);
获取贴纸后,可以修改动画贴纸在时间线上的入点,出点以及偏移值。
//改变入点 [currentSticker changeInPoint:1000000]; //改变出点 [currentSticker changeOutPoint:5000000]; //改变显示位置(入点和出点同时偏移offset值) [currentSticker movePosition:1000000];
编辑视频时,如果需要运用主题,则可通过时间线(timeline)实现添加,移除。
运用主题: m_timeline.applyTheme(m_themeId.toString());
移除主题:
m_timeline.removeCurrentTheme();
获取当前主题包Id:
m_timeline.getCurrentThemeId();
运用主题后,可以设置主题片头,片尾,主题音乐音量等,以设置主题片头为例:
m_timeline.setThemeTitleCaptionText("Meishe SDK");
转场包括视频转场和音频转场。视频转场是在视频轨道上设置的,音频转场是在音频轨道上设置的。
视频转场包括内嵌式转场和包裹式转场。设置视频内嵌转场:
m_videoTrack.setBuiltinTransition(0,transitionName);
视频包裹式转场:
m_videoTrack.setPackagedTransition(1,m_transitionId.toString());
同样地,音频转场同视频转场是相同用法,用户可参照使用。
在视频后续编辑中,经常会使用到几种特效,分别是视频特效(NvsVideoFx),音频特效(NvsAudioFx),时间线视频特效(NvsTimelineVideoFx)。
视频特效是使用在视频片段上的,每个视频片段可以添加若干个视频特效。视频特效包括内嵌视频特效,包裹视频特效,美颜特效。
添加内嵌视频特效:
videoClip.appendBuiltinFx(fxName);
添加包裹视频特效:
videoClip.appendPackagedFx(m_fxPackageId.toString());
添加美颜特效:
videoClip.appendBeautyFx();
移除视频特效包括移除指定索引值特效和移除所有视频特。
移除指定索引值的特效:
videoClip.removeFx(0);
移除所有视频特效: videoClip.removeAllFx();
音频特效是使用在音频片段上的,每个音频片段可以添加若干个音频特效。
添加音频特效:
audioClip.appendFx(fxName);
移除指定索引的音频特效:
audioClip.removeFx(0);
时间线视频特效是使用在时间线上的一种特效,包含内嵌特效和包裹特效。时间线上可以添加若干个时间线视频特效。
添加时间线特效:
m_timeline.addBuiltinTimelineVideoFx(1000000,5000000,fxName); m_timeline.addPackagedTimelineVideoFx(1000000,5000000,fxPackageId);
有多种方法获取时间线特效。
//获取时间线上第一个时间线视频特效 NvsTimelineVideoFx firstTimelineFx = m_timeline.getFirstTimelineVideoFx(); //获取时间线上最后一个时间线视频特效 NvsTimelineVideoFx lastTimelineFx = m_timeline.getLastTimelineVideoFx(); //获取时间线上某个时间线视频特效的前一个时间线视频特效 NvsTimelineVideoFx prevTimelineFx = m_timeline.getPrevTimelineVideoFx(currentTimelineFx); //获取时间线上某个时间线视频特效的下一个时间线视频特效 NvsTimelineVideoFx nextTimelineFx = m_timeline.getNextTimelineVideoFx(currentTimelineFx);
根据时间线上的位置获得时间线视频特效,返回当前位置时间线视频特效对象的数组。
获取的时间线视频特效数组排序规则如下:
1.添加时入点不同,按入点的先后顺序排列;
2.添加时入点相同,按添加时间线视频特效的先后顺序排列。
List<NvsTimelineVideoFx> timelineFxArray = m_timeline.getTimelineVideoFxByTimelinePosition(2000000);
获取时间线特效后,可以修改时间线特效在时间线上的入点,出点以及偏移值。
//改变入点 currentTimelineFx.changeInPoint(1000000); //改变出点 currentTimelineFx.changeOutPoint(5000000); //改变显示位置(入点和出点同时偏移offset值) currentTimelineFx.movePosition(1000000);
美摄SDK使用compileTimeline()用于将时间线上的片段生成输出一个新的视频。
生成视频:
m_streamingContext.compileTimeline(m_timeline, 0, m_timeline.getDuration(), m_compilePath, NvsStreamingContext.COMPILE_VIDEO_RESOLUTION_GRADE_720, NvsStreamingContext.COMPILE_BITRATE_GRADE_HIGH, 0);
美摄SDK提供了丰富的素材库,包括动画贴纸,主题,字幕样式,转场等。素材包可以从网络上下载,或者由美摄SDK项目组提供,用户可以根据需要选择使用这些素材包。美摄SDK通过NvsAssetPackageManager类对这些素材包进行管理,可以安装,升级,卸载,获取素材包的状态,版本号等。
素材包安装:
//此处采用同步安装方式,如果包裹过大可采用异步方式 int error = m_streamingContext.getAssetPackageManager().installAssetPackage(stickerPackagePath, null, NvsAssetPackageManager.ASSET_PACKAGE_TYPE_ANIMATEDSTICKER, true, m_stickerId);
素材包升级:
//此处采用同步升级方式,如果包裹过大可采用异步方式 int error = m_streamingContext.getAssetPackageManager().upgradeAssetPackage(stickerPackagePath, null, NvsAssetPackageManager.ASSET_PACKAGE_TYPE_ANIMATEDSTICKER, true, m_stickerId);
素材包卸载:
int error = m_streamingContext.getAssetPackageManager().uninstallAssetPackage(m_stickerId,NvsAssetPackageManager.ASSET_PACKAGE_TYPE_ANIMATEDSTICKER);
美摄SDK提供了很多回调接口,如果要查询采集设备状态,采集录制状态,视频播放状态,文件生成状态,资源包安装状态等,则必须在创建NvsStreamingContext对象后设置回调并实现对应的回调方法。
以视频播放回调为例:
m_streamingContext.setPlaybackCallback(this);
美摄SDK版本包括极速版,标准功能版,全功能PRO版,对于每个版本产品的功能点,请参考:https://www.meishesdk.com/editsdk,会有详细介绍。每个用户可根据个人需要选择使用,具体请联系美摄商务。