七牛云直播SDK之推流端快速开发

前言

   七牛云直播SDK迭代快,但是官方文档跟不上迭代速度,导致快速开始这部分文档的还没更新,很多被废弃的类、方法还在文档中,本文是基于2.3.0版本进行的快速开发,由于是第一次接触直播,存在着许多不足欢迎批评指正。

  1. 官方文档地址:https://developer.qiniu.com/pili/sdk/3718/PLDroidMediaStreaming-quick-start
  2. 官方Demo地址:https://github.com/pili-engineering/PLDroidMediaStreaming
  3. SDK地址:https://github.com/pili-engineering/PLDroidMediaStreaming/tree/master/releases
  4. 本文代码地址:https://github.com/infoSafe/LiveBroadcastDemo

快速开始

  •  创建项目(软编要求 MinimumSDK API 15 ; 硬编要求 MinimumSDK API 18)本文使用的是18
  • 导入SDK,在 app/src/main 目录下创建 jniLibs 目录。将文件导入对应的目录(如下图)。

     七牛云直播SDK之推流端快速开发_第1张图片

  • 添加相关权限并注册 Activity

  • 
    
    
        
        
        
        
        
        
        
        
        
        
        
        
    
        
            
                
                    
    
                    
                
            
    
            
    
            
            
        
    
    

     

  • 添加 happy-dns 依赖(

    compile 'com.qiniu:happy-dns:0.2.8'

  • 实现自己的 Application

    import android.app.Application;
    
    import com.qiniu.pili.droid.streaming.StreamingEnv;
    
    public class StreamingApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            /**
             * init must be called before any other func
             */
            StreamingEnv.init(getApplicationContext());
        }
    }

     

  • 创建主界面

    package com.live.demo.Activity;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    import com.live.demo.R;
    import com.live.demo.Util.Util;
    
    import java.util.UUID;
    
    public class MainActivity extends Activity  implements View.OnClickListener{
    
        private static final String TAG = "MainActivity";
    
        private static final String GENERATE_STREAM_TEXT = "http://api-demo.qnsdk.com/v1/live/stream/";
    
        private TextView tv_start;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
    
    
        public void initView(){
            tv_start = findViewById(R.id.tv_start);
            tv_start.setOnClickListener(this);
        }
    
    
        @Override
        public void onClick(View v) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                  final String tlpath =   genPublishURL();
    //                video_Audio
                    Intent intent = new Intent(MainActivity.this, SWCameraStreamingActivity.class);
    //                传推流地址
                    intent.putExtra("stream_publish_url", tlpath);
                    startActivity(intent);
    
                }
            }).start();
        }
    
    
        /**
         * @author: 
         * @create at: 2018/11/13  13:01
         * @Description: 获取推流地址
         */
        private String genPublishURL() {
            String publishUrl = Util.syncRequest(GENERATE_STREAM_TEXT + UUID.randomUUID());
            return publishUrl;
        }
    }
    

     

  • 主界面布局文件

    
    
    
        
    
    
    

     

  • 创建推流界面

    package com.live.demo.Activity;
    
    import android.app.Activity;
    import android.hardware.Camera;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.TextView;
    
    import com.live.demo.R;
    import com.live.demo.ui.CameraPreviewFrameView;
    import com.qiniu.android.dns.DnsManager;
    import com.qiniu.android.dns.IResolver;
    import com.qiniu.android.dns.NetworkInfo;
    import com.qiniu.android.dns.http.DnspodFree;
    import com.qiniu.android.dns.local.AndroidDnsServer;
    import com.qiniu.android.dns.local.Resolver;
    import com.qiniu.pili.droid.streaming.CameraStreamingSetting;
    import com.qiniu.pili.droid.streaming.MediaStreamingManager;
    import com.qiniu.pili.droid.streaming.StreamStatusCallback;
    import com.qiniu.pili.droid.streaming.StreamingProfile;
    import com.qiniu.pili.droid.streaming.StreamingState;
    import com.qiniu.pili.droid.streaming.StreamingStateChangedListener;
    
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.URISyntaxException;
    
    import static com.qiniu.pili.droid.streaming.AVCodecType.SW_VIDEO_WITH_SW_AUDIO_CODEC;
    
    public class SWCameraStreamingActivity extends Activity implements StreamingStateChangedListener,
            StreamStatusCallback  {
        private static final String TAG = "LiveAcivity";
        private MediaStreamingManager mMediaStreamingManager;
        private StreamingProfile mProfile;
        private  CameraPreviewFrameView cameraPreviewFrameView;
        private TextView mStatView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_swcamera_streaming);
            initView();
        }
    
        public void initView(){
           cameraPreviewFrameView = findViewById(R.id.cameraPreview_surfaceView);
            mStatView =  findViewById(R.id.stream_status);
            String publishURLFromServer = getIntent().getStringExtra("stream_publish_url");
            Log.d(TAG, "initView: ===>"+publishURLFromServer);
                mProfile = new StreamingProfile();
            try {
                mProfile.setVideoQuality(StreamingProfile.VIDEO_QUALITY_HIGH1)
                        .setAudioQuality(StreamingProfile.AUDIO_QUALITY_MEDIUM2)
                        .setQuicEnable(false)//RMPT or QUIC
                        .setVideoQuality(StreamingProfile.VIDEO_QUALITY_MEDIUM1)
                        .setEncodingOrientation(StreamingProfile.ENCODING_ORIENTATION.PORT )//横竖屏
                        .setEncodingSizeLevel(StreamingProfile.VIDEO_ENCODING_HEIGHT_480)
                        .setBitrateAdjustMode(StreamingProfile.BitrateAdjustMode.Auto)//自适应码率
                        .setEncoderRCMode(StreamingProfile.EncoderRCModes.QUALITY_PRIORITY)
                        .setDnsManager(getMyDnsManager())
                        .setStreamStatusConfig(new StreamingProfile.StreamStatusConfig(3))
                        .setSendingBufferProfile(new StreamingProfile.SendingBufferProfile(0.2f, 0.8f, 3.0f, 20 * 1000))
                        .setPublishUrl(publishURLFromServer);//设置推流地址
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            CameraStreamingSetting setting = new CameraStreamingSetting();
                setting.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT) // 摄像头切换
                        .setContinuousFocusModeEnabled(true)
                        .setFaceBeautySetting(new CameraStreamingSetting.FaceBeautySetting(1.0f, 1.0f, 1.0f))//美颜 磨皮,美白,红润 取值范围为[0.0f, 1.0f]
                        .setVideoFilter(CameraStreamingSetting.VIDEO_FILTER_TYPE.VIDEO_FILTER_BEAUTY)
                        .setCameraPrvSizeLevel(CameraStreamingSetting.PREVIEW_SIZE_LEVEL.MEDIUM)
                        .setCameraPrvSizeRatio(CameraStreamingSetting.PREVIEW_SIZE_RATIO.RATIO_16_9);
                mMediaStreamingManager = new MediaStreamingManager(this, cameraPreviewFrameView, SW_VIDEO_WITH_SW_AUDIO_CODEC);
                mMediaStreamingManager.prepare(setting, mProfile);
                mMediaStreamingManager.setStreamingStateListener(this);
    
        }
    
        @Override
        public void onStateChanged(StreamingState streamingState, Object o) {
            switch (streamingState) {
                case PREPARING:
                    Log.d(TAG, "onStateChanged: ===>"+"准备");
                    break;
                case READY:
                    startStreaming();
                    break;
                case CONNECTING:
                    Log.d(TAG, "onStateChanged: ===>"+"连接");
                    break;
                case STREAMING:
                    Log.d(TAG, "onStateChanged: ===>"+"已发送");
                    break;
                case SHUTDOWN:
                    Log.d(TAG, "onStateChanged: ===>"+"推流结束");
                    break;
                case IOERROR:
                    Log.d(TAG, "onStateChanged: ===>"+"IO异常");
                    break;
                case SENDING_BUFFER_EMPTY:
                    break;
                case SENDING_BUFFER_FULL:
                    break;
                case AUDIO_RECORDING_FAIL:
                    break;
                case OPEN_CAMERA_FAIL:
                    break;
                case DISCONNECTED:
                    Log.d(TAG, "onStateChanged: ===>"+"断开连接");
                    break;
            }
        }
    
        /**
         * @author: 
         * @create at: 2018/11/14  15:32
         * @Description: 开始推流
         */
        protected void startStreaming() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mMediaStreamingManager.startStreaming();
                    Log.d(TAG, "run: ===>"+"推流");
                }
            }).start();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            mMediaStreamingManager.resume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            mMediaStreamingManager.pause();
        }
    
        /**
         * @author: 
         * @create at: 2018/11/14  10:57
         * @Description: 防止 Dns 被劫持
         */
        private static DnsManager getMyDnsManager() {
            IResolver r0 = null;
            IResolver r1 = new DnspodFree();
            IResolver r2 = AndroidDnsServer.defaultResolver();
            try {
                r0 = new Resolver(InetAddress.getByName("119.29.29.29"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return new DnsManager(NetworkInfo.normal, new IResolver[]{r0, r1, r2});
        }
    
    
        @Override
        public void notifyStreamStatusChanged(final StreamingProfile.StreamStatus streamStatus) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "run:totalAVBitrate ===>"+streamStatus.totalAVBitrate);
                    Log.d(TAG, "run:audioFps ===>"+streamStatus.audioFps);
                    Log.d(TAG, "run:videoFps ===>"+streamStatus.videoFps);
                    mStatView.setText("bitrate:" + streamStatus.totalAVBitrate / 1024 + " kbps"
                            + "\naudio:" + streamStatus.audioFps + " fps"
                            + "\nvideo:" + streamStatus.videoFps + " fps");
                }
            });
        }
    
    
    }
    

     

推流界面布局




    

    

        

    



启动 APP 之后,当点击 开始推流,就可以开始推流了。

测试直播效果

1.下载播放端的Demo运行输入推流地址 :https://github.com/pili-engineering/PLDroidPlayer

2.或者扫码下载播放app输入推流地址

七牛云直播SDK之推流端快速开发_第2张图片

推流地址获取方法

  手机运行app,as打印推流地址

 

你可能感兴趣的:(Android)