前言

七牛云直播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 目录。将文件导入对应的目录(如下图)。

  • 添加相关权限并注册 Activity

  • <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.live.demo"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-feature android:glEsVersion="0x00020000" android:required="true" /><applicationandroid:name=".StreamingApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".Activity.MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name="com.qiniu.pili.droid.streaming.screen.ScreenCaptureRequestActivity"android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity><activity android:name=".Activity.AVStreamingActivity" /><activity android:name=".Activity.SWCameraStreamingActivity" /></application></manifest>
  • 添加 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 {@Overridepublic 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;@Overrideprotected 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);}@Overridepublic void onClick(View v) {new Thread(new Runnable() {@Overridepublic void run() {final String tlpath =   genPublishURL();
    //                video_AudioIntent 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;}
    }
    
  • 主界面布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"tools:context=".demo.Activity.MainActivity"><TextViewandroid:id="@+id/tv_start"android:text="开始推流"android:gravity="center"android:textSize="18sp"android:layout_marginTop="40dp"android:textColor="@color/textColorPrimary"android:background="@color/colorHeader"android:layout_width="160dp"android:layout_height="50dp" /></LinearLayout>
    
  • 创建推流界面

    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;@Overrideprotected 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);}@Overridepublic 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() {@Overridepublic void run() {mMediaStreamingManager.startStreaming();Log.d(TAG, "run: ===>"+"推流");}}).start();}@Overrideprotected void onResume() {super.onResume();mMediaStreamingManager.resume();}@Overrideprotected 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});}@Overridepublic void notifyStreamStatusChanged(final StreamingProfile.StreamStatus streamStatus) {runOnUiThread(new Runnable() {@Overridepublic 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");}});}}
    

推流界面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.live.demo.Activity.SWCameraStreamingActivity"><com.live.demo.ui.CameraPreviewFrameViewandroid:id="@+id/cameraPreview_surfaceView"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="left|top"android:gravity="center_vertical"android:orientation="vertical"><includelayout="@layout/status"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout></RelativeLayout>

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

测试直播效果

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

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

推流地址获取方法

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

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

  1. 七牛云 直播 java_七牛云直播SDK之推流解析

    最近由于项目需要,研究了直播的推拉流以及滤镜叠加的效果,在此记录一下一些小的细节. 前期做了直播SDK的调研,发现七牛云的SDK更符合项目需求一点,所以,最终选择了七牛云的SDK. 推流 七牛云官方的 ...

  2. android七牛直播镜像,七牛云直播SDK之推流解析

    最近由于项目需要,研究了直播的推拉流以及滤镜叠加的效果,在此记录一下一些小的细节. 前期做了直播SDK的调研,发现七牛云的SDK更符合项目需求一点,所以,最终选择了七牛云的SDK. 推流 七牛云官方的 ...

  3. 七牛云直播推流php,七牛云直播Android推流端之开速开发

    前言 在我看来,定性为快速开发的文档应该是毫无障碍的,对着敲应该就能直接运行的.可是由于七牛迭代太快了,文档跟不上代码迭代的速度,导致快速开始这部分文档的还没更新,很多被废弃的类.方法还在文档中,导致 ...

  4. php七牛云rtmp直播推流,GitHub - jangocheng/FlutterQiniucloudLivePlugin: Flutter 七牛云直播云 推流/播放 SDK集成...

    flutter_qiniucloud_live_plugin Flutter 七牛云直播云插件,支持IOS.Android客户端 Getting Started 集成七牛云直播云推流.观看等功能 功能 ...

  5. 【微信小程序控制硬件⑥ 进阶篇】服务器如何集成七牛云存储SDK,把用户自定义设备图片存储在第三方服务器!

    本博文由热爱分享热爱技术的半颗心脏原创,非官方人员.非组织名义编写,博文如有不对或侵犯您的权益,请及时留言,第一时间纠正! [微信小程序控制硬件①] 全网首发,借助 emq 消息服务器带你如何搭建微信 ...

  6. 七牛云 php sdk 安装,linux下Composer安装,通过Composer安装七牛云SDK

    先给linux云主机安装Composer,我装的是中国全量镜像,全局安装php -r "readfile('https://getcomposer.org/installer');" ...

  7. php系统接入七牛云直播服务,在旧有 PHP 系统上集成七牛云 PHP

    最近在一个古老的 PHP 系统上使用七牛云的上传图片功能,需要集成七牛云提供的 PHP-SDK,这个系统暂时不支持 composer,还好七牛云这个 SDK 不依赖其他的包,于是事情就变得简单了,只需 ...

  8. 七牛云直播-Android端播放卡顿问题处理

    背景: 七牛直播云主要涉及推流SDK.业务控制SDK.播放SDK.转发平台:而在播放端经常会遇到卡断不能播放的问题,此时可能有两种情况,第一,推流端停止推流,即主播下线:第二,播放端网络慢的原因:所以 ...

  9. 七牛直播sdk快速接入demo

    链接:https://github.com/JemyCheung/easystreaming 这个比较简洁,README也写的挺好,官方demo体验感比较好,但是很复杂,很容易扣代码扣错

最新文章

  1. 远程访问,文件的压缩,ip地址的设置(9,11,12unit)
  2. 用电脑发短信_重磅!一个软件实现电脑上接打手机电话、收发短信、传文件、屏幕镜像!...
  3. Redis-09Redis的基础事务
  4. Deno 运行时入门教程:Node.js 的替代品
  5. python—多进程之进程之间通信
  6. hihocoder 二分
  7. USACO-Section2.3 Zero Sum
  8. macos下卸载软件
  9. 电脑分屏设置主屏_华硕灵耀 X2 Pro 体验:两块屏幕的笔记本电脑,体验怎样?...
  10. Java版DBHelper【简单】(MySQL数据库)
  11. Sql server 分解字符串(实现split)
  12. kep server 6.4 激活_轻松一点,一触屏蔽!5G和未来显示的福音——低压激活,敏感元器件专用保护方案...
  13. [报告]HDU 4343 Interval query
  14. 点到直线的距离直线的交点及夹角
  15. Python将Word转换为Pdf格式文件(包含批量转换)
  16. spider pi 智能视觉六足机器人 开机介绍 0602
  17. GPS与compass对比
  18. Doevents函数详解
  19. java水仙花数(详解)
  20. narak 靶机实验实战演练

热门文章

  1. 【HTML】HTML网页设计--智能养老系统前端
  2. ST7789的显示问题-正点原子开发板验证
  3. 真机调试:问题: 想把写完的代码, 跑到手机上运行, 怎么办?
  4. 专心技术,拒绝浮躁,静下心来,做一个有创造力的coder
  5. class4-操作列表
  6. 思科向 IETF 提交 TrustSec 标准草案
  7. 用GNU Cash管理帐目
  8. 天平找不同质量小球c语言,有12个小球,其中只有一个球质量和其它的不同。现只有一台托盘天平,怎样只称三次就把质量不同的球找出来...
  9. excel随机生成数字或者字母
  10. 如何使用Tomcat自带的日志实现tomcat-juli.jar