本文档主要介绍使用移动直播 SDK 实现直播播放的方法。
针对开发者的接入反馈的高频问题,腾讯云提供有更加简洁的 API-Example 工程,方便开发者可以快速的了解相关 API 的使用,欢迎使用。
所属平台 | GitHub 地址 |
---|---|
iOS | Github |
Android | Github |
下载 SDK 开发包,并按照 SDK 集成指引 将 SDK 嵌入您的 App 工程中。
视频云 SDK 中的 TXLivePlayer 模块负责实现直播播放功能。
TXLivePlayer _txLivePlayer = [[TXLivePlayer alloc] init];
接下来我们要给播放器的视频画面找个地方来显示,iOS 系统中使用 view 作为基本的界面渲染单位,所以您只需要准备一个 view 并调整好布局就可以了。
// 用 setupVideoWidget 给播放器绑定决定渲染区域的 view,其首个参数 frame 在 1.5.2 版本后已经被废弃
[_txLivePlayer setupVideoWidget:CGRectMake(0, 0, 0, 0) containView:_myView insertIndex:0];
内部原理上讲,播放器并不是直接把画面渲染到您提供的 view (示例代码中的 _myView)上,而是在这个 view 之上创建一个用于 OpenGL 渲染的子视图(subView)。
如果您要调整渲染画面的大小,只需要调整您所常见的 view 的大小和位置即可,SDK 会让视频画面跟着您的 view 的大小和位置进行实时的调整。
如何做动画?针对 view 做动画是比较自由的,不过请注意此处动画所修改的目标属性应该是 transform 属性而不是 frame 属性。
[UIView animateWithDuration:0.5 animations:^{
_myView.transform = CGAffineTransformMakeScale(0.3, 0.3); // 缩小1/3
}];
NSString* flvUrl = @"http://2157.liveplay.myqcloud.com/live/2157_xxxx.flv";
[_txLivePlayer startPlay:flvUrl type:PLAY_TYPE_LIVE_FLV];
可选值 | 枚举值 | 含义 |
---|---|---|
PLAY_TYPE_LIVE_RTMP | 0 | 传入的 URL 为 RTMP 直播地址 |
PLAY_TYPE_LIVE_FLV | 1 | 传入的 URL 为 FLV 直播地址 |
PLAY_TYPE_LIVE_RTMP_ACC | 5 | 低延迟链路地址(仅适合于连麦场景) |
PLAY_TYPE_VOD_HLS | 3 | 传入的 URL 为 HLS(m3u8) 播放地址 |
关于 HLS(m3u8)在 App 上我们不推荐使用 HLS 这种播放协议播放直播视频源(虽然它很适合用来做点播),因为延迟太高,在 App 上推荐使用 LIVE_FLV 或者 LIVE_RTMP 播放协议。
结束播放时,如果要推出当前的 UI 界面,要记得用 removeVideoWidget 销毁 view 控件,否则会产生内存泄露或闪屏问题。
// 停止播放
[_txLivePlayer stopPlay];
[_txLivePlayer removeVideoWidget]; // 记得销毁 view 控件
本节将介绍常见直播播放功能的使用方式。
view:大小和位置
如需修改画面的大小及位置,直接调整 setupVideoWidget 的参数 view 的大小和位置,SDK 会让视频画面跟着您的 view 的大小和位置进行实时的调整。
setRenderMode:铺满 or 适应
可选值 | 含义 |
---|---|
RENDER_MODE_FILL_SCREEN | 将图像等比例铺满整个屏幕,多余部分裁剪掉,此模式下画面不会留黑边,但可能因为部分区域被裁剪而显示不全。 |
RENDER_MODE_FILL_EDGE | 将图像等比例缩放,适配最长边,缩放后的宽和高都不会超过显示区域,居中显示,画面可能会留有黑边。 |
setRenderRotation:画面旋转
可选值 | 含义 |
---|---|
RENDER_ROTATION_PORTRAIT | 正常播放(Home 键在画面正下方) |
RENDER_ROTATION_LANDSCAPE | 画面顺时针旋转270度(Home 键在画面正左方) |
对于直播播放而言,并没有真正意义上的暂停,所谓的直播暂停,只是画面冻结和关闭声音,而云端的视频源还在不断地更新着,所以当您调用 resume 的时候,会从最新的时间点开始播放,这跟点播是有很大不同的(点播播放器的暂停和继续与播放本地视频文件时的表现相同)。
// 暂停
[_txLivePlayer pause];
// 恢复
[_txLivePlayer resume];
此功能可以在推流端将一些自定义 message 随着音视频线路直接下发到观众端,适用场景例如:
(1)冲顶大会:推流端将题目下发到观众端,可以做到“音-画-题”完美同步。
(2)秀场直播:推流端将歌词下发到观众端,可以在播放端实时绘制出歌词特效,因而不受视频编码的降质影响。
(3)在线教育:推流端将激光笔和涂鸦操作下发到观众端,可以在播放端实时地划圈划线。
通过如下方案可以使用此功能:
-(void) onPlayEvent:(int)EvtID withParam:(NSDictionary *)param {
[self asyncRun:^{
if (EvtID == PLAY_EVT_GET_MESSAGE) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([_delegate respondsToSelector:@selector(onPlayerMessage:)]) {
[_delegate onPlayerMessage:param[@"EVT_GET_MSG"]];
}
});
}
}];
}
通过调用 snapshot 您可以截取当前直播画面为一帧屏幕,此功能只会截取当前直播流的视频画面,如果您需要截取当前的整个 UI 界面,请调用 iOS 的系统 API 来实现。
截流录制是直播播放场景下的一种扩展功能:观众在观看直播时,可以通过单击录制按钮把一段直播的内容录制下来,并通过视频分发平台(例如腾讯云的点播系统)发布出去,这样就可以在微信朋友圈等社交平台上以 UGC 消息的形式进行传播。
// 如下代码用于展示直播播放场景下的录制功能
//
// 指定一个 TXVideoRecordListener 用于同步录制的进度和结果
_txLivePlayer.recordDelegate = recordListener;
// 启动录制,可放于录制按钮的响应函数里,目前只支持录制视频源,弹幕消息等目前还不支持
[_txLivePlayer startRecord: RECORD_TYPE_STREAM_SOURCE];
// ...
// ...
// 结束录制,可放于结束按钮的响应函数里
[_txLivePlayer stopRecord];
日常使用中,网络情况在不断发生变化。在网络较差的情况下,最好适度降低画质,以减少卡顿;反之,网速比较好,可以观看更高画质。
传统切流方式一般是重新播放,会导致切换前后画面衔接不上、黑屏、卡顿等问题。使用无缝切换方案,在不中断直播的情况下,能直接切到另条流上。
清晰度切换在直播开始后,任意时间都可以调用。调用方式如下
// 正在播放的是流http://5815.liveplay.myqcloud.com/live/5815_62fe94d692ab11e791eae435c87f075e.flv,
// 现切换到码率为 900kbps 的新流上
[_txLivePlayer switchStream:@"http://5815.liveplay.myqcloud.com/live/5815_62fe94d692ab11e791eae435c87f075e_900.flv"];
说明:清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 提交工单 申请使用。
时移功能是腾讯云推出的特色能力,可以在直播过程中,随时回退到任意直播历史时间点观看,并能在此时间点一直观看直播。非常适合游戏、球赛等互动性不高,但观看连续性较强的场景。
// 设置直播回看前,先调用 startPlay
// 开始播放 ...
[TXLiveBase setAppID:@"1253131631"]; // 配置 appId
[_txLivePlayer prepareLiveSeek]; // 后台请求直播起始时间
配置正确后,在 PLAY_EVT_PLAY_PROGRESS 事件里,当前进度就不是从0开始,而是根据实际开播时间计算而来。
调用 seek 方法,就能从历史事件点重新直播
[_txLivePlayer seek:600]; // 从第10分钟开始播放
接入时移需要在后台打开2处配置:
说明:时移功能处于公测申请阶段,如您需要可 提交工单 申请使用。
腾讯云 SDK 的直播播放(LVB)功能,并非基于 ffmpeg 做二次开发, 而是采用了自研的播放引擎,所以相比于开源播放器,在直播的延迟控制方面有更好的表现,我们提供了三种延迟调节模式,分别适用于:秀场,游戏以及混合场景。
三种模式的特性对比
控制模式 | 卡顿率 | 平均延迟 | 适用场景 | 原理简述 |
---|---|---|---|---|
极速模式 | 较流畅偏高 | 2s- 3s | 美女秀场(冲顶大会) | 在延迟控制上有优势,适用于对延迟大小比较敏感的场景 |
流畅模式 | 卡顿率最低 | >= 5s | 游戏直播(企鹅电竞) | 对于超大码率的游戏直播(例如吃鸡)非常适合,卡顿率最低 |
自动模式 | 网络自适应 | 2s-8s | 混合场景 | 观众端的网络越好,延迟就越低;观众端网络越差,延迟就越高 |
三种模式的对接代码
TXLivePlayConfig* _config = [[TXLivePlayConfig alloc] init];
// 自动模式
_config.bAutoAdjustCacheTime = YES;
_config.minAutoAdjustCacheTime = 1;
_config.maxAutoAdjustCacheTime = 5;
// 极速模式
_config.bAutoAdjustCacheTime = YES;
_config.minAutoAdjustCacheTime = 1;
_config.maxAutoAdjustCacheTime = 1;
// 流畅模式
_config.bAutoAdjustCacheTime = NO;
_config.cacheTime = 5;
[_txLivePlayer setConfig:_config];
// 设置完成之后再启动播放
说明:更多关于卡顿和延迟优化的技术知识,可以阅读 视频卡顿怎么办?
支持400ms左右的超低延迟播放是腾讯云直播播放器的一个特点,它可以用于一些对时延要求极为苛刻的场景,例如远程夹娃娃或者主播连麦等,关于这个特性,您需要知道:
该功能是不需要开通的
该功能并不需要提前开通,但是要求直播流必须位于腾讯云,跨云商实现低延时链路的难度不仅仅是技术层面的。
播放地址需要带防盗链
播放 URL 不能用普通的 CDN URL, 必须要带防盗链签名,防盗链签名的计算方法见 txTime&txSecret。
播放类型需要指定 ACC
在调用 startPlay 函数时,需要指定 type 为 PLAY_TYPE_LIVE_RTMP_ACC,SDK 会使用 RTMP-UDP 协议拉取直播流。
该功能有并发播放限制
目前最多同时10路并发播放,设置这个限制的原因并非是技术能力限制,而是希望您只考虑在互动场景中使用(例如连麦时只给主播使用, 或者夹娃娃直播中只给操控娃娃机的玩家使用),避免因为盲目追求低延时而产生不必要的费用损失(低延迟线路的价格要贵于 CDN 线路)。
Obs 的延时是不达标的
推流端如果是 TXLivePusher,请使用 setVideoQuality 将quality
设置为 MAIN_PUBLISHER 或者 VIDEO_CHAT。Obs 的推流端积压比较严重,是无法达到低延时效果的。
该功能按播放时长收费
本功能按照播放时长收费,费用跟拉流的路数有关系,跟音视频流的码率无关,具体价格请参考 价格总览。
播放器 SDK 通过 URL 字符串播放视频,URL 中本身不包含视频信息。为获取相关信息,需要通过访问云端服务器加载到相关视频信息,因此 SDK 只能以事件通知的方式将视频信息发送到您的应用程序中,更多内容参见 事件监听。
例如您可以通过onNetStatus
的NET_STATUS_VIDEO_WIDTH
和NET_STATUS_VIDEO_HEIGHT
获取视频的宽和高。具体使用方法见 状态反馈(onNetStatus)。
您可以为 TXLivePlayer
对象绑定一个 TXLivePlayListener
,之后 SDK 的内部状态信息均会通过 onPlayEvent
(事件通知)和 onNetStatus
(状态反馈)通知给您。
事件 ID | 数值 | 含义说明 |
---|---|---|
PLAY_EVT_CONNECT_SUCC | 2001 | 已经连接服务器 |
PLAY_EVT_RTMP_STREAM_BEGIN | 2002 | 已经连接服务器,开始拉流(仅播放 RTMP 地址时会抛送) |
PLAY_EVT_RCV_FIRST_I_FRAME | 2003 | 网络接收到首个可渲染的视频数据包(IDR) |
PLAY_EVT_PLAY_BEGIN | 2004 | 视频播放开始,如果有转菊花什么的这个时候该停了 |
PLAY_EVT_PLAY_LOADING | 2007 | 视频播放 loading,如果能够恢复,之后会有 BEGIN 事件 |
PLAY_EVT_GET_MESSAGE | 2012 | 用于接收夹在音视频流中的消息,详情参考 消息接收 |
事件 ID | 数值 | 含义说明 |
---|---|---|
PLAY_EVT_PLAY_END | 2006 | 视频播放结束 |
PLAY_ERR_NET_DISCONNECT | -2301 | 网络断连,且经多次重连亦不能恢复,更多重试请自行重启播放 |
如何判断直播已结束?
基于各种标准的实现原理不同,很多直播流通常没有结束事件(2006)抛出,此时可预期的表现是:主播结束推流后,SDK 会很快发现数据流拉取失败(WARNING_RECONNECT),然后开始重试,直至三次重试失败后抛出 PLAY_ERR_NET_DISCONNECT 事件。
所以2006和-2301都要监听,用来作为直播结束的判定事件。
如下的这些事件您可以不用关心,我们只是基于白盒化的 SDK 设计理念,将事件信息同步出来
事件 ID | 数值 | 含义说明 |
---|---|---|
PLAY_WARNING_VIDEO_DECODE_FAIL | 2101 | 当前视频帧解码失败 |
PLAY_WARNING_AUDIO_DECODE_FAIL | 2102 | 当前音频帧解码失败 |
PLAY_WARNING_RECONNECT | 2103 | 网络断连, 已启动自动重连(重连超过三次就直接抛送 PLAY_ERR_NET_DISCONNECT 了) |
PLAY_WARNING_RECV_DATA_LAG | 2104 | 网络来包不稳:可能是下行带宽不足,或由于主播端出流不均匀 |
PLAY_WARNING_VIDEO_PLAY_LAG | 2105 | 当前视频播放出现卡顿 |
PLAY_WARNING_HW_ACCELERATION_FAIL | 2106 | 硬解启动失败,采用软解 |
PLAY_WARNING_VIDEO_DISCONTINUITY | 2107 | 当前视频帧不连续,可能丢帧 |
PLAY_WARNING_DNS_FAIL | 3001 | RTMP-DNS 解析失败(仅播放 RTMP 地址时会抛送) |
PLAY_WARNING_SEVER_CONN_FAIL | 3002 | RTMP 服务器连接失败(仅播放 RTMP 地址时会抛送) |
PLAY_WARNING_SHAKE_FAIL | 3003 | RTMP 服务器握手失败(仅播放 RTMP 地址时会抛送) |
通知每秒都会被触发一次,目的是实时反馈当前的推流器状态,它就像汽车的仪表盘,可以告知您目前 SDK 内部的一些具体情况,以便您能对当前网络状况和视频信息等有所了解。
评估参数 | 含义说明 |
---|---|
NET_STATUS_CPU_USAGE | 当前瞬时 CPU 使用率 |
NET_STATUS_VIDEO_WIDTH | 视频分辨率 - 宽 |
NET_STATUS_VIDEO_HEIGHT | 视频分辨率 - 高 |
NET_STATUS_NET_SPEED | 当前的网络数据接收速度 |
NET_STATUS_NET_JITTER | 网络抖动情况,抖动越大,网络越不稳定 |
NET_STATUS_VIDEO_FPS | 当前流媒体的视频帧率 |
NET_STATUS_VIDEO_BITRATE | 当前流媒体的视频码率,单位 kbps |
NET_STATUS_AUDIO_BITRATE | 当前流媒体的音频码率,单位 kbps |
NET_STATUS_CACHE_SIZE | 缓冲区(jitterbuffer)大小,缓冲区当前长度为0,说明离卡顿就不远了 |
NET_STATUS_SERVER_IP | 连接的服务器 IP |
本页内容是否解决了您的问题?