筆記:騰訊云直播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;//畫質優(yōu)先
    private boolean mAutoResolution;//分辨率優(yōu)先
    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();//調整觀眾端表現(xiàn)
        //horizontalPushLiver();//調整主播端表現(xiàn)

        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 后臺推攝像頭采集數(shù)據(jù)
        //如果希望主播在切后臺或者跳轉其他界面還能看到攝像頭采集的畫面, 按照以下配置即可。
        //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 :", "設置背景混淆音");

    }

    //發(fā)送消息
    public void sendMessage(View view) {
        Log.e("uuuuuuuu :", "發(fā)送消息");
        //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){
            //設置視頻水印,后面兩個參數(shù)分別是水印位置的 X 軸坐標和 Y 軸坐標
            mLivePushConfig.setWatermark(BitmapFactory.decodeResource(getResources(), R.drawable.watermark), 10, 10);

            //設置視頻水印
            //參數(shù)分別是水印圖片的 Bitmap、水印位置的 X 軸坐標,水印位置的 Y 軸坐標,水印寬度。后面三個參數(shù)取值范圍是[0, 1]
            //后面兩個參數(shù)分別是水印位置的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 為后臺播放暫停圖片的最長持續(xù)時間,單位是秒
        // 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);//表示停止攝像頭采集視頻畫面,但保持麥克風繼續(xù)采集聲音,用于主播更衣等場景;
    }


    //===============================橫屏推流===========================
    //調整觀眾端表現(xiàn)
    private void horizontalPushCustom() {
        // 豎屏狀態(tài), 手機 Home 鍵在正下方。   旋轉 0 度
        mLivePushConfig.setHomeOrientation(TXLiveConstants.VIDEO_ANGLE_HOME_DOWN);
        // 橫屏狀態(tài),手機 Home 鍵在右手方。   旋轉 270 度
        mLivePushConfig.setHomeOrientation(TXLiveConstants.VIDEO_ANGLE_HOME_RIGHT);
    }

    //調整主播端表現(xiàn)
    private void horizontalPushLiver() {
        // 豎屏狀態(tài),本地渲染相對正方向的角度為0。
        mLivePusher.setRenderRotation(0);
        // 橫屏狀態(tài),本地渲染相對正方向的角度為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是設置生效(可以不用重新推流,騰訊云是少數(shù)支持直播中熱切換分辨率的云商之一)
        mLivePusher.setRenderRotation(0);
        mLivePushConfig.setHomeOrientation(pushRotation);
        mLivePusher.setConfig(mLivePushConfig);
    }


    //===============================step 13:背景混音===========================
    //SDK 1.6.1 開始支持背景混音,支持主播帶耳機和不帶耳機兩種場景,您可以通過 TXLivePusher 中的如下這組接口實現(xiàn)背景混音功能:
    //playBGM   通過 path 傳入一首歌曲,小直播 Demo中我們是從iOS的本地媒體庫中獲取音樂文件
    //stopBGM   停止播放背景音樂
    //pauseBGM  暫停播放背景音樂
    //resumeBGM 繼續(xù)播放背景音樂
    //setMicVolume  設置混音時麥克風的音量大小,推薦在 UI 上實現(xiàn)相應的一個滑動條,由主播自己設置
    //setBGMVolume  設置混音時背景音樂的音量大小,推薦在 UI 上實現(xiàn)相應的一個滑動條,由主播自己設置



    //===============================step 14: 結束推流===========================
    //結束推流,注意做好清理工作
    public void stopRtmpPublish() {
        mLivePusher.stopCameraPreview(true); //停止攝像頭預覽
        mLivePusher.stopPusher();            //停止推流
        mLivePusher.setPushListener(null);   //解綁 listener

        mLivePusher.stopBGM();
        mLivePusher.stopScreenCapture();
        mCaptureView.setVisibility(View.GONE);
    }
}

注:
①、直播碼獲?。?a target="_blank">https://console.cloud.tencent.com/live/livecodemanage

image.png

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,058評論 25 709
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,001評論 2 59
  • 這兩天在聽《馬東的職場A計劃》里講到,我們在生活中做什么會得到高付出高回報的事情吶,那就是工作,花兩個小時作出...
    趙寜兒閱讀 3,610評論 1 1
  • 1.前言 隨著技術的發(fā)展,移動端開發(fā)也多種多樣起來,有Native、Hybrid和Web等多種開發(fā)方式。而Nati...
    lanceJin閱讀 2,141評論 0 7

友情鏈接更多精彩內容