直播
进阶功能
更新时间: 2021/11/01 21:17:39
音视频推流操作
- 中断、恢复视频推流
- 中断、恢复音频推流
API原型
/**
* 暂停视频推流
*/
public void pauseVideoLiveStream()
/**
* 继续视频推流
*/
public void resumeVideoLiveStream()
/**
* 暂停音频推流
*/
public void pauseAudioLiveStream()
/**
* 继续音频推流
*/
public void resumeAudioLiveStream()
/**
* 程序切后台后继续视频编码,编码最后一帧图像
*/
public void backgroundVideoEncode()
/**
* 设置垫片(图片),支持以bitmap作为参数,用于替代当前推流内容
* @param bitmap 垫片图,占位图,如果传`null`同`backgroundVideoEncode()`方法
*/
public void backgroundVideoEncode(Bitmap bitmap)
/**
* 程序切回前台后恢复视频编码
*/
public void resumeVideoEncode()
/**
* 程序切后台后继续音频编码,编码静音帧
*/
public void backgroundAudioEncode()
/**
* 程序切回前台后恢复音频编码
*/
public void resumeAudioEncode()
参数说明
无
示例
@Override
protected void onPause(){
Log.i(TAG,"Activity onPause");
if(mLSMediaCapture != null) {
if(!m_tryToStopLivestreaming && m_liveStreamingOn)
{
if(mLiveStreamingPara.getStreamType() != AUDIO) {
//推最后一帧图像
mLSMediaCapture.backgroundVideoEncode();
}
else {
//推静音帧
mLSMediaCapture.backgroundAudioEncode();
}
}
}
super.onPause();
}
@Override
protected void onResume(){
Log.i(TAG,"Activity onResume");
super.onResume();
if(mLSMediaCapture != null && m_liveStreamingOn) {
if(mLiveStreamingPara.getStreamType() != AUDIO) {
//关闭推流固定图像,正常推流
mLSMediaCapture.resumeVideoEncode();
}
else {
//关闭推流静音帧
mLSMediaCapture.resumeAudioEncode();
}
}
}
特殊说明
这里的暂停与切后台的差别是,暂停不会关闭摄像头只是不继续推流本地预览还在,切后台则会释放摄像头资源并发送最后一帧画面。同时暂停音频流是发送静音帧
伴音相关操作
- 开始、结束、中断、恢复伴音文件;
API原型
/**
* 开始播放伴音文件
* @param musicURL 音频文件地址/文件名
* @param loop 是否循环播放
* @return 播放伴音文件成功或者失败
*/
public boolean startPlayMusic(String musicURL,boolean loop)
/**
* 结束播放伴音文件,释放播放文件
* @return 停止伴音成功或者失败
*/
public boolean stopPlayMusic()
/**
* 暂停播放伴音文件
*
* @return 暂停播放伴音文件成功或者失败
*/
public boolean pausePlayMusic()
/**
* 继续播放伴音文件
*
* @return 继续伴音成功或者失败
*/
public boolean resumePlayMusic()
参数说明
参数 | 类型 | 说明 |
---|---|---|
musicURL | String | 音频文件地址 |
loop | boolean | 伴音音频文件是否单曲循环 |
示例
//伴音开关的控制
if(audioMixMsg == 1)
{
if(mMixAudioFilePath.isEmpty())
return;
if(mLSMediaCapture != null) {
mLSMediaCapture.startPlayMusic(mMixAudioFilePath,false);
}
}
else if (audioMixMsg == 2)
{
if(mLSMediaCapture != null){
mLSMediaCapture.resumePlayMusic();
}
}
else if(audioMixMsg == 3)
{
if(mLSMediaCapture != null){
mLSMediaCapture.pausePlayMusic();
}
}
else if(audioMixMsg == 4)
{
if(mLSMediaCapture != null){
mLSMediaCapture.stopPlayMusic();
}
}
特殊说明
无
音视频数据操作
- SDK将摄像头或麦克风采集的原始音视频数据回调给用户,用户进行前处理后返还给SDK
- 用户自行进行音视频的采集,然后将采集的音视频数据用SDK进行编码发送
API原型
/**
* 设置摄像头采集原始数据回调
* @param callback 裸流回调接口(NV21格式)
*/
public void setCaptureRawDataCB(VideoCallback callback)
/**
* 设置麦克风采集原始数据回调
* @param callback 裸流回调接口(PCM格式)
*/
public void setAudioRawDataCB(lsAudioCaptureCallback callback)
/**
* 自定义采集的YUV数据(该接口不需要调用 {@link #startVideoPreview})
* @param buffer YUV数据
* @param videoWidth 视频原始宽
* @param videoHeight 视频原始高
* @param bitrate 编码码率
* @param framerate 编码帧率
*/
public void sendCustomYUVData(byte[] buffer,int videoWidth,int videoHeight,int bitrate, int framerate)
/**
* 自定义采集的PCM数据
* @param buffer PCM数据
*/
public void sendCustomPCMData(byte[] buffer)
参数说明
参数 | 类型 | 说明 |
---|---|---|
callback | VideoCallback | 视频回调函数 |
callback | lsAudioCaptureCallback | 音频回调函数 |
buffer | byte[] | 视频数据(YUV I420格式) |
videoWidth | int | 视频宽 |
videoHeight | int | 视频高 |
bitrate | int | 视频码率 |
framerate | int | 视频帧率 |
buffer | byte[] | 音频数据(PCM) |
示例
//********** 摄像头采集原始数据回调(非滤镜模式下开发者可以修改该数据,美颜增加滤镜等,推出的流便随之发生变化) *************//
if(mVideoCallback){
senseEffect();
mLSMediaCapture.setCaptureRawDataCB(new VideoCallback() {
@Override
/**
* 摄像头采集数据回调
* @param data 摄像头采集的原始数据(NV21格式)
* @param textureId 摄像头采集的纹理ID
* @param width 视频宽
* @param height 视频高
* @param orientation 相机采集角度
* @return 滤镜后的纹理ID (<=0 表示没有进行滤镜或是滤镜库返回的是buffer数据(NV21格式),sdk将会使用buffer数据进行后续处理)
*/
public int onVideoCapture(byte[] data, int textureId, int width, int height, int orientation) {
if(mSenseEffect != null){
//返回纹理方式
return mSenseEffect.effect(textureId,data,width,height,orientation);
}else {
//返回buffer方式
for(int j = 0; j< width * height /4;j++){
data[j] = 0; //data必须还是原来的NV21格式
}
return 0;
}
}
});
}
//********** 麦克风采集原始数据回调(开发者可以修改该数据,进行降噪、回音消除等,推出的流便随之发生变化) *************//
if(mAudioCallback){
mLSMediaCapture.setAudioRawDataCB(new lsAudioCaptureCallback() {
int i = 0;
@Override
public void onAudioCapture(byte[] data, int len) {
// 这里将data直接修改,SDK根据修改后的data数据直接推流
if(i % 10 == 0){
for(int j = 0; j< 1000;j++){
data[j] = 0;
}
}
i++;
}
});
}
//【示例代码】设置自定义视频采集类型(如果是自定义YUV则不需要调用startVideoPreview接口)
mLSMediaCapture.setSourceType(lsMediaCapture.SourceType.CustomAV);
//自定义输入默认是横屏,正的yuv数据
//【示例代码 customVideo】设置自定义视频采集逻辑 (自定义视频采集逻辑不要调用startPreview,也不用初始化surfaceView)
new Thread() { //视频采集线程
@Override
public void run() {
while (true) {
try {
if(!m_liveStreamingOn){
continue;
}
int width = 352;
int height = 288;
int fps = 20;
int bitrate = width * height * fps * 9 /100;
FileInputStream in = new FileInputStream(String.format(Locale.getDefault(),"/sdcard/dump_%d_%d.yuv",width,height));
int len = width * height * 3 / 2;
byte buffer[] = new byte[len];
int count;
while ((count = in.read(buffer)) != -1) {
if (len == count) {
mLSMediaCapture.sendCustomYUVData(buffer,width,height,bitrate,fps);
} else {
break;
}
sleep(50, 0);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
//【示例代码】结束
//【示例代码2】设置自定义音频采集逻辑(音频采样位宽必须是16)
new Thread() { //音频采集线程
@Override
public void run() {
while (true) {
try {
if(!m_liveStreamingOn){
continue;
}
FileInputStream in = new FileInputStream("/sdcard/dump.pcm");
int len = 2048;
byte buffer[] = new byte[len];
int count;
while ((count = in.read(buffer)) != -1) {
if (len == count) {
mLSMediaCapture.sendCustomPCMData(buffer);
} else {
break;
}
sleep(20, 0);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
//【示例代码】结束
特殊说明
无
直播前测速操作
- 开始测速
- 结束测速
API原型
/**
* 开始测速
* @param url 推流地址
* @param bytes 测速文件大小
*/
public void startSpeedCalc(String url, long bytes)
/**
* 停止测速
*/
public void stopSpeedCalc()
参数说明
参数 | 类型 | 说明 |
---|---|---|
url | String | 测速地址 |
bytes | long | 上传数据大小(仅限于文件上传类型,经测试,NTS2不能超过500k(含500k)),单位是字节,500k=500*1024,默认为499k(控制最大不超过10M |
示例
if(mLSMediaCapture != null) {
if (mSpeedCalcRunning) {
mLSMediaCapture.stopSpeedCalc();
mSpeedCalcRunning = false;
showToast("结束测速");
} else {
showToast("开始测速");
mLSMediaCapture.startSpeedCalc(mliveStreamingURL, 1024 * 500);
mSpeedCalcRunning = true;
}
}
特殊说明
无
摄像头操作
- 闪光灯
- 变焦
- 对焦
- 前后摄像头切换
- 分辨率切换
- 曝光度设置
API原型
/**
* 设置闪光灯开关
* @param onFlash 闪光灯开关
*/
public void setCameraFlashPara(boolean onFlash)
/**
* 获取当前视频缩放比例
* @return 当前视频缩放比例
*/
public int getCameraZoomValue()
/**
* 获取摄像头支持的最大视频缩放比例
* @return 摄像头支持的最大视频缩放比例
*/
public int getCameraMaxZoomValue()
/**
* 设置视频缩放相关参数
* @param zoomValue 缩放参数
*/
public void setCameraZoomPara(int zoomValue)
/**
* 手动对焦一次
*/
public void setCameraFocus()
/**
* 设置是否自动对焦(自动对焦默认开启)
* @param isAutoFocus true:开启自动对焦 false:关闭自动对焦
*/
public void setCameraAutoFocus(boolean isAutoFocus)
/**
* 切换前后摄像头
*/
public void switchCamera()
/**
* 获取摄像头曝光强度
* @return 摄像头曝光强度
*/
public int getExposureCompensation()
/**
* 获取摄像头支持的最小曝光强度
* @return 摄像头支持的最小曝光强度
*/
public int getMinExposureCompensation()
/**
* 获取摄像头支持的最大曝光强度
* @return 摄像头支持的最大曝光强度
*/
public int getMaxExposureCompensation()
/**
* 设置摄像头曝光强度
* @param value 摄像头曝光强度 (根据获取的最大和最小曝光度进行设置)
*/
public void setExposureCompensation(int value)
/**
* 切换分辨率
* @param quality 需要切换的模板
* @param scale_16x9 是否16:9
*/
public void changeCaptureFormat(VideoQuality quality,boolean scale_16x9)
/**
* 切换分辨率
* @param videoPara 自定义分辨率
*/
public void changeCaptureFormatEx(lsMediaCapture.VideoPara videoPara)
参数说明
参数 | 类型 | 说明 |
---|---|---|
onFlash | boolean | 打开或者关闭摄像头flash |
zoomValue | int | 摄像头变焦功能属性:拉伸值,[1,maxZoomScale] |
isAutoFocus | boolean | true:开启自动对焦 false:关闭自动对焦 |
value | int | 曝光度 [MinExposureCompensation,MaxExposureCompensation] |
quality | VideoQuality | MEDIUM:标清 480360,HIGH:高清 640480,SUPER:超清 960540,SUPER_HIGH:超高清 1280720 |
scale_16x9 | boolean | 是否按16:9宽高比例 |
VideoPara参数说明
参数 | 类型 | 说明 |
---|---|---|
setWidth | int | 设置编码宽 |
setHeight | int | 设置编码高 |
setFps | int | 设置编码帧率 |
setBitrate | int | 设置编码码率 |
示例
//闪光灯
if(mLSMediaCapture != null){
mFlashOn = !mFlashOn;
mLSMediaCapture.setCameraFlashPara(mFlashOn);
if(mFlashOn){
flashBtn.setImageResource(R.drawable.flashstop);
}else {
flashBtn.setImageResource(R.drawable.flashstart);
}
}
//曝光度
if(mLSMediaCapture != null){
int max = mLSMediaCapture.getMaxExposureCompensation();
mLSMediaCapture.setExposureCompensation((progress-50) * max /50);
}
//切换分辨率
private void changeFormat(){
int index = count % 4;
count ++ ;
boolean is16x9 = true;
switch (index){
case 0:
mLSMediaCapture.changeCaptureFormat(lsMediaCapture.VideoQuality.SUPER_HIGH,is16x9);
break;
case 1:
mLSMediaCapture.changeCaptureFormat(lsMediaCapture.VideoQuality.SUPER,is16x9);
break;
case 2:
mLSMediaCapture.changeCaptureFormat(lsMediaCapture.VideoQuality.HIGH,is16x9);
break;
case 3:
mLSMediaCapture.changeCaptureFormat(lsMediaCapture.VideoQuality.MEDIUM,is16x9);
break;
}
}
特殊说明
无
镜像相关操作
- 切换本地预览镜像
- 切换编码镜像(针对拉流端观众)
API原型
/**
* 直播过程中,开关本地预览镜像效果(只对前置摄像头有效)
* @param mirror 是否镜像
*/
public void setPreviewMirror(boolean mirror)
/**
* 直播过程中,开关视频推流镜像效果(只对前置摄像头有效)
* @param mirror 是否镜像(观众端)
*/
public void setVideoMirror(boolean mirror)
参数说明
无
示例
if(mLSMediaCapture != null){
mLSMediaCapture.setVideoMirror(R.id.live_config_push_mirror_on == checkedId);
}
if(mLSMediaCapture != null){
mLSMediaCapture.setWaterPreview(R.id.live_config_water_on == checkedId);
}
特殊说明
无
视频截图操作
- 获取视频截图
API原型
/**
* 直播过程中,开启截图
*/
public void enableScreenShot()
参数说明
无
示例
private void capture(){
if(mLSMediaCapture != null){
mLSMediaCapture.enableScreenShot();
}
}
case MSG_SCREENSHOT_FINISHED://视频截图完成后的消息反馈
{
getScreenShotByteBuffer((Bitmap) object);
break;
}
特殊说明
截图在SDK消息回调中返回,为bitmap类型
滤镜相关操作
- 设置滤镜类型
- 设置磨皮强度
- 设置美白强度
API原型
/**
* 设置滤镜类型
* @param filterType 滤镜类型
*/
public void setFilterType(VideoEffect.FilterType filterType)
/**
* 设置滤镜强度
* @param filterStrength 滤镜强度 (0 - 1)
*/
public void setFilterStrength(float filterStrength)
/**
* 设置磨皮强度
* @param level 磨皮强度 (0 - 5)
*/
public void setBeautyLevel(int level)
参数说明
滤镜类型VideoEffect.FilterType参数说明
参数 | 说明 | |
---|---|---|
none | 无滤镜 | |
clean | 干净 | |
fairytale | 童话 | |
nature | 自然 | |
healthy | 健康 | |
tender | 温柔 | |
whiten | 美白 | |
参数 | 类型 | 说明 |
:-------- | :-------- | :-------- |
filterStrength | float | 滤镜强度 (0 - 1) |
level | int | 磨皮强度 (0 - 5) |
示例
switch (v.getId()){
case R.id.brooklyn:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.brooklyn);
break;
case R.id.clean:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.clean);
break;
case R.id.nature:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.nature);
break;
case R.id.healthy:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.healthy);
break;
case R.id.pixar:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.pixar);
break;
case R.id.tender:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.tender);
break;
case R.id.whiten:
mLSMediaCapture.setFilterType(VideoEffect.FilterType.whiten);
break;
default:
break;
}
//滤镜强度
if(mLSMediaCapture != null){
float param;
param = (float)progress/100;
mLSMediaCapture.setFilterStrength(param);
}
//磨皮强度
if(mLSMediaCapture != null){
int param;
param = progress/20;
mLSMediaCapture.setBeautyLevel(param);
}
特殊说明
无
水印相关操作
- 添加涂鸦
- 开关本地预览涂鸦
- 添加静态视频水印
- 开关本地预览静态水印
- 添加动态视频水印
- 开关本地预览动态水印
API原型
/**
* 设置涂鸦
* @param bitmap 涂鸦图片
* @param x 水印水平坐标X,整个图像左上角为(0,0)点
* @param y 水印垂直坐标Y,整个图像左上角为(0,0)点
*/
public void setGraffitiPara(Bitmap bitmap, int x, int y)
/**
* 是否显示本地涂鸦
* @param preview true:本地显示 false: 本地不显示
*/
public void setGraffitiPreview(boolean preview)
/**
* 设置视频水印相关参数
* @param bitmap 水印文件
* @param rect 水印具体位置(上下左右中四个基本位置)
* @param x 距离 rect 的 x 坐标
* @param y 距离 rect 的 y 坐标
*/
public void setWaterMarkPara(Bitmap bitmap, VideoEffect.Rect rect, int x, int y)
/**
* 是否显示本地水印
* @param preview true:本地显示 false: 本地不显示
*/
public void setWaterPreview(boolean preview)
/**
* 设置视频动态水印相关参数
* @param bitmapArray 水印图片数组
* @param rect 水印具体位置(上下左右中四个基本位置)
* @param x 距离 rect 的 x 坐标
* @param y 距离 rect 的 y 坐标
* @param fps 动态水印的叠加帧率
* @param looped 动态水印是否循环叠加的标志
*/
public void setDynamicWaterMarkPara(Bitmap[] bitmapArray, VideoEffect.Rect rect,int x, int y, int fps, boolean looped)
/**
* 是否显示本地动态水印
* @param preview true:本地显示 false: 本地不显示
*/
public void setDynamicWaterPreview(boolean preview)
参数说明
参数 | 类型 | 说明 |
---|---|---|
bitmap | Bitmap | 图像 |
rect | VideoEffect.Rect | 上下左右中四个基本位置 |
x | int | 距离 rect 的 水平坐标 |
y | int | 距离 rect 的 垂直坐标 |
fps | int | 动态水印的叠加帧率 |
looped | int | 动态水印是否循环叠加的标志 |
示例
private void addWaterMark(){
if(mLSMediaCapture != null){
Bitmap water = BitmapFactory.decodeResource(getResources(),R.drawable.water);
int x = 120;
int y = 60;
mLSMediaCapture.setWaterMarkPara(water, VideoEffect.Rect.leftTop,x,y);
}
}
Bitmap[] bitmaps;
private void addDynamicWaterMark(){
if(mLSMediaCapture != null){
int x = 0;
int y = 0;
int fps = 1; //水印的帧率
boolean looped = true; //是否循环
String[] waters;
try {
waters = getAssets().list("dynamicWaterMark");
bitmaps = new Bitmap[waters.length];
for(int i = 0; i< waters.length;i++){
waters[i] = "dynamicWaterMark/" + waters[i];
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap tmp = BitmapFactory.decodeStream(getAssets().open(waters[i]));
bitmaps[i] = tmp;
}
mLSMediaCapture.setDynamicWaterMarkPara(bitmaps,VideoEffect.Rect.center,x,y,fps,looped);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private Thread mGraffitiThread;
private boolean mGraffitiOn = false;
private void addGraffiti(){
if(mGraffitiThread != null){
return;
}
mGraffitiOn = true;
mGraffitiThread = new Thread(){
@Override
public void run() {
int x = 180;
int y = 180;
while (mGraffitiOn && bitmaps != null && mLSMediaCapture != null){
for(Bitmap bitmap:bitmaps){
if(!mGraffitiOn){
break;
}
SystemClock.sleep(1000);
if(mLSMediaCapture != null){
mLSMediaCapture.setGraffitiPara(bitmap,x,y);
}
}
}
}
};
mGraffitiThread.start();
}
特殊说明
无
直播辅助操作
- 直播过程中发生错误的回调函数
- 得到直播过程中的统计信息
- 更新自定义统计数据
- 设置日志的level
- 获取当前sdk的版本号
- 获取当前同步时间戳(与setSyncTimestamp配合使用)
- 获取当前透传时间戳(与setStreamTimestampPassthrough 配合使用)
- 在码率中发送自定义数据
API原型
lsMediaCapture.LsMediaCapturePara lsMediaCapturePara = new lsMediaCapture.LsMediaCapturePara();
lsMediaCapturePara.setMessageHandler(this); //设置SDK消息回调
case MSG_GET_STATICS_INFO://获取统计信息的反馈消息
{
Message message = Message.obtain(mHandler, MSG_GET_STATICS_INFO);
Statistics statistics = (Statistics) object;
Bundle bundle = new Bundle();
bundle.putInt("FR", statistics.videoEncodeFrameRate);
bundle.putInt("VBR", statistics.videoRealSendBitRate);
bundle.putInt("ABR", statistics.audioRealSendBitRate);
bundle.putInt("TBR", statistics.totalRealSendBitRate);
bundle.putInt("networkLevel", statistics.networkLevel);
bundle.putString("resolution", statistics.videoEncodeWidth + " x " + statistics.videoEncodeHeight);
message.setData(bundle);
if(mHandler != null) {
mHandler.sendMessage(message);
}
break;
}
/**
* 更新自定义统计数据
* @param jsonObject 自定义统计数据
*/
public void updateCustomStatistics(JSONObject jsonObject)
lsMediaCapturePara.setLogLevel(lsLogUtil.LogLevel.INFO); //日志级别
/**
* 获取SDK版本号
* @return SDK版本号
*/
public String getSDKVersion()
/**
* 获取当前推流时间戳,对应 setSyncTimestamp
* @return 当前推流的时间戳(毫秒)
*/
public long currentSyncTimestamp()
/**
* 获取当前时间戳,对应setStreamTimestampPassthrough 一起使用
* @return 当前同步时间戳(毫秒)
*/
public long currentStreamTimestamp()
/**
* 在码流中发送自定义数据
* @param customData 数据内容
* @return 0:发送成功,1: 参数长度和值域校验失败,2: 超过并发数限制(5个)
*/
public int sendCustomData(CustomData customData)
参数说明
参数 | 类型 | 说明 |
---|---|---|
jsonObject | JSONObject | 自定义统计数据(key,value) |
logLevel | lsLogUtil.LogLevel | 信息的级别 |
示例
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appkey","1111");
jsonObject.put("uid","2222");
mLSMediaCapture.updateCustomStatistics(jsonObject);
}catch (Exception e){
e.printStackTrace();
}
特殊说明
无
屏幕共享
- 屏幕共享预览,使用
MediaProjection
实现屏幕共享,与摄像头预览对应,需要调用stopVideoPreview()
方法结束屏幕共享预览
API原型
/**
* 打开视频预览
* @param quality 视频能力
* @param mediaProjectionPermissionResultData MediaProjection权限申请成功后获得的intent
* @param quality 视频能力
* @param scale_16x9 是否强制 16:9 模式
*
*/
public void startScreenCapture(NeteaseView videoView, Intent mediaProjectionPermissionResultData, VideoQuality quality, boolean scale_16x9);
参数说明
参数 | 类型 | 说明 |
---|---|---|
videoView | NeteaseView | SDK提供的预览显示View,用户可以布局到自己的APP中,也支持传null 适应屏幕共享无预览场景 |
mediaProjectionPermissionResultData | Intent | MediaProjection权限申请成功后获得的intent |
quality | VideoQuality | MEDIUM:标清 480360,HIGH:高清 640480,SUPER:超清 960540,SUPER_HIGH:超高清 1280720 |
scale_16x9 | boolean | 是否按16:9宽高比例 |
示例
// 在某Activity中
private static final int CAPTURE_PERMISSION_REQUEST_CODE = 11;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_capture);
// 申请屏幕捕捉
requestScreenCapturer(CAPTURE_PERMISSION_REQUEST_CODE);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected void requestScreenCapturer(int requestCode) {
// Toast.makeText(this, "5.0 以上系统才能支持录屏", Toast.LENGTH_LONG).show();
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, requestCode);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAPTURE_PERMISSION_REQUEST_CODE) {
if (resultCode != Activity.RESULT_OK || data == null) {
showToastErr("你拒绝了录屏请求");
return;
}
NeteaseView neteaseView = (NeteaseView) findViewById(R.id.videoview);
startScreenCapture(neteaseView, data);
}
}
// sdk接口调用
void startScreenCapture(NeteaseView neteaseView, Intent data) {
boolean mScale_16x9 = mPublishParam.isScale_16x9; //是否强制16:9
// 视频模板(SUPER_HIGH 1280*720、SUPER 960*540、HIGH 640*480、MEDIUM 480*360、LOW 352*288)
lsMediaCapture.VideoQuality videoQuality = mPublishParam.videoQuality;
mLSMediaCapture.startScreenCapture(neteaseView, data, videoQuality, mScale_16x9);
}
特殊说明
- 调用
startScreenCapture
之后,需要检查SDK回调信息,如果返回MSG_START_PREVIEW_ERROR,则说明打开屏幕共享失败 - 由于
MediaProjection
限制,此接口仅支持Android 5.0
及以上设备
此文档是否对你有帮助?
有帮助
我要吐槽