本章节介绍了拉流 SDK 进阶功能的接入方式,支持的进阶功能包括但不限于 RTM 协议拉流、QUIC 协议拉流、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。您可以根据实际业务需求,借助拉流 SDK 实现更复杂的功能。
真机调试:由于 SDK 使用了大量 Android 系统的音视频接口,这些接口在仿真模拟器下可能会出现异常,推荐您使用真机进行代码调试。
本节为您详细介绍如何使用拉流 SDK 进阶功能的实现,包括但不限于 RTM 协议拉流、QUIC 协议拉流、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。
视频直播拉流 SDK 支持 RTM 协议拉流,该功能需要配合火山引擎视频直播服务使用。详细信息可参考超低延时直播介绍。
注意
RTM 协议拉流不支持纯音频或纯视频流。
配置 RTM 拉流地址和 FLV 拉流地址进行播放。代码示例如下所示。
// 配置 RTM 地址 VeLivePlayerStream playStreamRTM = new VeLivePlayerStream(); playStreamRTM.url = "https://pull.example.com/live/stream.sdp"; playStreamRTM.format = VeLivePlayerFormatRTM; playStreamRTM.resolution = VeLivePlayerResolutionOrigin; playStreamRTM.streamType = VeLivePlayerStreamTypeMain; // 配置 FLV 地址 VeLivePlayerStream playStreamFLV = new VeLivePlayerStream(); playStreamFLV.url = "https://pull.example.com/live/stream.flv"; playStreamFLV.format = VeLivePlayerFormatFLV; playStreamFLV.resolution = VeLivePlayerResolutionOrigin; playStreamFLV.streamType = VeLivePlayerStreamTypeMain; // 创建 VeLivePlayerStreamData VeLivePlayerStreamData streamData = new VeLivePlayerStreamData(); streamData.mainStreamList = new ArrayList<>(); // 添加 RTM 流地址 streamData.mainStreamList.add(playStreamRTM); // 添加 FLV 流地址 streamData.mainStreamList.add(playStreamFLV); // 配置默认 format 和 protocol streamData.defaultFormat = VeLivePlayerFormatRTM; streamData.defaultProtocol = VeLivePlayerProtocolTLS; // 配置播放源 mLivePlayer.setPlayStreamData(streamData); // 开始播放 mLivePlayer.play();
视频直播拉流 SDK 支持 QUIC 协议拉流,该功能需要配合火山引擎视频直播服务使用。
使用视频直播控制台的地址生成器,生成 FLV 拉流地址。
配置 QUIC 拉流地址进行播放。代码示例如下所示。
// 配置 FLV 流地址 VeLivePlayerStreamData.VeLivePlayerStream playStreamFLV = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamFLV.url = "https://pull.example.com/live/stream.flv"; playStreamFLV.format = VeLivePlayerFormatFLV; playStreamFLV.resolution = VeLivePlayerResolutionOrigin; playStreamFLV.streamType = VeLivePlayerStreamTypeMain; // 创建播放源 VeLivePlayerStreamData streamData = new VeLivePlayerStreamData(); streamData.mainStreamList = new ArrayList<>(); // 添加 FLV 流 streamData.mainStreamList.add(playStreamFLV); // 配置默认 format 和 protocol streamData.defaultFormat = VeLivePlayerFormatFLV; streamData.defaultProtocol = VeLivePlayerProtocolQUIC; // 协议为 QUIC // 配置播放源 mLivePlayer.setPlayStreamData(streamData); // 开始播放 mLivePlayer.play();
说明
拉流 SDK 默认开启了 QUIC 协议拉流的失败降级策略,无需额外配置。如果 QUIC 协议拉流失败,SDK 将自动降级为 TCP 协议拉流。
播放器支持通过设置播放域名的 IP 地址进行拉流,以降低播放首帧时间。
请先获取直播播放地址并解析出 IP 地址。
使用播放器的 setUrlHostIP
接口将 IP 地址与域名关联起来,播放器将直接根据 IP 地址进行拉流播放。代码示例如下所示。
// 配置播放 URL mLivePlayer.setPlayUrl("https://pull.example.com/live/stream.flv"); // 添加 IP 地址和域名关联 List<String> valueList = new ArrayList<>(); valueList.add("xxx.xxx.xxx.xxx"); // IP 地址 Map<String, List<String>> map = new HashMap<>(); map.put("pull.example.com", valueList); // 配置 IP 地址 mLivePlayer.setUrlHostIP(map); // 开始播放 mLivePlayer.play();
主备流主要用于直播间容灾,通过配置主备两路直播流地址,在推流和分发环节使用主备流进行直播。播放器在接入时配置主备两路拉流地址,当主路地址拉流失败或者播放出错时,播放器会自动切换到备路地址进行播放。同样地,当备路地址播放出错时,播放器会切换回主路地址进行播放。主备地址可以来自同一直播服务商,也可以来自不同的直播服务商。
获取主流地址和备流地址,如果使用火山引擎视频直播服务,您可通过视频直播控制台的地址生成器,生成主备拉流地址。
// 配置主流地址 VeLivePlayerStreamData.VeLivePlayerStream playStreamMain = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamMain.url = "https://pull.example.com/live/主.flv"; playStreamMain.format = VeLivePlayerFormatFLV; playStreamMain.resolution = VeLivePlayerResolutionOrigin; playStreamMain.streamType = VeLivePlayerStreamTypeMain; // 流类型配置为主路 // 配置备流地址 VeLivePlayerStreamData.VeLivePlayerStream playStreamBackup = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamBackup.url = "https://pull.example.com/live/备.flv"; playStreamBackup.format = VeLivePlayerFormatFLV; playStreamBackup.resolution = VeLivePlayerResolutionOrigin; playStreamBackup.streamType = VeLivePlayerStreamTypeBackup; // 流类型配置为备路 // 创建播放源 VeLivePlayerStreamData streamData = new VeLivePlayerStreamData(); // 开启主备切换 streamData.enableMainBackupSwitch = true; // 添加主流 streamData.mainStreamList = new ArrayList<>(); streamData.mainStreamList.add(playStreamMain); // 添加备流 streamData.backupStreamList = new ArrayList<>(); streamData.backupStreamList.add(playStreamBackup); // 配置播放源 mLivePlayer.setPlayStreamData(streamData); // 开始播放 mLivePlayer.play();
onMainBackupSwitch
进行通知。代码示例如下所示。public void onMainBackupSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerStreamType streamType, VeLivePlayerError error) { // 主备切换回调通知 }
播放器支持配置多档位的直播拉流地址,通过接口可以实现多档位直播流的切换。
获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。
本文的接入说明以下列拉流地址为例。
档位 | 拉流地址 |
---|---|
源流(Orgin) | https://pull.example.com/live/123456.flv |
超清(UHD) | https://pull.example.com/live/123456_uhd.flv |
高清(HD) | https://pull.example.com/live/123456_hd.flv |
标清(SD) | https://pull.example.com/live/123456_sd.flv |
低清(LD) | https://pull.example.com/live/123456_ld.flv |
// 配置多档位流地址 VeLivePlayerStreamData.VeLivePlayerStream playStreamOrgin = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamOrgin.url = "https://pull.example.com/live/123456.flv"; playStreamOrgin.format = VeLivePlayerFormatFLV; playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位 playStreamOrgin.streamType = VeLivePlayerStreamTypeMain; VeLivePlayerStreamData.VeLivePlayerStream playStreamUHD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamUHD.url = "https://pull.example.com/live/123456_uhd.flv"; playStreamUHD.format = VeLivePlayerFormatFLV; playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位 playStreamUHD.streamType = VeLivePlayerStreamTypeMain; VeLivePlayerStreamData.VeLivePlayerStream playStreamHD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamHD.url = "https://pull.example.com/live/123456_hd.flv"; playStreamHD.format = VeLivePlayerFormatFLV; playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位 playStreamHD.streamType = VeLivePlayerStreamTypeMain; VeLivePlayerStreamData.VeLivePlayerStream playStreamSD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamSD.url = "https://pull.example.com/live/123456_sd.flv"; playStreamSD.format = VeLivePlayerFormatFLV; playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位 playStreamSD.streamType = VeLivePlayerStreamTypeMain; VeLivePlayerStreamData.VeLivePlayerStream playStreamLD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamLD.url = "https://pull.example.com/live/123456_ld.flv"; playStreamLD.format = VeLivePlayerFormatFLV; playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位 playStreamLD.streamType = VeLivePlayerStreamTypeMain; // 创建播放源 VeLivePlayerStreamData streamData = new VeLivePlayerStreamData(); // 添加多档位流 streamData.mainStreamList = new ArrayList<>(); streamData.mainStreamList.add(playStreamOrgin); streamData.mainStreamList.add(playStreamUHD); streamData.mainStreamList.add(playStreamHD); streamData.mainStreamList.add(playStreamSD); streamData.mainStreamList.add(playStreamLD); // 配置默认启播档位 streamData.defaultResolution = VeLivePlayerResolutionOrigin; // 配置播放源 mLivePlayer.setPlayStreamData(streamData); // 开始播放 mLivePlayer.play();
switchResolution
接口可以实现多个档位之间的手动切换。代码示例如下所示。mLivePlayer.switchResolution(VeLivePlayerResolutionUHD); // 切换到 UHD 档位
onResolutionSwitch
进行回调。代码示例如下所示。public void onResolutionSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerResolution resolution, VeLivePlayerError error, VeLivePlayerDef.VeLivePlayerResolutionSwitchReason reason) { // 档位切换回调 }
自适应码率(Adaptive Bit-Rate,简称 ABR)是一种流媒体传输技术,通过一系列算法策略,动态切换不同档位媒体流,以达到适应网络带宽变化,防止观众在观看直播过程产生卡顿,提升播放质量和观看体验。
注意
ABR 功能只适用于 FLV 格式流。
获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。
本文的接入说明以下列拉流地址为例。
档位说明 | 拉流地址 | 码率(kbps) |
---|---|---|
源流(Orgin) | https://pull.example.com/live/123456.flv | 2500 |
超清(UHD) | https://pull.example.com/live/123456_uhd.flv | 2500 |
高清(HD) | https://pull.example.com/live/123456_hd.flv | 1000 |
标清(SD) | https://pull.example.com/live/123456_sd.flv | 800 |
低清(LD) | https://pull.example.com/live/123456_ld.flv | 500 |
// 配置多档位流地址 VeLivePlayerStreamData.VeLivePlayerStream playStreamOrgin = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamOrgin.url = "https://pull.example.com/live/123456.flv"; playStreamOrgin.format = VeLivePlayerFormatFLV; playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位 playStreamOrgin.streamType = VeLivePlayerStreamTypeMain; playStreamOrgin.bitrate = 2500; VeLivePlayerStreamData.VeLivePlayerStream playStreamUHD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamUHD.url = "https://pull.example.com/live/123456_uhd.flv"; playStreamUHD.format = VeLivePlayerFormatFLV; playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位 playStreamUHD.streamType = VeLivePlayerStreamTypeMain; playStreamUHD.bitrate = 2500; VeLivePlayerStreamData.VeLivePlayerStream playStreamHD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamHD.url = "https://pull.example.com/live/123456_hd.flv"; playStreamHD.format = VeLivePlayerFormatFLV; playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位 playStreamHD.streamType = VeLivePlayerStreamTypeMain; playStreamHD.bitrate = 1000; VeLivePlayerStreamData.VeLivePlayerStream playStreamSD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamSD.url = "https://pull.example.com/live/123456_sd.flv"; playStreamSD.format = VeLivePlayerFormatFLV; playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位 playStreamSD.streamType = VeLivePlayerStreamTypeMain; playStreamSD.bitrate = 800; VeLivePlayerStreamData.VeLivePlayerStream playStreamLD = new VeLivePlayerStreamData.VeLivePlayerStream(); playStreamLD.url = "https://pull.example.com/live/123456_ld.flv"; playStreamLD.format = VeLivePlayerFormatFLV; playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位 playStreamLD.streamType = VeLivePlayerStreamTypeMain; playStreamLD.bitrate = 500; // 创建播放源 VeLivePlayerStreamData streamData = new VeLivePlayerStreamData(); // 添加多档位流 streamData.mainStreamList = new ArrayList<>(); streamData.mainStreamList.add(playStreamOrgin); streamData.mainStreamList.add(playStreamUHD); streamData.mainStreamList.add(playStreamHD); streamData.mainStreamList.add(playStreamSD); streamData.mainStreamList.add(playStreamLD); // 配置默认启播档位 streamData.defaultResolution = VeLivePlayerResolutionOrigin; // 开启 ABR streamData.enableABR = true; // 配置播放源 mLivePlayer.setPlayStreamData(streamData); // 开始播放 mLivePlayer.play();
onResolutionSwitch
进行回调。代码示例如下所示。public void onResolutionSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerResolution resolution, VeLivePlayerError error, VeLivePlayerDef.VeLivePlayerResolutionSwitchReason reason) { // 档位切换回调 }
截图功能允许您在播放器中截取当前直播画面并生成一张图片。
snapshot
接口可以实现截图功能。截图仅在播放器播放成功后可以生效。代码示例如下所示。int result = mLivePlayer.snapshot();
onSnapshotComplete
进行回调,同时将截取的图片数据传递给回调方法。代码示例如下所示。public void onSnapshotComplete(VeLivePlayer player, Bitmap bitmap) { // 截图成功回调,参数 bitmap 为截图的图片数据 }
SEI(Supplemental Enhancement Information)是直播流中的附加信息,它可以用于传递自定义的数据或元数据。
play
方法之前,您可以通过配置播放器的 enableSei
属性来开启 SEI 信息的接收功能。代码示例如下所示。// 创建播放器初始化配置 VeLivePlayerConfiguration config = new VeLivePlayerConfiguration(); // 打开 SEI 开关 config.enableSei = true; // 初始化配置 mLivePlayer.setConfig(config);
onReceiveSeiMessage
进行回调,并将接收到的 SEI 信息传递给回调方法。代码示例如下所示。public void onReceiveSeiMessage(VeLivePlayer player, String message) // SEI 回调 }
通过订阅解码后的视频数据,您可以获取视频帧数据并进行自定义的处理和渲染操作。播放器支持多种视频帧数据的回调,并提供了相应的参数和格式选项。
视频帧像素格式和视频数据封装格式的枚举和含义如下表所示。
格式类型 | 枚举 | 说明 |
---|---|---|
视频帧像素格式 | VeLivePlayerPixelFormatRGBA32 | RGBA32 |
VeLivePlayerPixelFormatTexture | 2D 纹理 | |
视频数据封装格式 | VeLivePlayerVideoBufferTypeByteBuffer | ByteBuffer |
VeLivePlayerVideoBufferTypeByteArray | ByteArray | |
VeLivePlayerVideoBufferTypeTexture | 纹理 |
配置订阅视频数据前,请您根据需要选择格式组合。格式组合需要遵循下表中提供的 VeLivePlayerPixelFormat 和 VeLivePlayerVideoBufferType 的对应关系。
像素格式/封装格式 | VeLivePlayerPixelFormatRGBA32 | VeLivePlayerPixelFormatTexture |
---|---|---|
VeLivePlayerVideoBufferTypeByteBuffer | √ | × |
VeLivePlayerVideoBufferTypeByteArray | √ | × |
VeLivePlayerVideoBufferTypeTexture | × | √(性能最优) |
1.您可以调用播放器的 enableVideoFrameObserver
接口开启或关闭视频帧数据订阅功能。接口参数说明如下表所示。
参数 | 类型 | 说明 |
---|---|---|
enable | boolean | 是否开启视频帧回调。 |
pixelFormat | VeLivePlayerPixelFormat | 视频帧像素格式。 |
bufferType | VeLivePlayerVideoBufferType | 视频数据封装格式。 |
代码示例如下所示。
// mLivePlayer.enableVideoFrameObserver(true, VeLivePlayerPixelFormatRGBA32, VeLivePlayerVideoBufferTypeByteBuffer);
onRenderVideoFrame
进行回调。代码示例如下所示。public void onRenderVideoFrame(VeLivePlayer player, VeLivePlayerVideoFrame videoFrame) { // 视频帧数据回调 }
VeLivePlayerVideoFrame
参数说明如下表所示。
参数 | 类型 | 说明 |
---|---|---|
bufferType | VeLivePlayerVideoBufferType | 视频帧数据封装格式 |
pixelFormat | VeLivePlayerPixelFormat | 视频帧像素格式 |
width | int | 视频帧的宽度,单位为 px |
height | int | 视频帧的高度,单位为 px |
pts | long | 视频帧的渲染时间戳,单位为 ms |
texture | VeLivePlayerVideoTexture | 当 bufferType 为 VeLivePlayerVideoBufferTypeTexture 时的视频数据,承载用于 OpenGL 渲染的纹理数据 |
buffer | ByteBuffer | 当 bufferType 为 VeLivePlayerVideoBufferTypeByteBuffer 时的视频数据,承载用于 JNI 层的 Direct Buffer |
data | byte[] | 当 bufferType 为 VeLivePlayerVideoBufferTypeByteArray 时的视频数据,承载用于 Java 层的字节数组数据 |
通过订阅解码后的音频数据,您可以获取音频帧数据并进行自定义的处理和渲染操作。
播放器支持音频帧数据帧回调格式为 PCM Float32 类型,数据封装格式为 ByteArray。
VeLivePlayerAudioBufferType | 音频数据封装格式 |
---|---|
VeLivePlayerAudioBufferTypeByteArray | ByteArray |
enableAudioFrameObserver
接口开启或关闭音频帧数据订阅功能。接口参数说明如下表所示。参数 | 类型 | 说明 |
---|---|---|
enable | boolean | 是否开启音频帧回调。 |
enableRendering | boolean | 是否开启播放器渲染。当不需要播放器内部进行音频播放时,可以将该参数值配置为 false 。 |
代码示例如下所示。
// 订阅音频帧数据,打开播放器内部音频渲染 mLivePlayer.enableAudioFrameObserver(true, true);
onRenderAudioFrame
接口进行回调。代码示例如下所示。void onRenderAudioFrame(VeLivePlayer player, VeLivePlayerAudioFrame audioFrame) { // 音频帧数据回调 }
VeLivePlayerAudioFrame
参数说明如下表所示。
参数 | 数据类型 | 说明 |
---|---|---|
bufferType | VeLivePlayerAudioBufferType | 音频帧数据封装格式 |
sampleRate | int | 音频采样率,单位为 Hz |
channels | int | 声道数 |
bitDepth | int | 音频位深度 |
pts | long | 音频渲染时间戳,单位为 ms |
buffer | byte[] | PCM 音频数据 |
samples | int | 音频采样点个数 |
超分,即超分辨率技术(Super-Resolution, SR)是指从观测到的低分辨率图像重建出相应的高分辨率图像的过程,移动端实时超分,是指利用算法技术在端上对低分辨率的帧进行实时重建,产生高分辨率的帧显示在屏幕上,从而改善视频内容的细节与对比度,全面提升视频的播放清晰度和观看体验的优化手段。
setEnableSuperResolution(boolean enable)
方法开启或者关闭拉流超分功能,默认状态为关闭。参数 | 类型 | 说明 |
---|---|---|
enable | boolean | 是否开启超分功能。 |
onStreamFailedOpenSuperResolution
进行回调。代理方法签名如下所示。void onStreamFailedOpenSuperResolution(VeLivePlayer player, VeLivePlayerError error);
如果开启超分失败,可能有以下几种原因。
直播拉流 SDK 支持调用火山引擎 HTTPDNS 服务对拉流地址的预解析,以此来降低播放首帧时长。
开通云解析 DNS 服务。
左侧导航栏选择实例信息,记录您的鉴权密钥,包含 SERVICE ID 和 SECRET KEY。
在拉流客户端调用 setVeHttpDNSAuth
方法配置调用 HTTPDNS 服务需要使用的鉴权密钥,代码示例如下所示。
VeLiveCommon.setVeHttpDNSAuth(getApplicationContext(), "http_dns_serviceID", "http_dns_key")
调用 prefetchDomains
方法进行域名解析,解析成功后的 IP 地址会自动设置给播放器,代码示例如下所示。
List<String> domains = new ArrayList<String>(); domains.add("xxx.pull.com"); domains.add("yyy.pull.com"); VeLiveCommon.prefetchDomains(domains);