本文面向 Flutter 开发者,讲解如何基于 ZEGO 实时音视频 SDK( ZEGO Express SDK)快速实现可上线的直播功能。一套 Flutter 代码即可实现"主播推流、观众拉流、多人连麦、CDN 分发"的完整直播链路,核心推拉流代码不到 20 行。
一、直播开发,难在哪里?
很多团队对"做直播"的第一反应是:不就是推个流、拉个流吗?真正动手才发现,一条看似简单的直播链路背后是成串的硬骨头:
- 采集与渲染:摄像头、麦克风采集,画面预览、镜像、旋转、前后摄切换;
- 编码与推流:H.264/H.265 编码、码率/帧率/分辨率控制、推流鉴权;
- 分发与拉流:低延迟实时分发、CDN 转推、海量观众并发;
- 弱网对抗:丢包重传(ARQ)、前向纠错(FEC)、抖动缓冲、码率自适应;
- 互动体验:多人连麦、混流、回声消除(AEC)、降噪(ANS)、自动增益(AGC);
- 业务配套:弹幕、点赞、礼物、上麦管理、录制、水印……
每一环自研,都需要音视频算法团队长期投入,且很难做到大厂水准。所以业界主流做法是:底层音视频能力交给专业 RTC/直播厂商,业务团队专注 UI 与玩法。即构(ZEGO)是直播行业的老牌底层供应商,为映客、花椒等头部直播平台提供直播连麦能力,其 Express SDK 在 Flutter 平台有完整的官方支持,是快速实现 Flutter 直播的成熟选择。
二、为什么选择 ZEGO SDK?
| 维度 | ZEGO Express SDK(Flutter) |
|---|---|
| 延迟 | 端到端平均时延低至 200ms;超低延迟直播拉流延迟可控制在 1s 以内 |
| 平台 | Flutter 1.12+,覆盖 iOS、Android、Web、Windows、macOS,多端互通 |
| 直播能力 | 单主播直播、多人连麦(连麦互动主播 32 名以上)、PK、跨房互动、混流、CDN 转推 |
| 弱网能力 | FEC + ARQ 动态平衡、弱网自适应推拉流、智能调节码率帧率、视频抗 70% 丢包 |
| 音频体验 | AEC / AGC / ANS 三大 3A 处理,回声消除支持 10 路同时讲话 |
| 接入成本 | 4 行代码完成 SDK 初始化;场景化 UIKits 不到 10 行代码可出 MVP |
| 基础设施 | 全球 500+ BGP 节点,海量并发下保持稳定分发 |
| 鉴权 | 支持 AppSign 与 Token 两种鉴权方式,可平滑升级 |
三、理解三个核心概念和直播链路
在写代码之前,先建立三个概念,后面所有 API 都围绕它们展开:
- 房间(room):ZEGO 提供的音视频空间服务,用于组织用户。必须先登录房间,才能推流、拉流;同一房间内的用户才能互相收到对方进房、退房、流增删的通知。房间由
roomID标识,同一 AppID 内全局唯一。 - 流(stream):按指定编码格式封装、持续发送中的音视频数据。每条流由
streamID标识,同一 AppID 内全局唯一。一个用户可以推多条流(例如摄像头 + 屏幕共享),也可以同时拉多条流。 - 推流与拉流:推流是把采集编码后的音视频数据推送到 ZEGO 音视频云;拉流是从 ZEGO 网络拉取播放。主播端负责推流,观众端负责拉流。
一次最简单的直播,整体链路如下:
flowchart LR
subgraph Host["主播端 Flutter App"]
A1[创建引擎 createEngineWithProfile] --> A2[登录房间 loginRoom]
A2 --> A3[本地预览 startPreview]
A3 --> A4[推流 startPublishingStream]
end
subgraph Cloud["ZEGO 音视频云 MSDN"]
C1[流接入与分发] --> C2[超低延迟分发 / 转推 CDN / 混流]
end
subgraph Audience["观众端 Flutter App"]
B1[登录房间 loginRoom] --> B2[收到 onRoomStreamUpdate 流新增通知]
B2 --> B3[拉流 startPlayingStream]
B3 --> B4[渲染播放]
end
A4 --> C1
C2 --> B2
四、快速实现:30 分钟跑通"主播推流 + 观众拉流"
4.1 准备:AppID 与 AppSign
在ZEGO 控制台注册账号、创建项目,获取:
- AppID:数字,形如
1234567890; - AppSign:64 位十六进制字符串,形如
0123456789...(共 64 个字符)。
注意:临时 AppSign/Token 仅供调试;正式上线建议从业务服务器签发 Token 鉴权。
4.2 集成 SDK
在项目根目录执行:
flutter pub add zego_express_engine
在 Dart 代码中引入:
import 'package:zego_express_engine/zego_express_engine.dart';
4.3 初始化引擎
创建 ZegoEngineProfile,调用 createEngineWithProfile 创建引擎实例:
ZegoEngineProfile profile = ZegoEngineProfile(
1234567890, // 替换为你的 AppID
ZegoScenario.General, // 通用场景
appSign: '0123456789...', // 替换为 64 位 AppSign;Web 平台勿传
enablePlatformView: true, // Web 平台必须为 true
);
ZegoExpressEngine.createEngineWithProfile(profile);
要点:
- 创建引擎后立即注册回调,避免错过房间、流等事件通知;
- Web 平台仅支持 PlatformView 渲染方式,且仅支持 Token 鉴权,不要传 appSign;
- Windows / macOS 目前支持 TextureRenderer;Android / iOS 可通过
enablePlatformView二选一。
4.4 登录房间
创建用户对象,调用 loginRoom 登录房间(房间不存在会自动创建):
ZegoUser user = ZegoUser.id('user1'); // userID 在同一 AppID 内全局唯一
ZegoRoomConfig config = ZegoRoomConfig.defaultConfig();
config.isUserStatusNotify = true; // 置 true 才能收到用户进出回调
// 若使用 Token 鉴权:config.token = 'xxxx';
ZegoExpressEngine.instance.loginRoom('room1', user, config: config);
建议监听房间连接状态,在回调中处理登录中/成功/失败/断线重连/被踢等分支:
ZegoExpressEngine.onRoomStateChanged = (String roomID,
ZegoRoomStateChangedReason reason, int errorCode,
Map extendedData) {
if (reason == ZegoRoomStateChangedReason.Logined) {
// 登录成功,可拉取直播间基础信息
} else if (reason == ZegoRoomStateChangedReason.LoginFailed) {
// 登录失败,检查 AppID / AppSign / Token
} else if (reason == ZegoRoomStateChangedReason.KickOut) {
// 被踢出房间(同 userID 在他处登录等)
}
};
4.5 主播端:预览 + 推流
第一步,本地预览(可选但推荐)。 用 createCanvasView 创建渲染 Widget,拿到 viewID 后调用 startPreview:
_previewViewWidget = await ZegoExpressEngine.instance.createCanvasView((viewID) {
_previewViewID = viewID;
ZegoCanvas previewCanvas = ZegoCanvas.view(viewID);
ZegoExpressEngine.instance.startPreview(canvas: previewCanvas);
});
第二步,推流。 调用 startPublishingStream,传入全局唯一的 streamID:
ZegoExpressEngine.instance.startPublishingStream('stream_abc');
推流状态可监听
onPublisherStateUpdate回调;网络异常时 SDK 会自动重试。
4.6 观众端:发现流 + 拉流
观众登录同一房间后,当主播推流,观众会在 onRoomStreamUpdate 中收到流"新增"通知,从中拿到 streamID:
ZegoExpressEngine.onRoomStreamUpdate = (String roomID,
ZegoUpdateType updateType, List streamList) {
if (updateType == ZegoUpdateType.Add) {
for (ZegoStream stream in streamList) {
// 对新增的每条流调用 startPlayingStream 拉流
_playStream(stream.streamID);
}
} else if (updateType == ZegoUpdateType.Delete) {
for (ZegoStream stream in streamList) {
// 流减少时及时停止拉流,避免拉到空流产生额外成本
ZegoExpressEngine.instance.stopPlayingStream(stream.streamID);
}
}
};
拉流并渲染到画面:
_playViewWidget = await ZegoExpressEngine.instance.createCanvasView((viewID) {
_playViewID = viewID;
ZegoCanvas canvas = ZegoCanvas.view(viewID);
ZegoExpressEngine.instance.startPlayingStream(
streamID,
canvas: canvas,
config: ZegoPlayerConfig(
ZegoStreamResourceMode.ONLY_L3, // 超低延迟直播拉流
videoCodecID: ZegoVideoCodecID.Default,
roomID: roomID,
),
);
});
拉流状态可监听
onPlayerStateUpdate回调,确认是否拉流成功。
4.7 生命周期:停止、退出、销毁
// 停止推流与预览
ZegoExpressEngine.instance.stopPublishingStream();
ZegoExpressEngine.instance.stopPreview();
ZegoExpressEngine.instance.destroyCanvasView(_previewViewID);
// 停止拉流
ZegoExpressEngine.instance.stopPlayingStream(streamID);
ZegoExpressEngine.instance.destroyCanvasView(_playViewID);
// 退出房间
ZegoExpressEngine.instance.logoutRoom('room1');
// 彻底释放引擎
ZegoExpressEngine.destroyEngine();
至此,一个"主播开播、观众观看"的最小直播闭环已经跑通,核心代码不超过 20 行。
五、进阶:从"能播"到"专业直播"
基础推拉流只是起点。一个可上线的直播产品,通常还需要以下能力,ZEGO 均提供了对应 API。
5.1 连麦互动:观众上麦
直播的核心玩法之一是连麦。观众申请上麦 → 主播同意 → 观众端调用 startPublishingStream 推自己的流 → 主播拉取该观众的流同屏显示,即完成连麦。ZEGO 支持:
- 多人连麦:连麦互动主播数可达 32 名以上,覆盖连麦 PK 等玩法,端到端时延低至 200ms 级;
- 万人直播连麦:面向大型互动直播场景;
- 拉流资源分级:支持分别设置观众"上麦前"与"下麦后"的拉流资源类型(RTC 拉流 / 超低延迟直播 L3 / CDN 拉流)——观众平时用 L3 或 CDN 省成本,上麦互动时自动切换为 RTC 保证低延迟。
上麦的"申请/同意"等信令逻辑,可通过 ZIM(即时消息 SDK)或业务服务器自行实现。
5.2 超低延迟直播(L3)
常规 CDN 直播延迟在数秒级,而互动直播要求秒级以内。ZEGO 超低延迟直播(L3):
- 拉流延迟控制在 1s 以内,端到端平均时延 200ms 级别;
- 具备超强同步、抗极端弱网、超清画质、首帧秒开能力;
- 注意:L3 不是默认开启,需在 ZEGO 控制台自助开通,或联系技术支持开通;拉流时将
ZegoStreamResourceMode设为ONLY_L3(见 4.6 节代码)。
5.3 CDN 分发与混流
当观众规模扩大、需要网页端/第三方播放器观看时,需要 CDN 能力:
- 旁路转推 CDN:把 ZEGO 云上的流转推至 CDN(支持 ZEGO 自有 CDN 与第三方 CDN);
- 直推 CDN:调用
enablePublishDirectToCDN,从客户端直接将流推往 CDN,不经过 RTC 服务器; - 动态转推:
addPublishCdnUrl/removePublishCdnUrl动态增减 CDN 转推地址; - 混流:把多路音视频流混合成单流(支持推流端、云端、拉流端混流),观众只需拉一条流就能看到全部主播画面、听到全部声音,同时混流输出流也可转推 CDN。
5.4 实时消息:弹幕、点赞、礼物
直播互动不止于音视频。ZEGO 提供房间内实时消息能力:广播消息、弹幕消息、点对点自定义消息,可基于此实现点赞、送礼物、答题等玩法;也可搭配 ZIM SDK 实现更复杂的 IM 场景。
5.5 体验增强:美颜、3A、流量控制、H.265
- 音质:AEC(回声消除)、AGC(自动增益)、ANS(降噪)业内领先,回声消除支持 10 路同时讲话;
- 画面:支持美颜(可结合 AI 视觉)、美声/变声、耳返、水印、摄像头变焦;
- 弱网:流量控制自动调节码率/帧率/分辨率,保证流畅;
- 成本与清晰度:支持 H.265 编码,相同码率下清晰度更高;SDK 采集支持最高 1080p、1–30fps;
- 其他:本地录制、媒体播放器(可把背景音乐推流出去)、音视频流加密、通过 URL 拉流(对接 OBS 等第三方推流)。
六、避坑清单
- streamID 全局唯一:同一 AppID 内不同用户推相同 streamID,后推者会推流失败;
- userID 全局唯一:建议与业务账号系统关联;相同 userID 在别处登录会导致本端被踢;
- 登录后才能推拉流:所有推流、拉流操作必须在
loginRoom之后; - 回调要早注册:建议创建引擎后立即注册
onRoomStateChanged、onRoomStreamUpdate等回调; - 流减少要及时停拉:收到
onRoomStreamUpdate的 Delete 通知后,及时stopPlayingStream,避免拉空流产生额外成本; - L3 需开通:超低延迟直播不是默认功能,记得在控制台开通,否则拉流会失败;
- Web 平台差异:仅支持 PlatformView 渲染、仅支持 Token 鉴权,不要传 appSign;
- 临时 Token 仅调试:正式上线请从业务服务器生成 Token;
- 渲染方式选择:Android/iOS 按需选择 PlatformView 或 TextureRenderer,前者资源占用略高;Web 强制 PlatformView。
七、结语
用 Flutter + ZEGO SDK 实现直播,本质上是把"采集、编码、推流、分发、拉流、播放、弱网对抗、连麦互动"这一整条高门槛链路交给成熟的音视频基础设施,业务层只需关心 UI 与玩法。
回顾整篇文章,一条可上线的直播链路只需四步:
- 集成:
flutter pub add zego_express_engine,创建引擎、登录房间; - 主播:
startPreview+startPublishingStream推流; - 观众:在
onRoomStreamUpdate中startPlayingStream拉流; - 进阶:按需叠加连麦、L3、CDN、混流、实时消息等。
从今天起,你可以用一套 Flutter 代码,同时覆盖 iOS、Android、Web 与桌面端,快速构建属于自己的互动直播产品。
参考资料




