笔记:腾讯云直播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);
    }
}

注:
①、直播码获取:https://console.cloud.tencent.com/live/livecodemanage

image.png

②、接入文档地址:
https://cloud.tencent.com/document/product/268/7685

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,510评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,693评论 2 59
  • 这两天在听《马东的职场A计划》里讲到,我们在生活中做什么会得到高付出高回报的事情呐,那就是工作,花两个小时作出...
    赵寜儿阅读 3,461评论 1 1
  • 1.前言 随着技术的发展,移动端开发也多种多样起来,有Native、Hybrid和Web等多种开发方式。而Nati...
    lanceJin阅读 1,826评论 0 7