Android腾讯云直播开发,笔记:腾讯云直播SDK测试demo
看着腾讯直播的官方指导接入SDK,写了一个demo,有点简陋并且没全部demo应用,有空再更新吧,先做个笔记Mark先
demo地址
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.TypedValue;
import android.view.Surface;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.tencent.rtmp.ITXLivePushListener;
import com.tencent.rtmp.TXLiveConstants;
import com.tencent.rtmp.TXLivePushConfig;
import com.tencent.rtmp.TXLivePusher;
import com.tencent.rtmp.ui.TXCloudVideoView;
import com.tencent.ugc.TXRecordCommon;
import static com.tencent.rtmp.TXLiveConstants.PAUSE_FLAG_PAUSE_AUDIO;
import static com.tencent.rtmp.TXLiveConstants.PAUSE_FLAG_PAUSE_VIDEO;
public class StartLiveActivity extends AppCompatActivity{
private TXLivePushConfig mLivePushConfig;
private TXCloudVideoView mCaptureView;
private TXLivePusher mLivePusher;
//设置清晰度
private boolean mAutoBitrate;//画质优先
private boolean mAutoResolution;//分辨率优先
private int mVideoQuality = TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION;//直播视频质量
//美颜
private int mBeautyStyle;//磨皮风格: 0:光滑 1:自然 2:朦胧
private int mBeautyLevel;//磨皮等级: 取值为 0-9.取值为 0 时代表关闭美颜效果.默认值: 0,即关闭美颜效果.;
private int mWhiteningLevel;//美白等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
private int mRuddyLevel;//红润等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
//滤镜
private int filterIndex;//滤镜图片
private int filterDegree;//滤镜程度
private float expouseCompensation;//曝光值
//摄像头
private boolean mFlashTurnOn=true;//是否开启
private boolean mTouchFocus=false;//是否手动(true)自动对焦(false),默认手动
//设置水印
private boolean isLogo=true;//true设置,false不设置
private boolean HWVideoCode =true;//是否开启软(false,默认)硬件编码(true)
//本地录制
private TextView recordTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
recordTv=findViewById(R.id.recordTv);
mLivePusher = new TXLivePusher(this);
mLivePushConfig = new TXLivePushConfig();
mLivePushConfig.setTouchFocus(mTouchFocus);//是否自动对焦
mLivePushConfig.setFrontCamera(true);//是否前置摄像头
initLogo();//设置水印
initHardWareCode();//软硬件编码
setPasueBackImg();//后台推流,设置主播暂停背景图
//horizontalPushCustom();//调整观众端表现
//horizontalPushLiver();//调整主播端表现
initLiveType();//开播类型
}
@Override
protected void onResume() {
super.onResume();
//10.4 切前台处理
//mCaptureView.onResume(); // mCaptureView 是摄像头的图像渲染view
//mLivePusher.resumePusher(); // 通知 SDK 重回前台推流
}
@Override
protected void onStop() {
super.onStop();
//10.3 切后台处理
//mCaptureView.onPause(); // mCaptureView 是摄像头的图像渲染view
//mLivePusher.pausePusher(); // 通知 SDK 进入“后台推流模式”了
//10.4 后台推摄像头采集数据
//如果希望主播在切后台或者跳转其他界面还能看到摄像头采集的画面, 按照以下配置即可。
//1、step 10.1 和 step 10.2 无需设置。
//2、在 step 10.3 中,注释 mLivePusher.pausePusher() 该方法。
//3、在 step 10.4 中,注释 mLivePusher.resumePusher() 该方法。
}
@Override
protected void onDestroy() {
super.onDestroy();
stopRtmpPublish();//结束推流
}
//开播类型
private void initLiveType() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("开始纯音频直播还是音视频直播");
builder.setIcon(R.mipmap.ic_launcher);
builder.setMessage("请选择纯音频直播或是音视频直播");
builder.setPositiveButton("音视频直播", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
initStartLive();//开始直播
}
});
builder.setNegativeButton("纯音频直播", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
initOnlyVoiceLive();
}
});
builder.show();
}
//纯音频直播
private void initOnlyVoiceLive() {
// 只有在推流启动前设置启动纯音频推流才会生效,推流过程中设置不会生效。
mLivePushConfig.enablePureAudioPush(true); // true 为启动纯音频推流,而默认值是 false;
mLivePusher.setConfig(mLivePushConfig); // 重新设置 config
String rtmpUrl = Constant.START_LIVE_URL;//开始直播的推流地址
mLivePusher.startPusher(rtmpUrl);
}
//开始直播
private void initStartLive() {
mLivePusher.setConfig(mLivePushConfig);
String rtmpUrl = Constant.START_LIVE_URL;//开始直播的推流地址
mLivePusher.startPusher(rtmpUrl);
mCaptureView = (TXCloudVideoView) findViewById(R.id.video_view);
mLivePusher.startCameraPreview(mCaptureView);
}
//纯音频直播
public void voiceLive(View view) {
Log.e("uuuuuuuu :", "纯音频直播");
initOnlyVoiceLive();
}
//设置清晰度
public void setDifinition(View view) {
Log.e("uuuuuuuu :", "设置清晰度");
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
final String[] arrayOfString = {"秀场直播", "手游直播", "连麦(主画面)", "连麦(小画面)", "视频通话"};
localBuilder
.setTitle("设置清晰度")
.setIcon(R.mipmap.ic_launcher)
.setItems(arrayOfString, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
switch (paramAnonymousInt) {
case 0://秀场直播
mAutoBitrate = false;
mAutoResolution = false;
//VIDEO_QUALITY_SUPER_DEFINITION
mVideoQuality = TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION;
mLivePusher.setVideoQuality(mVideoQuality, mAutoBitrate, mAutoResolution);
break;
case 1://手游直播
mAutoBitrate = true;
mAutoResolution = true;
mVideoQuality = TXLiveConstants.VIDEO_QUALITY_SUPER_DEFINITION;
mLivePusher.setVideoQuality(mVideoQuality, mAutoBitrate, mAutoResolution);
break;
case 2://连麦(主画面)
mAutoBitrate = true;
mAutoResolution = true;
mVideoQuality = TXLiveConstants.VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER;
mLivePusher.setVideoQuality(mVideoQuality, mAutoBitrate, mAutoResolution);
break;
case 3://连麦(小画面)
mAutoBitrate = false;
mAutoResolution = false;
mVideoQuality = TXLiveConstants.VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER;
mLivePusher.setVideoQuality(mVideoQuality, mAutoBitrate, mAutoResolution);
break;
case 4://视频通话
mAutoBitrate = true;
mAutoResolution = true;
mVideoQuality = TXLiveConstants.VIDEO_QUALITY_REALTIEM_VIDEOCHAT;
mLivePusher.setVideoQuality(mVideoQuality, mAutoBitrate, mAutoResolution);
break;
}
//暂时不知道什么用
if (mVideoQuality == TXLiveConstants.VIDEO_QUALITY_STANDARD_DEFINITION ||
mVideoQuality == TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION ||
mVideoQuality == TXLiveConstants.VIDEO_QUALITY_SUPER_DEFINITION) {
mLivePushConfig.setVideoEncodeGop(5);
}
// 列表对话框不加这句,点击选择后也后不会消失
paramAnonymousDialogInterface.dismiss();
}
}).create().show();
}
//设置美颜
public void beatify(View view) {
Log.e("uuuuuuuu :", "美颜滤镜");
//美颜滤镜
mBeautyStyle = 0;//磨皮风格: 0:光滑 1:自然 2:朦胧
mBeautyLevel = 0;//磨皮等级: 取值为 0-9.取值为 0 时代表关闭美颜效果.默认值: 0,即关闭美颜效果.;
mWhiteningLevel = 0;//美白等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
mRuddyLevel = 0;//红润等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
View view_beaty = getLayoutInflater().inflate(R.layout.beaty, null);
SeekBar mStyleSeekBar = view_beaty.findViewById(R.id.mStyleSeekBar);
final TextView mStyleTV = view_beaty.findViewById(R.id.mStyleTV);
mStyleSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mStyleTV.setText(progress + "");
mBeautyStyle = progress;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
SeekBar mLevelSeekBar = view_beaty.findViewById(R.id.mLevelSeekBar);
final TextView mLevelTV = view_beaty.findViewById(R.id.mLevelTV);
mLevelSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mLevelTV.setText(progress + "");
mBeautyLevel = progress;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
SeekBar whiteningLevelSeekbar = view_beaty.findViewById(R.id.whiteningLevelSeekbar);
final TextView whiteningLevelTV = view_beaty.findViewById(R.id.whiteningLevelTV);
whiteningLevelSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
whiteningLevelTV.setText(progress + "");
mWhiteningLevel = progress;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
SeekBar ruddyLevelSeekbar = view_beaty.findViewById(R.id.ruddyLevelSeekbar);
final TextView ruddyLevelTV = view_beaty.findViewById(R.id.ruddyLevelTV);
ruddyLevelSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ruddyLevelTV.setText(progress + "");
mRuddyLevel = progress;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
localBuilder
.setTitle("设置美颜")
.setIcon(R.mipmap.ic_launcher)
.setView(view_beaty)
.setPositiveButton("确定美颜", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
mLivePusher.setBeautyFilter(mBeautyStyle, mBeautyLevel, mWhiteningLevel, mRuddyLevel);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
}
})
.create()
.show();
}
//设置滤镜
public void filter(View view) {
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
View view_filter = getLayoutInflater().inflate(R.layout.filter, null);
initFilterType(view_filter);
localBuilder
.setTitle("设置滤镜")
.setIcon(R.mipmap.ic_launcher)
.setView(view_filter)
.setPositiveButton("确定滤镜程度", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
mLivePusher.setSpecialRatio(filterDegree / 10.f);//滤镜程度
}
})
.setNegativeButton("确定滤镜图片", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
setFilter(filterIndex);//滤镜图片
}
})
.create()
.show();
}
//设置曝光值
public void exposure(View view) {
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
View view_expouse = getLayoutInflater().inflate(R.layout.expouse, null);
initExpouseView(view_expouse);
localBuilder
.setTitle("设置曝光值")
.setIcon(R.mipmap.ic_launcher)
.setView(view_expouse)
.setPositiveButton("确定曝光值", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
mLivePusher.setExposureCompensation(expouseCompensation);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
}
})
.create()
.show();
}
//设置摄像头
public void setCameraHead(View view) {
Log.e("uuuuuuuu :", "设置摄像头");
AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
View view_camera = getLayoutInflater().inflate(R.layout.camera, null);
initCameraView(view_camera);
localBuilder
.setTitle("设置曝光值")
.setIcon(R.mipmap.ic_launcher)
.setView(view_camera)
.setInverseBackgroundForced(false)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
}
})
.create()
.show();
}
//设置水印logo
public void setLogo(View view) {
Log.e("uuuuuuuu :", "设置水印logo");
if (isLogo){
Toast.makeText(this, "设置失败,水印LOGO已经设置了", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "设置失败,需要在mLivePusher.setConfig(mLivePushConfig)之前调用!,这里已经做了,只需修改isLogo的值即可", Toast.LENGTH_SHORT).show();
}
}
//开始软硬件编码
public void hardwareCode(View view) {
Log.e("uuuuuuuu :", "开始软硬件编码");
if (HWVideoCode){
Toast.makeText(this, "硬件加速失败,原因:\n1、当前手机 API 级别过低(最低 18)\n" +
"2、需要在mLivePusher.setConfig(mLivePushConfig)之前调用!,这里已经做了,只需修改mTouchFocus的值即可", Toast.LENGTH_SHORT).show();
}
}
//本地录制
public void nativeRecord(View view) {
Log.e("uuuuuuuu :", "本地录制");
nativeRecord();
}
//后台推流
public void backPush(View view) {
Log.e("uuuuuuuu :", "纯音频直播");
Toast.makeText(this, "查看代码中的10.1、10.2、10.3、10.4", Toast.LENGTH_SHORT).show();
}
//网络提示
public void networkTips(View view) {
Log.e("uuuuuuuu :", "网络提示");
mLivePusher.setPushListener(new ITXLivePushListener() {
@Override
public void onPushEvent(int event, Bundle bundle) {
if (event==TXLiveConstants.PUSH_WARNING_NET_BUSY){
Toast.makeText(StartLiveActivity.this, "您当前的网络状况不佳,推荐您离 WiFi 近一点,尽量不要让 WiFi 穿墙", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onNetStatus(Bundle bundle) {
}
});
}
//横屏推流
public void horizontalPush(View view) {
Log.e("uuuuuuuu :", "横屏推流");
}
//设置背景混淆音
public void setBGM(View view) {
Log.e("uuuuuuuu :", "设置背景混淆音");
}
//发送消息
public void sendMessage(View view) {
Log.e("uuuuuuuu :", "发送消息");
//Android 示例代码
//mLivePusher.sendMessage(questionInfo.getBytes("UTF-8"));
//mLivePusher.sendMessage(new byte[]);
byte[] bytes = new byte[]{};
mLivePusher.sendMessageEx(bytes);
}
//==================================设置滤镜=======================
//初始化Dialog的空件
private void initFilterType(final View view_filter) {
filterDegree = 0;
final TextView mFilterTV = view_filter.findViewById(R.id.mFilterTV);
SeekBar mFilterSeekBar = view_filter.findViewById(R.id.mFilterSeekBar);
mFilterSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
filterDegree = progress;
mFilterTV.setText("" + filterDegree);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
view_filter.findViewById(R.id.bailan).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 5;
}
});
view_filter.findViewById(R.id.biaozhun).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 1;
}
});
view_filter.findViewById(R.id.chaotuo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 7;
}
});
view_filter.findViewById(R.id.chunzhen).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 4;
}
});
view_filter.findViewById(R.id.fennen).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 13;
}
});
view_filter.findViewById(R.id.huaijiu).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 14;
}
});
view_filter.findViewById(R.id.landiao).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 15;
}
});
view_filter.findViewById(R.id.langman).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 10;
}
});
view_filter.findViewById(R.id.qingliang).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 16;
}
});
view_filter.findViewById(R.id.qinxi).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 11;
}
});
view_filter.findViewById(R.id.rixi).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 17;
}
});
view_filter.findViewById(R.id.weimei).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 12;
}
});
view_filter.findViewById(R.id.white).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 9;
}
});
view_filter.findViewById(R.id.xiangfen).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 8;
}
});
view_filter.findViewById(R.id.yinghong).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 2;
}
});
view_filter.findViewById(R.id.yuanqi).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 6;
}
});
view_filter.findViewById(R.id.yunshang).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
filterIndex = 3;
}
});
}
//设置滤镜
private void setFilter(int index) {
Bitmap bmp = getFilterBitmapByIndex(index);
if (mLivePusher != null) {
mLivePusher.setFilter(bmp);
}
}
//获取图片资源
public Bitmap getFilterBitmapByIndex(int index) {
Bitmap bmp = null;
switch (index) {
case 1:
bmp = decodeResource(getResources(), R.drawable.filter_biaozhun);
break;
case 2:
bmp = decodeResource(getResources(), R.drawable.filter_yinghong);
break;
case 3:
bmp = decodeResource(getResources(), R.drawable.filter_yunshang);
break;
case 4:
bmp = decodeResource(getResources(), R.drawable.filter_chunzhen);
break;
case 5:
bmp = decodeResource(getResources(), R.drawable.filter_bailan);
break;
case 6:
bmp = decodeResource(getResources(), R.drawable.filter_yuanqi);
break;
case 7:
bmp = decodeResource(getResources(), R.drawable.filter_chaotuo);
break;
case 8:
bmp = decodeResource(getResources(), R.drawable.filter_xiangfen);
break;
case 9:
bmp = decodeResource(getResources(), R.drawable.filter_white);
break;
case 10:
bmp = decodeResource(getResources(), R.drawable.filter_langman);
break;
case 11:
bmp = decodeResource(getResources(), R.drawable.filter_qingxin);
break;
case 12:
bmp = decodeResource(getResources(), R.drawable.filter_weimei);
break;
case 13:
bmp = decodeResource(getResources(), R.drawable.filter_fennen);
break;
case 14:
bmp = decodeResource(getResources(), R.drawable.filter_huaijiu);
break;
case 15:
bmp = decodeResource(getResources(), R.drawable.filter_landiao);
break;
case 16:
bmp = decodeResource(getResources(), R.drawable.filter_qingliang);
break;
case 17:
bmp = decodeResource(getResources(), R.drawable.filter_rixi);
break;
default:
bmp = null;
break;
}
return bmp;
}
//获取资源图片转换
private Bitmap decodeResource(Resources resources, int id) {
TypedValue value = new TypedValue();
resources.openRawResource(id, value);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inTargetDensity = value.density;
return BitmapFactory.decodeResource(resources, id, opts);
}
//======================================曝光值======================
//初始化曝光值控件
private void initExpouseView(View view_expouse) {
SeekBar mExpuseSeekBar = view_expouse.findViewById(R.id.mExpuseSeekBar);
final TextView mExpuseTV = view_expouse.findViewById(R.id.mExpuseTV);
mExpuseSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float p=(progress-10)/10.0f;
expouseCompensation=p;
mExpuseTV.setText("曝光值为:"+p);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
//===================================控制摄像头======================
private void initCameraView(View view_camera) {
TextView cameraTV = view_camera.findViewById(R.id.cameraTV);//前后摄像头
TextView lampTV = view_camera.findViewById(R.id.lampTV);//闪光灯
TextView mFocuseTV = view_camera.findViewById(R.id.mFocuseTV);//自动手动对焦
TextView mMirrorTV = view_camera.findViewById(R.id.mMirrorTV);//镜像效果
cameraTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 默认是前置摄像头
mLivePusher.switchCamera();
}
});
lampTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLivePusher.turnOnFlashLight(mFlashTurnOn);
//mFlashTurnOn为true表示打开,否则表示关闭
if (!mLivePusher.turnOnFlashLight(mFlashTurnOn)) {
Toast.makeText(getApplicationContext(), "打开闪光灯失败:绝大部分手机不支持前置闪光灯!", Toast.LENGTH_SHORT).show();
}
mFlashTurnOn=!mFlashTurnOn;
}
});
mFocuseTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "设置手自动对焦失败:需要在mLivePusher.setConfig(mLivePushConfig)之前调用!,这里已经做了,只需修改mTouchFocus的值即可", Toast.LENGTH_SHORT).show();
}
});
mMirrorTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 需在 mLivePusher.setConfig(mLivePushConfig); 之后调用
mLivePusher.setMirror(true);
}
});
}
//=================================软硬件编码========================
private void initHardWareCode() {
if (HWVideoCode){
if (HWVideoCode){
if (mLivePushConfig != null) {
if(Build.VERSION.SDK_INT < 18){
Toast.makeText(getApplicationContext(), "硬件加速失败,当前手机 API 级别过低(最低 18)",
Toast.LENGTH_SHORT).show();
HWVideoCode = false;
}
}
}
mLivePushConfig.setHardwareAcceleration(HWVideoCode ? TXLiveConstants.ENCODE_VIDEO_HARDWARE : TXLiveConstants.ENCODE_VIDEO_SOFTWARE);
// 如果你不清楚要何时开启硬件加速, 建议设置为 ENCODE_VIDEO_AUTO
// 默认是启用软件编码, 但手机 CPU 使用率超过 80% 或者帧率 <= 10, SDK 内部会自动切换为硬件编码
//ENCODE_VIDEO_HARDWARE 开启硬件加速
//ENCODE_VIDEO_SOFTWARE 禁用硬件加速,默认禁用硬件加速
//ENCODE_VIDEO_AUTO 自动选择是否启用硬件加速
}
}
//=================================设置水印========================
private void initLogo() {
if (isLogo){
//设置视频水印,后面两个参数分别是水印位置的 X 轴坐标和 Y 轴坐标
mLivePushConfig.setWatermark(BitmapFactory.decodeResource(getResources(), R.drawable.watermark), 10, 10);
//设置视频水印
//参数分别是水印图片的 Bitmap、水印位置的 X 轴坐标,水印位置的 Y 轴坐标,水印宽度。后面三个参数取值范围是[0, 1]
//后面两个参数分别是水印位置的X轴坐标和 Y 轴坐标
//mLivePushConfig.setWatermark(mBitmap, 0.02f, 0.05f, 0.2f);
}
}
//=================================本地录制========================
private void nativeRecord(){
String externalFilesDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES).toString()+".mp4";
mLivePusher.startRecord(externalFilesDir);
mLivePusher.setVideoRecordListener(new TXRecordCommon.ITXVideoRecordListener() {
@Override
public void onRecordEvent(int event, Bundle bundle) {
Log.e("本地录制==","完成"+event);
}
@Override
public void onRecordProgress(long milliSecond) {
recordTv.setText(String.format("%02d:%02d",milliSecond/1000/60, milliSecond/1000%60));
}
@Override
public void onRecordComplete(TXRecordCommon.TXRecordResult txRecordResult) {
Log.e("本地录制==","完成"+txRecordResult.videoPath+" "+txRecordResult.coverPath);
}
});
recordTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLivePusher.stopRecord();
}
});
}
//=============================后台推流============================
// 设置主播暂停背景图
private void setPasueBackImg() {
mLivePushConfig.setPauseImg(300,5);
// 300 为后台播放暂停图片的最长持续时间,单位是秒
// 10 为后台播放暂停图片的帧率,最小值为 5,最大值为 20
Bitmap bitmap = decodeResource(getResources(), R.drawable.pause_publish);
mLivePushConfig.setPauseImg(bitmap);
// 设置推流暂停时,后台播放的暂停图片, 图片最大尺寸不能超过 1920*1920.
//10.2 设置setPauseFlag
mLivePushConfig.setPauseFlag(PAUSE_FLAG_PAUSE_VIDEO|PAUSE_FLAG_PAUSE_AUDIO);//表示同时停止视频和音频采集,并且推送填充用的音视频流;
//mLivePushConfig.setPauseFlag(PAUSE_FLAG_PAUSE_VIDEO);//表示停止摄像头采集视频画面,但保持麦克风继续采集声音,用于主播更衣等场景;
}
//===============================横屏推流===========================
//调整观众端表现
private void horizontalPushCustom() {
// 竖屏状态, 手机 Home 键在正下方。 旋转 0 度
mLivePushConfig.setHomeOrientation(TXLiveConstants.VIDEO_ANGLE_HOME_DOWN);
// 横屏状态,手机 Home 键在右手方。 旋转 270 度
mLivePushConfig.setHomeOrientation(TXLiveConstants.VIDEO_ANGLE_HOME_RIGHT);
}
//调整主播端表现
private void horizontalPushLiver() {
// 竖屏状态,本地渲染相对正方向的角度为0。
mLivePusher.setRenderRotation(0);
// 横屏状态,本地渲染相对正方向的角度为90。
mLivePusher.setRenderRotation(90);
}
//Activity自旋转
@Override
public void onConfigurationChanged(Configuration newConfig) {
// 自动旋转打开,Activity随手机方向旋转之后,只需要改变推流方向
int mobileRotation = getWindowManager().getDefaultDisplay().getRotation();
int pushRotation = TXLiveConstants.VIDEO_ANGLE_HOME_DOWN;
switch (mobileRotation) {
case Surface.ROTATION_0:
pushRotation = TXLiveConstants.VIDEO_ANGLE_HOME_DOWN;
break;
case Surface.ROTATION_90:
pushRotation = TXLiveConstants.VIDEO_ANGLE_HOME_RIGHT;
break;
case Surface.ROTATION_270:
pushRotation = TXLiveConstants.VIDEO_ANGLE_HOME_LEFT;
break;
default:
break;
}
//通过设置config是设置生效(可以不用重新推流,腾讯云是少数支持直播中热切换分辨率的云商之一)
mLivePusher.setRenderRotation(0);
mLivePushConfig.setHomeOrientation(pushRotation);
mLivePusher.setConfig(mLivePushConfig);
}
//===============================step 13:背景混音===========================
//SDK 1.6.1 开始支持背景混音,支持主播带耳机和不带耳机两种场景,您可以通过 TXLivePusher 中的如下这组接口实现背景混音功能:
//playBGM 通过 path 传入一首歌曲,小直播 Demo中我们是从iOS的本地媒体库中获取音乐文件
//stopBGM 停止播放背景音乐
//pauseBGM 暂停播放背景音乐
//resumeBGM 继续播放背景音乐
//setMicVolume 设置混音时麦克风的音量大小,推荐在 UI 上实现相应的一个滑动条,由主播自己设置
//setBGMVolume 设置混音时背景音乐的音量大小,推荐在 UI 上实现相应的一个滑动条,由主播自己设置
//===============================step 14: 结束推流===========================
//结束推流,注意做好清理工作
public void stopRtmpPublish() {
mLivePusher.stopCameraPreview(true); //停止摄像头预览
mLivePusher.stopPusher(); //停止推流
mLivePusher.setPushListener(null); //解绑 listener
mLivePusher.stopBGM();
mLivePusher.stopScreenCapture();
mCaptureView.setVisibility(View.GONE);
}
}
Android腾讯云直播开发,笔记:腾讯云直播SDK测试demo相关推荐
- iOS RTMP 视频直播开发笔记(3)- 了解 H.264 编码
iOS RTMP 视频直播开发笔记(3)- 了解 H.264 编码 本节内容整理自:H264–1–编码原理以及I帧B帧P帧,作者:dxpqxb H264是一种高压缩率的编码标准,如何压缩嘞?一般的视频 ...
- iOS RTMP 视频直播开发笔记(6)- 封包 FLV
iOS RTMP 视频直播开发笔记(6)- 封包 FLV 讲讲FLV文件格式.以及数据如何放置的. FLV里面是由多个Tag构成的:[[tag1][tag2][tag3][tag4]-] 而Tag多种 ...
- iOS RTMP 视频直播开发笔记(4)- 关于 AVVideoProfileLevelKey
iOS RTMP 视频直播开发笔记(4)- 关于 AVVideoProfileLevelKey iOS的Video参数中有一个叫做AVVideoProfileLevelKey的参数,说明太简单,只说了 ...
- iOS RTMP 视频直播开发笔记(5)- iOS H.264 实时硬编码实现原理
iOS RTMP 视频直播开发笔记(5)- iOS H.264 实时硬编码实现原理 网上有两个实现,GDCL – AVEncoder 和 IFVideoPicker. IFVideoPicker 使用 ...
- ZYNQ LINUX开发笔记——windows下用xilinx SDK编译zynq linux app小程序
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ LINUX开发笔记--windows下用xilinx SDK编译zynq linux app小程序 前言 操作方法 总结 前 ...
- 腾讯云直播开发日记(三) 聊天室-直播转码-连麦混流
腾讯云直播开发日记(三) 直播的时候,用户还是需要和主播互动的,我们当前的互动就只有刷礼物,那没钱说礼物怎么搞? 不得让他们吹水? 所以我们需要做一个聊天室, 这个话自己也能做, 系统上线迫在眉睫,工 ...
- Android开发笔记(一百一十三)测试工具
单元测试TestCase Android的sdk提供了对项目进行单元测试的功能,开发包的android.test下面便是专门用来单元测试的类.单元测试的作用是通过模拟文本输入和手势输入(如点击操作), ...
- 【STM32+ESP-12S连接腾讯云物联网开发平台 1】云平台的创建和AT固件烧录
腾讯云物联网开发平台创建和ESP-12S的固件烧录 前言 一.腾讯云物联网开发平台的创建 1. 创建产品 2. 配置产品和创建设备 3. 设备三元组说明 二.ESP-12S固件烧录 1.固件获取 2. ...
- 云风开发笔记(1) 背包系统
折腾了好久,终于可以开始正式项目开发了. 之前的这段日子,我们陷落在公司的股权分配问题中,纠结于到底需要几个人到位才启动:更是反复讨论,到底应该做个怎样的游戏.林林总总,终于,在已经到位的几位同学的摩 ...
- 【Io开发笔记】机智云智能浇花器实战(1)-基础Demo实现
一,系统总计设计 该系统主要由三个部分组成:传感执行部分.无线通信部分,机智云自助开发平台部分.传感执行部分由主控单元.显示单元.和存储单元共同组成.传感检测部分采集空气环境参数信息,并且实时处理采集 ...
最新文章
- java shiro实例_Apache Shiro入门实例
- XStream 用法汇总
- The DVMM Lab at Columbia University
- SQLServer常见性能问题
- Java面试必问JVM调优,那.NET5呢?
- Kooteam 0.2.0 发布,新增周报、日报功能
- 产品经理该如何做竞品分析
- k8s节点不稳定,报错failed to wipe the XDP state error=failed to load BPF program
- jdbc odbc连接mysql_具体说明JDBC连接数据库与ODBC连接数据的区别
- 优缺点 快速扫描 硬盘监测_用硬盘检测工具检测硬盘超实用的技巧!
- wdr7660虚拟服务器设置,TP-LINK WDR7660用手机怎么设置?
- 夜神模拟器adb找不到
- Excel操作:使用Excel制作甘特图
- CogPDF417Tool工具
- 2021.05.09 美团测开笔试-弹吉他
- vue 悬浮图标_vue实现移动端悬浮窗效果
- 2022网鼎杯白虎组misc830题解
- linux 的gz命令详解,linux tar.gz压缩解压命令详解
- 计算机组成原理实验:系统总线与系统接口
- HashMap扩容时的rehash方法中(e.hash oldCap) == 0算法推导
热门文章
- 信息收集-目录扫描(7kbscan御剑版)下载及使用
- MCE公司:新型 RORγt 小分子反向激动剂的发现
- 密码字典生成工具汇总
- 挖矿病毒zz.sh——记一次linux(centos)成为矿机后的排查与修复过程
- 大数据科学相关岗位,我们需要具备哪些数学基础?
- python 编程自学手册 pdf-跪求《python学习手册》(第五版)pdf中文版!/
- Java图书管理系统
- 免费培训后包就业,还月薪上万,深扒BI数据工程师培训套路
- 清华大学计算机系研究生培养方案,清华大学计算机科学与技术系攻读硕士学位研究生培养方案...
- 计算机二级c语言f7保存,国家计算机二级c语言上机真题