3、直播推流基础:RTMP协议简介、推流地址生成、摄像头与麦克风权限

好,咱们进入第三讲。这一章是实操前的最后一道理论关。

说白了,你要做直播带货,就得把手机摄像头拍到的画面、麦克风收进来的声音,实时地送到服务器上去。这个过程,就叫「推流」。而推流最常用的协议,就是 RTMP。

3.1 RTMP 协议简介

RTMP,全称 Real-Time Messaging Protocol,实时消息传输协议。是 Adobe 搞出来的东西,最初为了 Flash 播放器服务。现在 Flash 早没了,但 RTMP 在直播推流领域依然坚挺。

为什么?因为它延迟低,稳定。我做过对比测试,RTMP 的延迟通常能控制在 1-3 秒,对于带货场景来说完全够用。你想想看,主播说「三二一上链接」,观众看到也就慢个一两秒,不影响抢购。

RTMP 有几个核心特点:

  • 基于 TCP:可靠传输,不会丢包。但代价是如果网络差,它会拼命重传,导致卡顿。
  • 长连接:推流过程中,客户端和服务器一直保持连接,实时性高。
  • 分块传输:数据被切成小块(Chunk),每个块独立发送,方便服务器快速转发。

核心要点:RTMP 推流本质上就是客户端不断往服务器写数据,服务器不断读数据。写进去的是视频帧和音频帧,读出来的是直播流。

嗯,这里要注意一点。RTMP 默认使用端口 1935。如果你的服务器防火墙没开这个端口,推流肯定失败。我在项目里遇到过好几次,排查半天发现是安全组规则没配好。

3.2 推流地址生成

推流地址长什么样?我直接给你看个例子:

rtmp://push.live.example.com/live/stream_key_123456

这个地址分三部分:

  1. 协议头rtmp://,告诉客户端用 RTMP 协议。
  2. 推流域名或 IPpush.live.example.com,指向你的推流服务器。
  3. 应用名和流密钥/live/stream_key_123456,其中 live 是应用名,stream_key_123456 是流密钥。

流密钥是干嘛的?说白了就是身份凭证。服务器通过它来区分不同的直播间。你想想看,如果所有人都用同一个密钥推流,那画面不就乱套了?

生成推流地址时,我建议遵循以下规则:

  • 流密钥要足够复杂,防止被恶意盗推。我一般用 UUID 或 MD5 哈希。
  • 推流域名和播放域名最好分开。推流用 push,播放用 play,方便做权限控制。
  • 如果使用腾讯云、阿里云等云服务商,它们会提供标准的推流地址生成工具。

个人经验:我曾经在生成推流地址时,直接把用户 ID 当成了流密钥。结果有人写了个脚本,遍历用户 ID 疯狂推流,导致服务器负载飙升。后来我改用「用户ID + 时间戳 + 随机数」做 MD5,才彻底解决这个问题。

3.3 摄像头与麦克风权限

推流之前,你得先拿到摄像头和麦克风的权限。在小程序里,这事没那么简单。

小程序获取权限的流程是这样的:

  1. 用户进入直播间,点击「开始直播」。
  2. 小程序弹出权限请求框,询问是否允许使用摄像头和麦克风。
  3. 用户点击「允许」,小程序拿到权限。
  4. 如果用户点击「拒绝」,那就没法推流了。

代码层面,我们使用 wx.authorize 来申请权限:

// 申请摄像头权限
wx.authorize({
    scope: 'scope.camera',
    success() {
        console.log('摄像头权限已获取');
        // 可以开始推流了
    },
    fail() {
        console.log('摄像头权限被拒绝');
        // 引导用户去设置中开启
    }
});

// 申请麦克风权限
wx.authorize({
    scope: 'scope.record',
    success() {
        console.log('麦克风权限已获取');
    },
    fail() {
        console.log('麦克风权限被拒绝');
    }
});

这里有个坑,我必须要说。如果用户第一次拒绝了权限,第二次再调用 wx.authorize 是不会弹出授权框的。你需要引导用户去小程序的设置页面手动开启。

避坑指南:我曾经做过一个直播项目,上线后发现 30% 的用户无法推流。排查后发现,这些用户都是在第一次使用时拒绝了权限。后来我在代码里加了判断,如果授权失败,就弹窗提示「请前往设置开启权限」,并提供一个跳转按钮。问题才解决。

跳转设置页的代码:

wx.openSetting({
    success(res) {
        // 用户从设置页返回后,检查权限
        if (res.authSetting['scope.camera'] && res.authSetting['scope.record']) {
            console.log('权限已开启,可以推流了');
        }
    }
});

另外,iOS 和 Android 在权限处理上有些差异。iOS 只要用户拒绝过一次,就不会再弹授权框。Android 则每次都会弹。嗯,这个细节你在测试时要注意。

3.4 小结

这一章我们讲了三个核心点:

  • RTMP 协议是什么,为什么用它。
  • 推流地址怎么生成,密钥怎么设计。
  • 摄像头和麦克风权限怎么获取,踩坑怎么处理。

下一章,我们就要真正动手写代码了。我会带你实现一个最简单的推流 Demo,把画面和声音送到服务器上。准备好了吗?