前言
如何从零开始搭建一套直播系统?
主流直播系统需要哪些功能模块?
利用阿里云来搭建一套直播系统应该怎么做?
你对以上问题感兴趣吗? 本文将以花椒直播的基本需求为核心,使用阿里云作为服务基础,讲述我们是如何基于阿里云部署一套直播系统,同时涉及到服务端、客户端、前端技术以及阿里云的使用。
本文适合对直播系统感兴趣,有一定开发基础,了解基本的云服务概念,K8S 等基本概念的程序员。
直播
一个直播系统会有哪些基本的产品需求呢?直播产品的最基础功能首先是推拉流,和推拉流相关的功能有:
视频美化:秀场直播,各位帅哥美女肯定希望自己看上去更美更帅,所以需要有美颜,一些让主播看起来更好看的特效;
视频特效:除了让主播看起来更美,还可增加趣味性,例如萌颜,绿幕等;
除此之外,为了让用户更有参与感,我们还需要各种互动功能,比如评论弹幕,互动直播,打赏送礼等。
本文我们将基于阿里云的服务实现最基本的推拉流功能。阿里云账号需要以下准备工作:
注册阿里云账号需要完成实名认证;
保证阿里云账户有一定金额;
至少需要一个域名并完成认证及备案;
为域名购买 TLS 证书【可选】。
本文中涉及到的示例代码说明:
iOS 基于 XCode 10 或更高版本,使用 Objective-C 开发语言;
Android 基于 Android Studio 3.4 或更高版本,使用 Java 语言;
服务端基于 Golang 1.12 或更高版本。
阿里云直播服务简介
阿里云视频直播服务(ApsaraVideo Live)作为领先的音视频直播平台,基于内容接入、分发网络和大规模分布式实时转码等技术,提供了便捷接入、高清流畅、低延迟、高并发的音视频直播服务。其工作原理如下:
采用android/ios等设备采集音视频直播流并将其推送至阿里云直播中心,通过CDN边缘节点进行加速,保证上行传输的稳定性。
音视频直播流推送至阿里云直播中心后,可以根据业务需求对直播流进行转码,录制,截图,审核等处理。
通过CDN内容分发网络下发音视频直播流,观众可以通过播放器实时观看。
通过配置回放策略生成回放,并将录制视频存储至点播系统。
完整的推拉流系统涉及主播端、观众端、阿里云、AppServer,其中AppServer需要根据业务实现。阿里云推拉流时序图如下所示:
在搭建直播服务之前,需要首先在阿里云控制台进行推拉流相关配置,可以按照以下步骤完成操作。
添加域名
在阿里云控制台选择视频直播>域名管理进入直播域名管理,分别添加推流域名和播流域名。
域名 CNAME
域名关联
URL 鉴权
URL 鉴权功能旨在保护用户站点的内容资源不被非法站点下载盗用。鉴权功能默认为开启状态,建议您保持默认开启状态,否则会出现直播被盗录、盗播的风险。
当鉴权功能开启时,有默认鉴权和自定义鉴权两种鉴权方式,可按需选择默认鉴权或自定义鉴权。其中,默认鉴权中,鉴权key随机分配,有效时长 30 分钟。超过有效时间,鉴权失效;自定义鉴权中,可以对鉴权 主KEY、 副KEY、 有效时长、 AppName 和 StreamName 等进行自定义,然后再生成 鉴权URL 进行推流。
推流回调设置
使用 ffmpeg 指令进行推流测试:
直播录制配置
一般情况下,直播过程中需要将音视频内容保存下来生成点播,供用户观看。阿里云配置回放可以根据如下几个步骤。
OSS 对象存储配置
首先打开对象存储控制台,添加用于存储回放的bucket,然后选择对应的 Bucket 的域名管理,绑定用户域名。添加 Bucket 如下图所示:
CDN 配置
打开CDN 控制台,添加CDN域名,源站信息选择OSS域名,对应域名选择OSS中绑定的域名。配置如图所示。在配置完成后,将OSS绑定的域名CNAME到CDN域名。
回放设置
注意:阿里云回放录制时长有限制,最长6个小时,如果超过配置的录制时长,回放会被切割为多个文件。
AppServer 搭建
在完成阿里云准备工作之后,需要编写代码实现AppServer,主要实现如下功能:
提供直播流状态回调
维护开播状态及 Feed 流信息
为了简化 AppServer 开发流程,我们对底层的通用云服务操作封装了 video-sdk。使用方法如下。
创建 Client
在使用 SDK 时,需要首先创建 Client:
1streamsUrl,err:=config.LiveCloudClient().GenStream(uid,WithStreamValidDuration(24*time.Hour))直播流状态回调
1funcLiveStreamCallback(whttp.ResponseWriter,r*http.Request){ 2_=r.ParseForm() 3 4streamCallback,err:=config.LiveCloudClient().ParseStreamCallback(r) 5iferr!=nil{ 6log.Println(“LiveStreamCallbackParseStreamCallbackerror:”,err,r.Form.Encode(),r.PostForm.Encode()) 7} 8//执行业务处理 9…10_,_=w.Write([]byte(`{“errno”:0,”errmsg”:”success”}`))11}1213…1415svr.HandleFunc(false,”/callback/replay”,LiveReplayCallback)
维护开播状态
AppServer需要维护开播状态,比较准确的方式是采用阿里云的流状态回调。当接收到推流回调时,将 Feed 信息置为直播状态;当接收到断流回调时,将 Feed 信息置为关播状态或回放状态。示例代码如下:
1live:=model.NewLive(context.Background())2err=live.SetStreamStatus(streamCallback)监控
直播的监控分为推流质量监控和播放质量监控。大部分的直播卡顿等问题都受到推流质量的影响。通过实时监测推流的质量可以及时定位直播中的卡顿、延时等问题。阿里云推流监控是秒级监控,实时返回每秒钟的推流监控数据,包括:
主播到CDN节点的接收音视频帧率
音视频时间戳
接受头次数
音视频码率(Kbps)
最大音视频帧间隔(毫秒)
推流断开错误码
阿里云推流监控如图所示:
Android 接入SDK 引入
下载阿里云Android视频直播SDK,将 arrlibs 下的文件放到主工程的 libs 目录下,并修改 build.gradle 文件:
1applyplugin:’com.android.application’ 2 3android{ 4compileSdkVersion28 5defaultConfig{ 6applicationId”com.huajiao.capsules” 7minSdkVersion22 8targetSdkVersion28 9versionCode110versionName”1.0″11testInstrumentationRunner”android.support.test.runner.AndroidJUnitRunner”12}13buildTypes{14release{15minifyEnabledfalse16proguardFilesgetDefaultProguardFile(‘proguard-android-optimize.txt’),’proguard-rules.pro’17}18}19allprojects{20repositories{21jcenter()22flatDir{23dirs’src/main/libs’24}25}26}27}2829dependencies{30implementationfileTree(dir:’libs’,include:[‘*.jar’,’*.aar’])31implementationfileTree(dir:’libs’,include:[‘*.jar’])32implementation’com.android.support:appcompat-v7:28.0.0’33implementation’com.android.support.constraint:constraint-layout:1.1.3’34testImplementation’junit:junit:4.12’35androidTestImplementation’com.android.support.test:runner:1.0.2’36androidTestImplementation’com.android.support.test.espresso:espresso-core:3.0.2’37}
然后在主工程的 proguard-rules.pro 文件添加:
1-keepclasscom.alibaba.livecloud.**{*;}2-keepclasscom.alivc.**{*;}
最后在 AndroidManifest 文件中添加所需权限:
1<uses-permissionandroid:name=”android.permission.INTERNET”/>2<uses-permissionandroid:name=”android.permission.RECORD_AUDIO”/>3<uses-permissionandroid:name=”android.permission.CAMERA”/>4<uses-permissionandroid:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>5<uses-permissionandroid:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/>6<uses-permissionandroid:name=”android.permission.MODIFY_AUDIO_SETTINGS”/>7<uses-permissionandroid:name=”android.permission.READ_PHONE_STATE”/>8<uses-permissionandroid:name=”android.permission.READ_EXTERNAL_STORAGE”/>9<uses-permissionandroid:name=”android.permission.BLUETOOTH”/>设置推流参数
创建 AlivcLivePushConfig 对象
1AlivcLivePushConfigmAlivcLivePushConfig=newAlivcLivePushConfig();
设置分辨率
1mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_540P);
设置码率
推流的码率控制有三种qualityMode模式可选:清晰度优先模式、流畅度优先模式和自定义模式
清晰度优先模式(AlivcQualityModeEnum.QM_RESOLUTION_FIRST):SDK内部会对码率参数进行配置,优先保障推流视频的清晰度。
流畅度优先模式(AlivcQualityModeEnum.QM_FLUENCY_FIRST):SDK内部会对码率参数进行配置,优先保障推流视频的流畅度。
自定义模式(AlivcQualityModeEnum.QM_CUSTOM):SDK会根据开发者设置的码率进行配置。
清晰度优先模式和流畅度优先模式是根据日常使用场景由SDK定义的一套比较适合该场景的推荐使用模式,这两种模式下帧率和编码码率都是由定义好的,不可以外部调节;自定义模式下需要设置视频的fps、目标码率、最小码率以及初始码率等参数。
1//清晰度优先模式 2mAlivcLivePushConfig.setQualityMode(AlivcQualityModeEnum.QM_RESOLUTION_FIRST); 3 4//流畅度优先模式 5mAlivcLivePushConfig.setQualityMode(AlivcQualityModeEnum.QM_FLUENCY_FIRST); 6 7//自定义模式,需要手动设置视频的fps、目标码率、最小码率以及初始码率等参数 8mAlivcLivePushConfig.setQualityMode(AlivcQualityModeEnum.QM_CUSTOM); 9//设置帧率10mAlivcLivePushConfig.setFps(AlivcFpsEnum.FPS_25);11//设置目标码率12mAlivcLivePushConfig.setTargetVideoBitrate(1200);13//设置最小码率14mAlivcLivePushConfig.setMinVideoBitrate(600);15//设置初始码率16mAlivcLivePushConfig.setInitialVideoBitrate(1000);创建推流并设置回调 1/**创建AlivcLivePusher**/ 2publicvoidinit(){ 3AlivcLivePushConfigpushConfig=getPushConfig(); 4try{ 5 6//创建AlivcLivePusher 7if(mAlivcLivePusher==null){ 8mAlivcLivePusher=newAlivcLivePusher(); 9}10mAlivcLivePusher.init(mContext.getApplicationContext(),pushConfig);1112//设置回调13//推流信息回调14mAlivcLivePusher.setLivePushInfoListener(this);15//网络状况回调16mAlivcLivePusher.setLivePushNetworkListener(this);17//背景音乐回调18mAlivcLivePusher.setLivePushBGMListener(this);19//推流错误信息回调20mAlivcLivePusher.setLivePushErrorListener(this);21//mAlivcLivePusher.setCustomFilter(this);22//mAlivcLivePusher.setCustomDetect(this);23}catch(IllegalArgumentExceptione){24e.printStackTrace();25}catch(IllegalStateExceptione){26e.printStackTrace();27}28}开始推流1publicvoidstartPush(finalStringurl){2mAlivcLivePusher.startPushAysnc(url);3}监听推流1@Override2publicvoidonStarted(){3Log.d(TAG,String.format(“onStarted”));4}56@Override7publicvoidonStoped(){8Log.d(TAG,String.format(“onStoped”));9}iOS 接入SDK 引入
通过 Cocopods 引入推流 SDK:pod ‘AlivcLivePusher’
添加请求权限:在 Info.plist 文件中添加麦克风和摄像头权限Privacy – Microphone Usage Description、Privacy – Camera Usage Description。
如果需要在后台推流,需要打开后台音频彩集模式。
SDK不支持bitcode,所以需要在工程中关闭bitcode选项
设置推流参数
创建 AlivcLivePushConfig 对象
1self.pushConfig=[[AlivcLivePushConfigalloc]init];
设置分辨率
至此我们就完成了阿里云最基础的直播推流功能代码开发,除些之外推流SDK还支持推图片流,纯音频流,还支持背景音乐播放、混音、降噪、耳返等等功能,具体可以查看官方文档。
下一节我们将通过阿里云容器服务将 AppServer 部署到 Kubernetes 上,同时接入播放器 SDK 和业务接口,让我们的 Demo 真正运行起来。
参考文档
视频直播 – 添加域名https://help.aliyun.com/document_detail/98296.html
视频直播 – 域名关联https://help.aliyun.com/document_detail/98299.html
视频直播 – 鉴权https://help.aliyun.com/document_detail/98300.html
视频直播 – 回放录制https://help.aliyun.com/document_detail/84931.html
Android SDK 集成https://help.aliyun.com/document_detail/94843.html
Android SDK 使用https://help.aliyun.com/document_detail/94844.html
iOS SDK 集成https://help.aliyun.com/document_detail/94821.html
iOS 推流 SDK 使用