首页 腾讯云动态正文

移动直播技术知多少:基础原理解析 & 腾讯云直播接入

云返利网 腾讯云动态 2020-08-21 21:08:16 7 0 腾讯云服务












本文可以了解到

移动端视频直播相关的基础知识,以及如何利用腾讯云直播 SDK 搭建自己的直播系统。

前言

1. 视频时代已经来临

当今的互联网,视频已经成为一股洪流,冲刷着每一个人。

2020 年,由于新型冠状病毒疫情的爆发,视频直播互动更是一飞冲天,在网购、游戏、教育、金融等等方面都呈现爆发式发展。

可见音视频相关的技术,已经是我们不得不去了解的内容了。

2. 视频开发包括哪些内容

移动端的音视频开发一般有:短视频和视频直播互动。

在本人的【】系列文章中,主要讲解的就是「短视频开发」相关的知识。

而「直播」涉及到的技术,更加庞大,可以说是「短视频开发」的一个超集,因为它不仅涉及到本地视频的编辑,还涉及到直播服务器的架设,以及面对不稳定网络的优化等等,搭建一个直播系统并非易事。

那么你肯定要问了,既然很难,那我直接用第三方的 SDK 就可以了,干嘛还要学习这些晦涩难懂的视频知识?

3. 为什么学习直播基础知识

如果不了解基本知识,直接接入第三方的 SDK 可以吗?当然可以!

但俗话说得好:工欲善其事,必先利其器

如果不了解其中原理,在未来遇到问题时,要么难以有效地解决,要么需要付出比现在成倍的努力。

一、直播基础知识

最原始的直播系统其实并没有想象的那么复杂,无非就是主播端将音视频数据推送到服务器,观众端则从服务器拉取数据播放。

1. 基础流程

通过下面这个数据流程图,能清晰地看到整个直播的过程。

可以看到,「主播客户端」处理的事情,其实就是短视频开发中最重要的内容:

流程 详细操作
音视频数据采集 通过摄像头和麦克风采集
音视频滤镜 通过 OpenGL 和 SoundTouch 等工具实现音视频编辑
音视频编码 通过系统硬编码 或 FFmpeg 软编码,将数据编码为 H264 和 AAC
数据封装打包 将编码好的数据封装成指定的格式

唯一不一样的地方,短视频会将封装好的数据保存到本地,直播则是通过 推流协议 将数据推送到服务器。

关于 H264 、AAC 、封装格式 等知识,不清楚的可以查看这篇文章【】。

  • 推流

推流,是直播中的一个术语,意思是将流媒体数据推送到服务器。如何推流,关键就在于使用的推流协议。

  • 拉流

拉流,指的是「观众端」流媒体数据的拉取,同样也需要通过约定的拉流协议来拉取。

2. 直播协议

直播协议包含了上面提到的 「推流」和「拉流」协议。

主要有一下三种:

  • RTMP

RTMP 全名:Real Time Messaging Protocol,实时消息传送协议。是 Adobe 公司开发的,用于 Flash Player 和服务器间之间传输音视频数据。RTMP 是基于 TCP开发的,属于应用层的协议,默认端口为 1935 。

RTMP 主要特点是实时性好,延时比较低(1~3s)。既可以用来推流,也可以用来拉流。

但是由于其基于 TCP 长链接协议,默认端口非公共端口,可能会被防火墙拦截。

RTMP 视频数据封装格式为 flv 。

  • HTTP-FLV

HTTP-FLV,从其命名可以大概看出工作模式。即:将音视频数据封装为 flv 格式,通过 HTTP 长链接协议传输。既然是基于 HTTP ,其默认端口就是 80,可以直接穿透防火墙。

其传输方式和 RTMP 一样,只是将协议更换为 HTTP,所以实时性也比较好。

由于 HTTP-FLV 的特点,非常适合用于 App 直播拉流。

  • HLS

HLS:HTTP Live Streaming。是苹果公司推出的基于 HTTP 的流媒体传输协议,视频封装格式是 ts,在 iOS 和 Mac 支持比较好。

与 RTMP 和 HTTP-FLV 不同的是,HSL 是切片传输,它会将视频切为一个个小的 ts 文件,并将切片信息记录在 .m3u8 文件中。

拉流客户端根据 .m3u8 中的 ts 索引信息,按顺序下载播放。

由于其切片的特点,会导致比较大的延迟,在实时性要求比较高的情况下,效果不好。

以上,就是在直播系统中经常使用到的三大协议。

综合以上特点,推流的时候,经常使用的是 RTMP 协议;拉流播放的时候,经常使用的是 HTTP-FLV 和 HLS 协议。

3. 直播服务器

有了协议,那么客户端和服务器就可以通讯了,怎么样搭建服务器呢?

服务器:一般都是 Nginx + 协议拓展模块。

协议拓展模块

i. nginx-rtmp-module ,不支持 http-flv;

ii. nginx-http-flv-module,兼容nginx-rtmp-module,并支持 http-flv 直播;

iii. srs(simple-rtmp-server),支持三种协议。

搭建服务器也是一个比较繁琐的过程,涉及到的知识也很多,本文不再深入,网上也有很多相关资料可查看。

二、直播中的重难点

在直播中,有几个非常重要的地方,会直接影响直播效果,导致用户流失。

1. 首屏时间

首屏时间,即从观众打开直播,到看到画面呈现出来的时间。影响这个时间的是 H264 编码中的一个概念: GOP 。

  • GOP

全称:Group of Picture。即一组帧组成的一个序列。

在 H264 中,分别有 I帧、P帧、B帧 三种帧类型。

GOP 就是由一个 I帧 和多个 P帧 或 B帧 组成的一组相近的画面 。

解码器可以直接解码 I帧 ,但是 P帧 和 B帧 必须依赖 I帧,或者前后的 P 或 B 才能解码。

首次连上直播间时,需要抛弃掉 P 和 B 帧,等待 I帧

所以,影响首屏时间最重要的因素就是 I帧,也就是两个 GOP 之间的间隔时间。

GOP 间隔的设置并非越小越好,太小则两个 I帧 之间的 P/B帧 越少,压缩率越低,画面质量越差,需要做好权衡。

2. 稳定性问题

我们知道网络是不稳定的,经常会出现网速慢,甚至断网的问题,所以稳定性优化也是非常重要的。比如以下几个方面:

  • 码率控制

同样分辨率下,码率越高,视频越清晰,同时需要的带宽也越大。相反,码率越低,视频越模糊,数据越小。

  • 弱网优化

根据不同的网速切换不同的码率进行播放等。

  • 断线重连

网络断开时的重联机制。

3. 全局负载均衡

随着业务的发展,如果主播和观众的数量越来越多以后,系统可能会面临高并发情景,按照上面介绍的最简单的系统,可能就扛不住了。

直播卡顿,甚至系统奔溃,将直接影响公司的声誉。解决这种情况的一个好办法就是使用 CDN 。

  • CDN 内容分发

解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播。

关于 CDN 可参考:CDN是什么?使用CDN有什么优势?

加入 CDN 后,整个直播系统架构如下:

三、其他

除了以上提到的内容,当今的直播系统还要包括以下内容:录制转码鉴黄截屏权鉴防盗回声消除连麦 等等,整套下来,需要非常多的知识储备,以及大量的时间精力,才能完成。

大部分公司其实很难完成,而国内大厂们则利用自己强大的研发能力,提供了各自的 SDK ,大大降低了直播门槛。

实际上,一些知名的直播公司,也是利用了第三方的 SDK 来搭建自己的直播系统的,比如斗鱼、龙珠直播、now直播等等,都是利用了腾讯云直播平台搭建的。

下面,就来看看如何使用腾讯云直播 SDK 来搭建直播系统。

四、使用腾讯云直播 SDK ,搭建直播系统

先通过腾讯云直播的架构图,了解一下腾讯云直播提供了哪些功能。

可以看到,腾讯云直播中提供了最基础的 推流拉流录制 ,转码 ,点播,以及 推流加速 和 CDN加速。除了这些,还有 控制台,以及更加灵活的 API 控制接口等等。

基本上,一个直播系统该有的功能基本都具有了。

1. 开通云直播服务

要使用腾讯云直播功能,需要先注册腾讯云账号,完成注册后,进入控制台,然后搜索「云直播」,打开对应的页面,点击【申请开通】即可开通云直播服务。

开通后,会赠送 20GB 国内播放流量,可以用来测试。

  • 申请移动端 License

想要在 Android/iOS 手机上使用云直播,需要先申请对应的 License 。当然了,这是需要付费才能使用的。

不过腾讯提供了一个免费的测试版 License ,可以免费使用 28 天。这里使用测试版的 License 进行演示。具体如下:

进入「云直播」控制台后,点击左侧的「直播 SDK」-「License」。

点击「立即申请」,填写 App 名字Android 包名iOS Bundle ID

填好以后,点击「确定」,得到 Key 和 LiscenseUrl,这两个值在后面接入 SDK 的时候将会用到。

  • 添加自有域名

虽然腾讯云直播已经搭建好了直播服务器,但是 工信部 规定,直播需要备案域名,所以如果没有服务器和域名的话,需要先购买服务器,注册域名,然后对域名申请备案。

需要注意的是:云直播需要两个不同的域名,一个用作推流,一个用于播放。

腾讯云已经为我们提供了一个 推流域名,所以我们其实只需要提供一个域名用于播放就可以了。

添加流程如下:

「云直播控制台」- 「域名管理」-「添加域名」

添加完成后,会生成域名对应的 CNAME(CNAME 很关键,下面详细讲解)。

到这里域名就配置完毕了。

  • 配置CNAME

如果你一个 “纯粹” 的移动端开发者,不怎么了解服务端的话,你肯定会觉得很奇幻:刚刚配置的播放域名有什么用呢?它是怎么和腾讯云的服务器进行关联的呢?

关键的地方就在这个 CNAME 上。

我们知道,手机/PC 在访问一个域名的时候,会向 DNS 发起请求,普通情况下,DNS 会将域名解析成 IP 地址,然后返回给 手机/PC ,接着通过这个 IP 发起真正的请求。

但是,实际上并非总是这样的,我们可以给一个 域名A 配置一个 别名 ,这个别名也是一个 域名B 。



当客户端对A域名发起请求时,DNS 会找到 A ,说:“给我 IP 吧”,这时候 A 会告诉 DNS :“我没有,你去找 B域名要吧”。


DNS 转向 B ,并且获取到了 B 的 IP 地址,然后返回给客户端,客户端对 B 的 IP 发起了请求。


这时候的 A域名 就变成了类似一个中转站的东西,对 A域名 的请求,实际上访问的是 B域名。

CNAME 就是 别名 的意思。也就是说,上面腾讯云生成的 CNAME 域名,是不能直接访问的,还需要把它和我们自己备案的 播放域名 进行关联。

当我们访问自己的 播放域名 的时候,实际上是访问了腾讯云的直播服务器。

弄清楚了这层关系以后,配置就很简单了。

至于怎么关联,各大云服务提供商都会提供 CNAME 的配置,按照云服务提供商的说明进行配置就可以了。

这也说明了,腾讯云直播可以绑定任意的云服务,你可以使用腾讯云的,也可以使用阿里云的。只要备案好,并配置 CNAME 即可。

2. 集成 SDK

完成了以上配置以后,一个基础版的直播服务就开通了。接下来,只需在客户端集成 SDK 就可以实现推流和拉流播放了。

以 Android 端为例,说明整个集成过程。

  • 依赖配置

腾讯云提供了多种集成方式,jar/aar/gradle 依赖,推荐使用 gradle 依赖,方便简单,在 app/build.gradle 添加:

dependencies { implementation 'com.tencent.liteavsdk:LiteAVSDK_Smart:latest.release'}

配置 so 架构,腾讯云直播支持 armeabi 、 armeabi-v7a 和 arm64-v8a,你可以选择这几个架构都适配,也可以选择其中的一个架构,在 app/build.gradle 添加:

defaultConfig { ndk { abiFilters "armeabi", "armeabi-v7a", "arm64-v8a" }}
  • 配置打包参数

在 app/build.gradle 中配置

android {
//省略其他... packagingOptions { pickFirst '**/libc++_shared.so' doNotStrip "*/armeabi/libYTCommon.so" doNotStrip "*/armeabi-v7a/libYTCommon.so" doNotStrip "*/x86/libYTCommon.so" doNotStrip "*/arm64-v8a/libYTCommon.so" } //......}
  • 配置权限

在 AndroidManifest.xml 中配置

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-feature android:name="android.hardware.Camera"/><uses-feature android:name="android.hardware.camera.autofocus" />
  • 初始化SDK

在 Application 类中配置 License 的 Key 和 LicenseUrl

class App : Application() { override fun onCreate() { super.onCreate()  // 替换成控制台获取到的 licence url val licenceURL = "http://license.vod2.myqcloud.com/license/v1/xxxxx"  // 替换成控制台获取到的 licence key val licenceKey = "e90e0872aaeb7797xxxxxxxxx"   TXLiveBase.getInstance().setLicence(this, licenceURL, licenceKey) }}

3. 推流与拉流

实现推流和拉流非常简单,腾讯云已经把功能都封装好了。

推流:摄像头/麦克风数据采集、编码、视频渲染、推送数据。

拉流:拉取数据、解码、渲染播放。

我们要做的就是简单地调用一下 API 。

3.1 实现数据推流

直播 SDK 提供了一个 View 用于视频的播放显示:TXCloudVideoView。把它放到 xml 中即可,SDK 会根据 TXCloudVideoView 的宽高和视频的宽高,做对应的自适应缩放。

// activity_push.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<com.tencent.rtmp.ui.TXCloudVideoView android:id="@+id/tx_cloud_video_view" android:layout_width="match_parent" android:layout_height="match_parent" />
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="推流" android:onClick="startPushing"/></androidx.constraintlayout.widget.ConstraintLayout>

接着,在 Activity 中初始化推流工具,并把 TXCloudVideoView 绑定到 SDK ,实现摄像头预览。

class VideoPushActivity : AppCompatActivity() { private lateinit var mLivePusher: TXLivePusher
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_push) initPusher() }
private fun initPusher() { val mLivePushConfig = TXLivePushConfig() mLivePusher = TXLivePusher(this) // 一般情况下不需要修改 config 的默认配置 mLivePusher.config = mLivePushConfig
mLivePusher.startCameraPreview(tx_cloud_video_view) }
fun startPushing(v: View) { val rtmpURL = "rtmp://2157.livepush.myqcloud.com/live/demo?txSecret=39193bda8a439ba8852baf9bce1fde39&txTime=5E8DF4FF" val ret = mLivePusher.startPusher(rtmpURL.trim()) if (ret == -5) { Log.i("VideoPushActivity", "startRTMPPush: license 校验失败") } }
override fun onDestroy() { super.onDestroy() mLivePusher.stopPusher() mLivePusher.stopCameraPreview(true) }}

是不是非常简单,初始化完毕后,只要把推流地址给到推流工具,启动推流就搞定了。

当然了,你还可以做更多的配置,比如

  • 通过 mLivePusher.setPushListener(this) 来监听推送状态和网络状态,详见【官方文档】;

  • 通过 TXLivePushConfig 来配置旋转角度、设置水印、帧率、码率等等,非常丰富的参数配置,详见【官方文档】;

  • 通过 mLivePusher.getBeautyManager() 获取到美颜工具 TXBeautyManager可用于配置美颜相关的内容,不过这个方法是需要另外付费的。

最后,要注意的是,在退出推流页面的时候,需要在 onDestroy 中停止推流,并关闭、释放摄像头。

3.2 实现拉流播放

接下来,看看如何播放上面的推流视频。

视频的播放显示,依然是通过 TXCloudVideoView 。

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<com.tencent.rtmp.ui.TXCloudVideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放" android:onClick="startPlaying"/>
</androidx.constraintlayout.widget.ConstraintLayout>

同样的,在 Activity 中把 TXCloudVideoView 绑定给拉流工具。

// VideoPlayerActivity
class VideoPlayerActivity : AppCompatActivity() { private lateinit var mLivePlayer: TXLivePlayer
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initPlayer() }
private fun initPlayer() { //创建 player 对象 mLivePlayer = TXLivePlayer(this)
//关联 player 对象与界面 view mLivePlayer.setPlayerView(video_view) }
fun startPlaying(v: View) { val flvUrl = "http://2157.liveplay.myqcloud.com/live/demo.flv" mLivePlayer.startPlay(flvUrl, TXLivePlayer.PLAY_TYPE_LIVE_FLV) }}

拉流播放的过程也是非常简单,配置好拉流地址,启动播放就可以了。

需要注意的是,在 App 端,目前只支持 RMPT 和 FLV 两种播放格式,在启动播放的时候,需要指定对应的格式。

mLivePlayer.startPlay(flvUrlTXLivePlayer.PLAY_TYPE_LIVE_FLV)mLivePlayer.startPlay(flvUrl, TXLivePlayer.PLAY_TYPE_LIVE_RTMP)

当然了,你也可以通过一些配置来达到自己的播放需求。比如:

  • mLivePlayer.setRenderRotation(TXLiveConstants.RENDER_ROTATION_LANDSCAPE) 设置横屏播放;

  • mLivePlayer.setRenderMode(int mode) 设置画面拉升模式:平铺模式/自适应模式;

  • mLivePlayer.setPlayListener(this) 监听播放状态和网络状态。

详见【官方文档】

3.3 生成推拉流地址
  • 地址格式

从上面推拉流的地址可以看出地址的组合格式,具体如下图:

注意

只要符合上图规则的 URL 地址,腾讯云直播就认为是正确的,就可以正常推流和拉流。

前面四个参数很简单,根据自己的需求配置就可以了。

关键在于最后面的 权鉴 参数。

  • 权鉴

权鉴的用途是:防盗推/播!

腾讯云直播默认情况下,推流已经设置了权鉴,拉流是没有设置权鉴的。

️ 注意

权鉴不是必填参数,也就是说,如果不启动权鉴,这个参数是可以去掉的,一样可以推拉流。

但是,没有权鉴的情况下,人家只要知道了服务器域名,就可以按照地址格式,拼接出合规的地址,直接就可以推拉流了。

言外之意就是,你的服务器被人盗了

而直播 SDK 的计费方式恰恰就是根据播放流量来计费的,如果被人家随便拉流播放的话,必然会造成损失。

// 无权鉴推流地址
rtmp://2157.livepush.myqcloud.com/live/demo

// 有权鉴推流地址
rtmp://2157.livepush.myqcloud.com/live/demo?txSecret=39193bda8a439ba8852baf9bce1fde39&txTime=5E8DF4FF
  • 开启权鉴

开启权鉴的方式也很简单,可以通过控制台或调用 API 设置。

️ 注意

一般控制台设置只在测试的时候使用,生产环境下建议是通过自己的服务端调用 API 来配置权鉴 key ,并保持动态更新。

这里只是测试,我们就用控制台来配置。

「云直播控制台」-「域名管理」-「在要开启权鉴播放域名上,点击管理」-「访问控制」-「编辑」-「开启权鉴」-「设置主key、备key、过期时间」。

其中:

主key 很重要,用来参与推拉流地址中权鉴的计算。

备用key 主要用于当 主key 泄漏以后,可用 备用key 来生成地址,并且更新 主key 。

️ 注意

权鉴的 key 千万不能泄露,只有自己和腾讯云知道,这样双方才能对权鉴中 MD5 的加密值进行验证。泄漏以后要赶紧更新。

  • 权鉴计算

从地址格式拼接图已经知道,权鉴的格式是:

txSecrect=Md5(key+StreamName+txTime)&txTime=xxxx

txTime:到期时间的 UNIX 时间戳。

比如过期时间为 2020-04-28 23:59:59,时间戳为 1586361599 。时间戳可以进一步转换为 16 进制,比如 1586361599 的 16 进制为 5E8DF4FF。

因此,

txTime = 1586361599



txTime = 5E8DF4FF

️ 注意

拉流地址的 txTime 的计算有所不同,它的值等于【设置的时间 + 权鉴key 设置的过期时间】。

例如设置的过期时间为 2020-04-28 00:00:00权鉴key 的过期时间是 10s ,那么拉流地址真实的过期时间为:2020-04-28 00:00:10(UNIX时间戳十六进制为 5EA7018A)。

假设 权鉴key 为 123456 ,StreamName 为 demo,那么

txSecrect = MD5(12345demo5EA7018A) = 08472000d6fb5b5b2f2dc61583900287

搞清楚了地址的规则和权鉴的原理,就可以获取推拉流相应的地址了。

有两种方式:

  1. 云直播控制台生成(主要用于测试)

  2. 自己拼接生成(用于生产,根据需求来生成)

  • 控制台生成方式

在「云直播控制台」-「辅助工具」-「地址生成器」,可选择生成推流或者拉流地址,如下:

其中,

AppName:应用名,默认为live,根据自己的需求配置。

StreamName :直播通道名字,根据需求填写,比如主播的用户ID。

过期时间 :直播通道的有效时间,过了这个时间,则无法再推送或者拉流。

点击「生成地址」,控制台自动生成好推流和拉流地址和权鉴,如下:

  • 手动拼接方式

我们已经知道了地址的规则,那么自己来拼接也是可以的,而且在生产环境中也只能通过这种方法,因为我们不可能每次开启直播的时候,都要去控制台生成一个地址。

所以,只要按照上面讲解的规则生成地址就可以了,并且地址的生成应该放到我们自己系统的服务器中,而不是 App 中,这样才能避免泄漏权鉴key。

请求流程如下:

至此,一个简单的直播系统就搭建完成了。

如果你想要实现一些高级的效果,比如滤镜、添加水印,但是你又不想付费,那也是有办法的,通过 SDK 自定义渲染接口,就可以实现,前提是你有 OpenGL 基础

下面就通过一个灰色滤镜和添加水印,简单介绍一下如何自定义渲染。

4. 自定义视频渲染

目前视频渲染基本都是使用 OpenGL 实现的,腾讯云直播也不例外。

先来看下 SDK 提供的 推流 自定义渲染接口。

TXLivePusher 可以设置一个回调接口 VideoCustomProcessListener ,其接口定义如下:

public interface VideoCustomProcessListener { /** * @param textureId: 原视频纹理 ID * @param width: 视频宽 * @param height: 视频高 * return 新视频画面纹理 ID */ int onTextureCustomProcess(int textureId, int width, int height);
void onDetectFacePoints(float[] points);
void onTextureDestoryed();}

重点是第一个接口 onTextureCustomProcess ,第一个参数是一个 OpenGL 的纹理 ID,这个纹理保存了原视频画面,另外两个参数是画面的宽和高。

返回值也是一个纹理 ID,这个纹理就是经过处理后的视频画面的纹理 ID 。

如果直接把第一个参数 textureId 返回,则渲染的画面就是原始的视频画面。

  • 自定义灰色滤镜

根据上面的接口,既然已经有了原视频画面的纹理,那么对这个纹理进行处理就是很简单的事了。但仅仅处理是不够,还需要返回一个新的纹理,要怎么才能得到一个新的纹理呢?

如果你学过 OpenGL ,以及 OpenGL FBO(帧缓存对象),那就很容易实现了。

OpenGL FBO 提供了缓冲技术,不需要将画面显示出来,可以将画面绘制到一个新的纹理上。详细介绍可以看【】

限于文章篇幅,以及 OpenGL 相关知识的了解程度,这里只简单将接口实现贴出来,要了解详细的代码,可以参考本文的【Demo源码:GreyFilter】

class VideoPushActivity : AppCompatActivity(), TXLivePusher.VideoCustomProcessListener { // 省略无关代码 // ......
private fun initPusher() { val mLivePushConfig = TXLivePushConfig() mLivePusher = TXLivePusher(this)
// 一般情况下不需要修改 config 的默认配置 mLivePusher.config = mLivePushConfig
mLivePusher.startCameraPreview(tx_cloud_video_view)
// 开启自定义渲染 mLivePusher.setVideoProcessListener(this) } private var greyFilter: GreyFilter? = null override fun onTextureCustomProcess(textureId: Int, width: Int, height: Int): Int { if (greyFilter == null) { greyFilter = GreyFilter() greyFilter?.setTextureID(textureId) greyFilter?.setVideoSize(width, height) } greyFilter?.draw() return if(greyFilter?.getFboTextureID() == -1) textureId else greyFilter?.getFboTextureID()!! } // ......}

原理很简单:利用 OpenGL FBO 技术,创建一个新的纹理单元 B ,接着将 SDK 传递给我们的纹理单元 A 中的画面处理成灰色,并绘制到 FBO 上,新的纹理单元 B 就有了灰色滤镜处理过的画面,然后将 B 返回给 SDK 内部进行渲染绘制。

  • 添加水印

添加水印也很简单,水印其实就是在原视频的基础上,绘制多一个 Logo 图片叠加在上面。

那么只需要在 FBO 上面,先绘制原视频数据,再绘制水印即可,唯一要注意的是,需要做好水印的位置和大小的适配。

具体实现参考【Demo源码:WaterMarkDrawer】

五、总结

腾讯云直播 SDK 提供了比较全面的功能,基本上涵盖了直播系统中该有的功能点,整一套使用下来,也比较顺畅易用(仅仅体验使用,深入使用可能会遇到其他的一些问题),主要有以下特点:

  • 系统搭建非常简单,SDK 提供的接口很简洁友好,基本上是傻瓜式接入;

  • 提供的功能点齐全,从采集-本地处理-推流,到云端转码、录制、鉴黄等,再到拉流,还有直播连麦等高级功能,提供了一体式解决方案;

  • 支持推拉流地址自定义,拓展方便;

  • 提供自定义渲染接口,对于有自定义能力的小伙伴来说非常实用。

当然也有美中不足的地方:

  • 拉流自定义渲染接口只提供了原始数据,没有提供 OpenGL 纹理渲染,处理起来比较麻烦;

  • 推流自定义渲染接口必须要返回一个新的纹理,不能直接通过 OpenGL 渲染,需要借助 FBO ,加大了开销;

  • 推拉流都可以设置 SurfaceView 作为渲染窗口,但是被绑定到 SDK 的 OpenGL 线程中,没有暴露渲染上下文,无法定义自己的 OpenGL 渲染环境。文档中也没有深入的说明,目前不知其用途。

综上,直播涉及到的知识确实非常多,投入足够多的精力也并非不可实现,但对于小公司或者没有足够研发投入的公司来说,使用第三方的 SDK 或许是更好的选择,毕竟他们都是顶住了千万级流量的,专业性,稳定性和可靠性都比较好。


技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。

推荐阅读:

本文分享自微信公众号 - 音视频开发进阶(glumes_blog)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“”,欢迎正在阅读的你也加入,一起分享。

【关于云返利网】

云返利网是阿里云、腾讯云、华为云产品推广返利平台,在各个品牌云产品官网优惠活动之外,云返利网还提供返利。您可以无门槛获得阿里云、华为云、腾讯云所有产品返利,在官网下单后就可以领取,无论是自己用、公司用还是帮客户采购,您个人都可以获得返利。云返利网的目标是让返利更多、更快、更简单!详情咨询13121395187(微信同号)