一、申请指南
官网地址:https://www.aliyun.com/product/live
准备工作:
-
在阿里云进行ICP备案
已在其它ISP备案但未在阿里备案的也需重新接入,我这边资料齐全一次过大概花了7天。但这里有一个坑,阿里备案需要备案服务号,而直播这边不提供备案服务号,在线人工咨询、工单咨询后,给出的回复(2020/03/02)是目前只能去购买一台云服务器ECS(我们服务器没有部署在阿里云平台)。好在价格也不贵,低配200/年拿了个备案服务号。 -
OBSStudio
研发时测试推流
点击下载: OBSStudio -
PotPlayer\VLC Media Player
研发时测试播放
点击下载: PotPlayer
点击下载: VLC Media Player
二、配置推流地址\播放地址
1. 进入直播控制台,点击域名管理,点击添加域名(域名先需在阿里云备案)
2. 分别添加一个推流地址与播放地址(注意两个地址需不同)
三、配置鉴权信息
进入直播控制台,点击域名管理,而后分别配置推流域名和播放域名
1. 配置推流域名
a. 配置回调地址
官方说明: 推断流回调可以进行直播流流状态实时信息回调,及时通知用户推流或断流操作结果。
其中https://live.aliyunlive.com/pub为自己服务器地址,也就是配置的推流回调地址。
样例:
https://live.aliyunlive.com/pub? action=publish & app=xc.cdnpe.com & appname=test01 & id=test01 & ip=42.120.74.183 & node=cdnvideocenter010207116011.cm3
参数说明:
b.访问控制
点击同页面访问控制,在URL鉴权中再点击修改配置,然后设置一个鉴权KEY。推荐32位带大小写参。
2. 配置播放域名
a. 配置Https
点击HTTPS配置,上传证书即可(如无证书,可以参考我的另外一篇文章,可以免费领取一年阿里云的SSL证书)
b. 和推流域名同样,配置一个播放鉴权key(尽量不要与推流域名一样)
四、 测试播放
1. 使用地址生成器生成一个推流地址与播放地址
输入一个AppName(Path)和StreamName(Filename),点击生成,会得到推流地址和播放地址,分别丢如OBS和Potplayer,测试是否可以正常推拉流。(工具使用该篇文章后面讲解)
2. 自己组装推拉流地址
先看官方文档:
例如
域名:live.test.com
AppName: app
StreamName: test
Timestamp: 1583133237 (10位秒,在时间戳的前30分钟内,该鉴权key有效)
rand: 477b3bbc253f467b8def6711128c7bec (自定义随机字符,官方推荐去掉-的UUID,为进一步保证鉴权Key的安全,这里测试后得出同一流,推流的rand和播放的rand可以不同)
uid: 0 (官方说明:暂未使用,设置成 0 即可)
鉴权Key: 123456 (注意推流和播放的鉴权Key不同,上面已有讲解)
组合地址后为:
rtmp://live.test.com/app/test?auth_key=timestamp-rand-uid-md5hash
md5hash的生成方法为:
URI-Timestamp-rand-uid-PrivateKey(URI是用户的请求对象相对地址,不包含参数,如:/Filename)
HashValue = md5sum(sstring)
即为:
/app/test-1583133237-477b3bbc253f467b8def6711128c7bec-0-123456
取md5小写 (注意小写) = e732852bdc84dac82f055cfff833f7e1,就是PrivateKey
最后拼合地址为:
rtmp://live.test.com/app/test?auth_key=1583133237-477b3bbc253f467b8def6711128c7bec-0-e732852bdc84dac82f055cfff833f7e1
推流和播放的生成方法相同。
五、OBSStudio和PotPlayer的使用
1. OBSStudio
打开OBSStudio,点击文件 - 设置(或者右下角设置)-切换到[推流]选项卡,把服务改为自定义,服务器输入推流地址即可。
然后新增一个来源,测试的话摄像头比较好,容易观察和判断细节。
最后,点击开始推流后,左下角无错误提示,右下角有流量在走,即推流成功。
2. PotPlayer
确定正在推流后,打开PotPlayer,输入播放地址即可。
六、安卓的播放简单集成
这里使用阿里云提供的播放SDK:https://help.aliyun.com/document_detail/125579.html?spm=a2c4g.11186623.2.7.3b656381pv9iGi
1. 引入模块
工程build.gradle
allprojects {
repositories {
google()
jcenter()
mavenCentral()
// 添加阿里源
maven {url 'https://maven.aliyun.com/repository/releases'}
}
}
App build.grade
dependencies {
//https://help.aliyun.com/document_detail/124711.html?spm=a2c4g.11186623.6.1079.a9ea1bc7WxDrpL
//https://maven.aliyun.com/mvn/search
implementation 'com.aliyun.sdk.android:AliyunPlayer:4.7.3-full'
implementation 'com.alivc.conan:AlivcConan:1.0.2.1'
}
2. Activity源码
package com.itxca.test.live;
import android.graphics.Bitmap;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.aliyun.player.AliPlayer;
import com.aliyun.player.AliPlayerFactory;
import com.aliyun.player.IPlayer;
import com.aliyun.player.bean.ErrorInfo;
import com.aliyun.player.bean.InfoBean;
import com.aliyun.player.nativeclass.TrackInfo;
import com.aliyun.player.source.UrlSource;
import com.itxca.test.R;
import com.itxca.test.ui.bases.BaseActivity;
/**
* Project Name : test
* Package Name : com.itxca.test.live
* Create Time : 2020-03-02 11:05
* Create By : @author xIao
* Version : 1.0.0
**/
public class AliPlayActivity extends BaseActivity {
private SurfaceView surfaceView;
private AliPlayer aliyunVodPlayer;
@Override
public boolean isRegEventBus() {
return false;
}
@Override
protected int getLayoutId() {
return R.layout.activity_tx_play;
}
@Override
protected int getTitleBarId() {
return R.id.tb_title;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (aliyunVodPlayer != null) {
aliyunVodPlayer.release();
}
}
@Override
protected void initView() {
setTitle("直播播放");
}
@Override
protected void initData() {
initPlayer();
initSourceData();
}
private void initSourceData() {
//创建VidSts
UrlSource urlSource =new UrlSource();
urlSource.setTitle("测试001");
//替换该地址为你的播放地址
urlSource.setUri("rtmp://live.test.com/app/test?auth_key=1583119273-0-0-82d0b07300f2bd4aef2df7da0adf9798");
//设置播放源
aliyunVodPlayer.setDataSource(urlSource);
//准备播放
aliyunVodPlayer.prepare();
//播放
aliyunVodPlayer.start();
}
private void initPlayer() {
//如果播放的视频是通过播放器SDK安全下载后的本地文件,那么还需要设置一个加密校验信息(建议在Application中配置一次即可):
//PrivateService.initService(getApplicationContext(), "encryptedApp.dat的本地路径");
//创建播放器
aliyunVodPlayer = AliPlayerFactory.createAliPlayer(getApplicationContext());
//绑定view
surfaceView = findViewById(R.id.sv_live_player);
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
aliyunVodPlayer.setDisplay(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
aliyunVodPlayer.redraw();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
aliyunVodPlayer.setDisplay(null);
}
});
//设置回调
aliyunVodPlayer.setOnCompletionListener(new IPlayer.OnCompletionListener() {
@Override
public void onCompletion() {
//播放完成事件
}
});
aliyunVodPlayer.setOnErrorListener(new IPlayer.OnErrorListener() {
@Override
public void onError(ErrorInfo errorInfo) {
//出错事件
}
});
aliyunVodPlayer.setOnPreparedListener(new IPlayer.OnPreparedListener() {
@Override
public void onPrepared() {
//准备成功事件
}
});
aliyunVodPlayer.setOnVideoSizeChangedListener(new IPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(int width, int height) {
//视频分辨率变化回调
}
});
aliyunVodPlayer.setOnRenderingStartListener(new IPlayer.OnRenderingStartListener() {
@Override
public void onRenderingStart() {
//首帧渲染显示事件
}
});
aliyunVodPlayer.setOnInfoListener(new IPlayer.OnInfoListener() {
@Override
public void onInfo(InfoBean infoBean) {
//其他信息的事件,type包括了:循环播放开始,缓冲位置,当前播放位置,自动播放开始等
}
});
aliyunVodPlayer.setOnLoadingStatusListener(new IPlayer.OnLoadingStatusListener() {
@Override
public void onLoadingBegin() {
//缓冲开始。
}
@Override
public void onLoadingProgress(int percent, float kbps) {
//缓冲进度
}
@Override
public void onLoadingEnd() {
//缓冲结束
}
});
aliyunVodPlayer.setOnSeekCompleteListener(new IPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete() {
//拖动结束
}
});
aliyunVodPlayer.setOnSubtitleDisplayListener(new IPlayer.OnSubtitleDisplayListener() {
@Override
public void onSubtitleShow(long id, String data) {
//显示字幕
}
@Override
public void onSubtitleHide(long id) {
//隐藏字幕
}
});
aliyunVodPlayer.setOnTrackChangedListener(new IPlayer.OnTrackChangedListener() {
@Override
public void onChangedSuccess(TrackInfo trackInfo) {
//切换音视频流或者清晰度成功
}
@Override
public void onChangedFail(TrackInfo trackInfo, ErrorInfo errorInfo) {
//切换音视频流或者清晰度失败
}
});
aliyunVodPlayer.setOnStateChangedListener(new IPlayer.OnStateChangedListener() {
@Override
public void onStateChanged(int newState) {
//播放器状态改变事件
}
});
aliyunVodPlayer.setOnSnapShotListener(new IPlayer.OnSnapShotListener() {
@Override
public void onSnapShot(Bitmap bm, int with, int height) {
//截图事件
}
});
}
}
3. Layout源码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/layout_titlebar" />
<include layout="@layout/layout_state" />
<SurfaceView
android:id="@+id/sv_live_player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
七、总结
阿里云直播的基本集成基本上就完了,推流的话Github也有很多例子,就不再详述了。其实播放也可以不用阿里的SDK,只要支持Rtmp、Flv或者M3U8的播放器都可以。
简单集成会很快,在域名备案成功后1小时能把推拉流调试完成,测试直播。但是阿里的设置里面细节其实很多,包括自动截图、录播、导播等,官方都有详细介绍,跟着做就行了。
整个集成流程我耗时在没注意推流和拉流的鉴权key不同,导致生成的流一直无法使用,各位也别在这翻车了。
原帖地址,转载请注明:https://blog.csdn.net/hx7013/article/details/104611262