1.前言 阿里云提供了 RTMP 直播服务,有两种计费方式,不包括视频截图,存储量费用。 (1)按量计算:流量阶梯单价 x 流量 假设1000人同时在线并同时观看视频1小时,流量计算方式为:1000(人) x 0.5(视频码率Mbps) x 3600(观看时间/秒)x 1024 8(将Mbps换算为GB) = 219.7GB,0.29(阶梯流量单价:元/GB)x 219.7(流量:GB) = 63.71 元
适合突发流量的情况。
(2)按峰值带宽计算:峰值带宽阶梯单价 X 峰值 假设1000人同时在线并同时观看视频1小时,流量计算方式为:1000(人) x 0.5(视频码率Mbps) = 500Mbps。1.00(峰值带宽阶梯单价:元/Mbps)X 500 (Mbps) = 500 元
适合全天都平稳进行直播的场景。
超低延时直播RTS按 “峰值带宽” 计费 1.32 元,还需要加上一个转码费用,如果在 web 端播放 artc 协议,需要做一个转码。
参考文章: 【1】.视频直播 详细价格信息 【2】.视频直播产品定价 流量估计: 【3】.直播转码费用
2.配置域名 这里就要到 视频直播 -> 推/播流域名管理 界面增加域名,其实还挺麻烦的,推流和拉流两个域名还不能一样。
配置完了推流和拉流地址,需要将推流地址和拉流地址进行关联,在拉流地址里面选择 “域名管理” 可以配置推流地址。
参考文章: 【1】.验证域名归属权
3.控制台生成地址 有两种方式生成推流和拉流地址,(1) 控制台,(2) 代码生成。控制台生成 可以直接生成推流和拉流地址 (1) 登录视频直播控制台。
(2) 在左侧导航栏选择直播工具箱 > 地址生成器。
(3) 在直播地址生成器页签,完成以下配置获取推流地址和播放地址。 选择播流域名,关联的推流域名,输入 AppName,StreamName 然后点击开始生成,就可以获取一个 rtmp 地址,可以将这个地址配置到 OBS 中进行直播了。
参考文章: 【1】.生成推流地址和播放地址 表格中RTS地址,即超低延时直播RTS地址,使用前需开通超低延时直播功能。 【2】.直播推流 1.使用OBS推流;2.使用阿里云直播Demo推流;
4.代码生成地址 通过API自定义拼接地址,下面的代码基本上可以使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 import java.math.BigInteger;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import org.apache.commons.lang3.*;public class Create_Live_Url { public static String md5 (String param) { if (param == null || param.length() == 0 ) { return null ; } try { MessageDigest md5 = MessageDigest.getInstance("MD5" ); md5.update(param.getBytes()); byte [] byteArray = md5.digest(); BigInteger bigInt = new BigInteger (1 , byteArray); String result = bigInt.toString(16 ); while (result.length() < 32 ) { result = "0" + result; } return result; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null ; } public static void generate_push_url (String pushDomain,String pushKey,String appName,String streamName,long expireTime) { String pushUrl = "" ; if (pushKey=="" ) { pushUrl = "rtmp://" +pushDomain+"/" +appName+"/" +streamName; }else { long timeStamp = System.currentTimeMillis()/1000L + expireTime; String stringToMd5 = "/" +appName+"/" +streamName+"-" +Long.toString(timeStamp)+"-0-0-" +pushKey; String authKey = md5(stringToMd5); pushUrl = "rtmp://" +pushDomain+"/" +appName+"/" +streamName+"?auth_key=" +Long.toString(timeStamp)+"-0-0-" +authKey; } System.out.println("推流地址是: " +pushUrl); } public static void general_pull_url (String pullDomain,String pullKey,String appName,String streamName,long expireTime) { String rtmpUrl = "" ; String hlsUrl = "" ; String flvUrl = "" ; String artcUrl = "" ; if (pullKey == "" ) { rtmpUrl = "rtmp://" +pullDomain+"/" +appName+"/" +streamName; hlsUrl = "http://" +pullDomain+"/" +appName+"/" +streamName+".m3u8" ; flvUrl = "http://" +pullDomain+"/" +appName+"/" +streamName+".flv" ; }else { long timeStamp = System.currentTimeMillis()/1000L + expireTime; String rtmpToMd5 = "/" +appName+"/" +streamName+"-" +Long.toString(timeStamp)+"-0-0-" +pullKey; String rtmpAuthKey = md5(rtmpToMd5); rtmpUrl = "rtmp://" +pullDomain+"/" +appName+"/" +streamName+"?auth_key=" +Long.toString(timeStamp)+"-0-0-" +rtmpAuthKey; String hlsToMd5 = "/" +appName+"/" +streamName+".m3u8-" +Long.toString(timeStamp)+"-0-0-" +pullKey; String hlsAuthKey = md5(hlsToMd5); hlsUrl = "http://" +pullDomain+"/" +appName+"/" +streamName+".m3u8" +"?auth_key=" +Long.toString(timeStamp)+"-0-0-" +hlsAuthKey; String flvToMd5 = "/" +appName+"/" +streamName+".flv-" +Long.toString(timeStamp)+"-0-0-" +pullKey; String flvAuthKey = md5(flvToMd5); flvUrl = "http://" +pullDomain+"/" +appName+"/" +streamName+".flv" +"?auth_key=" +Long.toString(timeStamp)+"-0-0-" +flvAuthKey; String artcToMd5 = "/" +appName+"/" +streamName+"-" +Long.toString(timeStamp)+"-0-0-" +appKey; String artcAuthKey = md5(artcToMd5); artcUrl = "http://" +pullDomain+"/" +appName+"/" +streamName+"?auth_key=" +Long.toString(timeStamp)+"-0-0-" +artcAuthKey; } System.out.println("RTMP播放地址为: " +rtmpUrl); System.out.println("m3u8播放地址为: " +hlsUrl); System.out.println("flv播放地址为: " +flvUrl); } public static void main (String[] args) { String appName = RandomStringUtils.randomAlphanumeric(5 );; String streamName = RandomStringUtils.randomAlphanumeric(5 );; long expireTime = 3600L ; String pullDomain = "mxl-pull.pier39.cn" ; String pullKey = "querty1234" ; String pushDomain = "mxl-push.pier39.cn" ; String pushKey = "querty123" ; Create_Live_Url.general_pull_url(pullDomain, pullKey, appName, streamName, expireTime); Create_Live_Url.generate_push_url(pushDomain, pushKey, appName, streamName, expireTime); } }
需要注意: (1)鉴权的有效时长应该和控制台配置的有效时长相同,默认是 1440 分钟,也就是一天。
(2)需要注意 pushKey 和 pullKey 不一样,需要在直播域名的详情页的访问控制中进行查看。
参考文章: 【1】.RTMP协议接入流程 RTMP、HLS、HTTP-FLV 协议对比:RTMP 延迟1s-3s;HLS:>10s;HTTP-FLV:1s-3s。 【2】.推流、拉流与播流 1.准备工具和环境;2.按需拉取直播流;3.获取推流与播放地址;4.推流设置与操作;5.播放设置与查看 【3】.如何通过PHP或Java代码生成推流地址和播放地址? 【4】.配置URL鉴权 【5】.鉴权代码示例
5.超低延时 登录视频直播控制台, (1) 在左侧导航栏选择推/播流域名管理,进入域名管理页面。 (2) 单击需要开启超低延时直播的播流域名操作列的域名配置,进入域名管理页面。 (3) 选择直播管理 > 超低延时播放 RTS。 (4) 打开RTS播放开关。 (5) 选择版本低延时直播(RTS 1.0),打开H5自动转码开关。
参考文章: 【1】.超低延时直播简介 【2】.开通超低延时直播功能 【3】.生成推流地址和播放地址 支持RTMP、FLV、M3U8、RTS格式,推荐使用RTS格式地址播放。示例:RTS:artc://example.aliyundoc.com/app/stream?auth_key={鉴权串} 【4】.URL鉴权
6.配置https 使用超低延迟 rts 播放,需要为拉流地址配置 ssl 证书,否则无法播放。我在操作的时候,又遇到了问题,问题就是在阿里云签发证书的时候,总是出现失败的情况。 (1)购买证书 去阿里云 ssl 证书管理页面申请一个免费的证书。如果在阿里云购买了证书之后,可以选择一键部署,直接部署到拉流端域名。
(2)配置直播域名 在视频直播 -> 推/播流域名管理,选择拉流域名,选择 HTTPS 配置,开启HTTPS证书。
(3)验证证书是否生效 设置完成待证书1分钟后全网生效,使用HTTPS方式访问资源,如果浏览器中出现锁样的标识,则HTTPS安全加速生效。
参考文章: 【1】.Demo体验 您需要为域名配置SSL证书,* 如果您在体验过程中出现问题,可优先前往直播控制台工具箱>自助问题排查中快速诊断常见推/播流问题,并提供解决建议。 【2】.配置HTTPS安全加速 这里是阿里云详细的操作步骤。 【3】.部署证书至阿里云云产品(云产品部署)
6.超低延迟播放 可以到 问题自查 查看自己的直播是否可用。 (1) 安装
1 pnpm add aliyun-aliplayer --save
(2) 配置license 直播工具箱 -> SDK管理 -> 我的授权,需要先购买 License,然后创建应用,将 license 和应用绑定就可以了。(多个应用共用一个license)
1 2 3 4 license : { domain : 'xxx.tech' , key : 'xx' , },
(3) 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <div id ="J_prismPlayer" > </div > <script > import Aliplayer from 'aliyun-aliplayer' ;import 'aliyun-aliplayer/build/skins/default/aliplayer-min.css' ;var player = new Aliplayer ({ id : 'J_prismPlayer' , source : '<your play URL>' , isLive : true , license : { domain : 'xxx' , key : 'xxx' }, },function (player ){ console .log ('The player is created.' ) }); player.on ('rtsTraceId' , function (event ) { console .log ('EVENT rtsTraceId' , event.paramData ); }) player.on ('rtsFallback' , function (event ) { console .log (' EVENT rtsFallback' , event.paramData ); }) </script >
参考文章: 【1】.接口说明 这是另外一种组件,只支持 rtc。 【2】.快速使用阿里云ARTC Web SDK 这里是使用的 web sdk 进行的直播,使用这种方式就少了一个视频转码的费用,如果使用 h5 播放,还有一个视频转码的费用。 【3】.超低延时直播(RTS)视频播放 超低延时直播(RTS)使用URL方式播放,无需额外设置参数。 【4】.阿里云 Vue 播放器 demo 这是阿里云播放器进行播放的例子,可以直接使用播放器直接播放。 【5】.进阶功能 【6】.Aliplayer阿里云Web播放器 -Aliplayer 错误码 4004 地址不存在
7.样式修改 参考文章: 【1】.Web播放器常见问题 此黑边为播放器容器的背景色,可以通过给video标签设置css属性object-fit: cover;来解决该问题。
8.视频截图 参考文章: 【1】.阿里云Aliplayer高级功能介绍(一):视频截图 使用 canvas 进行了截图处理。
9.视频转码 超低延时直播Web RTS SDK对音视频解码存在以下限制。
不支持视频含B帧,否则会出现画面跳跃。
不支持AAC编码,否则会出现噪音。
建议您使用RTS超低延时直播时推流配置为不含B帧。如果您无法控制直播推流输入情况,可以使用RTS转码功能自定义设置转码的分辨率、帧率、码率、音频编码格式、B帧等参数。
参考文章: 【1】.RTS转码 具体详情,请参见超低延时直播。
10.在线查询 我根据在线的Demo,然后写了代码,结果总是出现问题,后来只能找工单了,找工单知道了要配置自定义权限策略,我配置了全部权限,也可以配置某一个权限,然后配置给了 RAM,结果还是无法调用,还是报错:Server response has a bad format type: RAW。 (1) 创建自定义授权策略 需要先通过权限控制台,新增一个授权策略,比如读取权限。可以通过选择进行配置,也可以通过编写json进行配置。
(2) 配置RAM 在控制台上,新增了一个RAM账号,然后配置了 AliyunLiveFullAccess、AliyunSTSAssumeRoleAccess 两个权限,再加上自定义的权限策略。需要在搜索栏中重新搜索
(3) 获取 AK 在RAM用户配置页面,创建了一个 AccessKey,然后获取到了 Secret
(4) 编写代码 根据官网提示,我编写了下面的代码,结果总是报错:Server response has a bad format type: RAW,这个代码应该不是正确的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import com.aliyuncs.CommonRequest;import com.aliyuncs.CommonResponse;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.exceptions.ServerException;import com.aliyuncs.http.MethodType;import com.aliyuncs.profile.DefaultProfile;public class AliYunUtil { public static void getLiveStatus () { DefaultProfile profile = DefaultProfile.getProfile("cn-qingdao" , "xx" , "xxx" ); IAcsClient client = new DefaultAcsClient (profile); CommonRequest request = new CommonRequest (); request.setSysMethod(MethodType.POST); request.setSysDomain("xx" ); request.setSysVersion("2016-11-01" ); request.setSysAction("DescribeLiveStreamsOnlineList" ); request.putQueryParameter("RegionId" , "cn-hangzhou" ); try { CommonResponse response = client.getCommonResponse(request); System.out.println(response.getData()); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { e.printStackTrace(); } } }
后来工单给了另外的方法,这才调用成功了,至于给的官方的例子为什么调用不成功,估计只有阿里云自己的工程师知道了,主要代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void getLiveStatus () { DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou" , "xx" , "xx" ); IAcsClient client = new DefaultAcsClient (profile); DescribeLiveStreamsOnlineListRequest request = new DescribeLiveStreamsOnlineListRequest (); request.setRegionId("cn-hangzhou" ); request.setDomainName("xx" ); try { DescribeLiveStreamsOnlineListResponse response = client.getAcsResponse(request); System.out.println(JSONObject.toJSONString(response)); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { System.out.println("ErrCode:" + e.getErrCode()); System.out.println("ErrMsg:" + e.getErrMsg()); System.out.println("RequestId:" + e.getRequestId()); } }
参考文章: 【1】.DescribeLiveStreamsOnlineList查询域名在线流列表 这是查询在线流列表的问题。 【2】.Server response has a bad format type: RAW 没有答案 【3】.自定义授权 创建自定义访问策略 【4】.授权信息 授权信息,这里写了一些通用的授权策略结构,还有一些直播查询需要的权限、资源类型访问级别等说明。 【5】.DescribeLiveStreamsOnlineList 这是阿里云官网给的测试方法,我尝试之后,可以在线调用成功,但是实际上我把代码拷贝过来,无法运行成功。
问题 1.直播黑屏 在同一个页面中,创建两个实例,结果就会出现其中一个实例黑屏的问题,这个问题是偶发的,我开始的时候以为是 id 的问题,我把这个 id 号改为了随机,结果也还是不行。
参考文章: 【1】.阿里云播放器Aliplayer-WEB走坑中
2.直播卡顿 在手机的webview中进行视频播放的时候,总是出现卡顿的现象,不知道为什么。官方给出的结论有以下几种可能:
(1) 上行带宽不足或网络抖动,导致的数据发送速率下降,无法达到流畅播放的帧率要求 (2) 码率、帧率或编码档位设置的过高,但硬件条件存在限制,导致编码速度变慢,无法达到流畅播放的帧率要求。 (3) 推流过程中会有一定的CPU损耗,硬件配置较差的低端手机,在推流过程中若整体CPU 使用率超过80%以上,画面会出现不同程度的卡顿,花屏等现象,会影响到视频的采集,同时也会影响到用户端的观看。 (4) 视频采集参数的设置过低。
【尝试方案】 (1)尝试增加播放器参数
1 2 3 enableHardwareAcceleration: true , // 开启硬件加速 decodeFrameLimit: 30, // 强制解码帧率上限 videoBufferLength: 0.3, // 降低缓冲延迟
(2)尝试配置rts转码,结果因为大疆设备端的帧率过高,无法进行转码。
(3)尝试找官方解决,官方说解决不了,叫我自己解决。
1 2 3 4 5 6 7 看起来您这个源流我们的转码不支持解码重新编码了,这个问题目前看从直播侧解决不了了 对于卡顿的问题,如果是只有帧率高,可以从播放器侧做优化,即配置 enableHardwareAcceleration: true, // 开启硬件加速 decodeFrameLimit: 30, // 强制解码帧率上限 videoBufferLength: 0.3, // 降低缓冲延迟 这边找到之前的一个案例,也是大疆的无人机推流,分析推过来的流,在每个 P 帧前面都有插入 SEI ,导致播放卡顿,要在推流端把这个 SEI 和 AUD 去掉 再推流
参考文章: 【1】.视频直播出现卡顿现象 【2】.直播出错恢复处理 【3】.RTS转码 【4】.超低延时直播快速入门
3.新版本报错 最新的版本 v.2.28.5,好像引用了一个私有依赖,导致安装之后运行报错,出现的错误莫名其妙:“./node_modules/.pnpm/aliyun-aliplayer@2.28.5/node_modules/aliyun-aliplayer/build/aliplayer-min.js 6:881,Module parse failed: Unexpected token (6:881) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders”
【解决方案】 (1)所以最好就是在 package.json 中锁定版本
1 "aliyun-aliplayer" : "2.27.1"
(2)后来经过和阿里云的工程师进行沟通,最后还是叫他们升级了版本,到了 @2.30.1 这个版本就解决问题了。
4.域名不匹配E008 这个问题比较奇怪,我去看了看,发现是 license 配置的问题。在后台配置页面,多个应用只有一个 key,但是在前端每一个域名要配置不同的domain。
1 2 license.domain 申请License时填写的站点域名。例如:在example.com/product/vod中嵌入Web播放器SDK,则请输入该站点的域名example.com。 license.key License申请成功后分配的密钥,为49位的字符串。