完全指南)
写给刚接触 RTMP/Flash 音视频协议的同学用大白话讲清楚这些神秘代码到底是什么意思。一、先讲个故事什么是 NetStatusEvent想象你在使用一个视频直播 App你点击开始观看 → 服务器说好开始播放了网络卡了 → 服务器说缓冲区空了等一下主播关播了 → 服务器说播放已结束输错了房间号 → 服务器说找不到这个流这些服务器给你的通知消息在 RTMP 协议里就叫做NetStatusEvent网络状态事件。你的代码里定义的NetStatusEvent结构体就是用来描述这些通知的type NetStatusEvent struct { Code string // 具体发生了什么事比如播放开始、连接失败 Level string // 严重程度status正常信息 / error错误 / warning警告 }就这么简单一个事件 一件事 它的严重程度。二、Level严重程度-- 三种语气Level含义打个比方status正常状态信息快递员打电话说你的包裹已送达error出错了快递员说地址不存在送不了warning警告可能有问题快递员说天气不好可能会晚到三、Code事件代码详解 — 按场景分类场景一NetStream.Play.* — 我在看直播这是观众端最常遇到的一组事件代码Level大白话解释Play.Startstatus播放正式开始画面出来了Play.Stopstatus播放结束主播关了或者你主动停了Play.Resetstatus播放列表重置了比如切换清晰度Play.StreamNotFounderror找不到这个流房间号可能错了Play.Failederror播放失败原因不明可能是没权限Play.PublishNotifystatus有人开始推流了你正在看这个流Play.UnpublishNotifystatus推流的人停了Play.Switchstatus切换了流比如自适应码率切换Play.Completestatus播放完成点播文件播完了实际开发中的典型处理func handlePlayEvent(e *NetStatusEvent) { switch e.Code { case NetStream_Play_Start: log.Println(开始播放渲染画面吧) startRendering() case NetStream_Play_StreamNotFound: log.Println(房间不存在提示用户) showError(该直播间不存在) case NetStream_Play_Stop: log.Println(播放结束) cleanupPlayer() } }场景二NetStream.Buffer.* — 数据缓冲区直播就像用水管接水缓冲区就是水桶代码Level大白话解释Buffer.Emptystatus水桶见底了数据来得不够快画面会卡Buffer.Fullstatus水桶满了可以继续流畅播放了Buffer.Flushstatus剩余的水都倒出来了流式处理结束实际用途 用Buffer.Empty和Buffer.Full来显示/隐藏加载中动画。case NetStream_Buffer_Empty: showLoadingSpinner() // 显示转圈圈 case NetStream_Buffer_Full: hideLoadingSpinner() // 隐藏转圈圈流畅播放场景三NetStream.Publish.* — 我在推流这是主播端的事件代码Level大白话解释Publish.Startstatus推流成功观众能看到你了Publish.BadNameerror这个流名已经被别人用了Publish.Idlestatus你连上了但没在推数据空闲Unpublish.Successstatus成功停止推流推流失败最常见的原因 流名冲突两个人同时推同一个房间。场景四NetStream.Record.* --我在录制代码Level大白话解释Record.Startstatus录制开始Record.Stopstatus录制结束Record.Failederror录制失败Record.NoAccesserror没有录制权限场景五NetStream.Seek.* -- 我要快进/拖动代码Level大白话解释Seek.Notifystatus跳转成功从第 5 分钟开始播了Seek.Failederror跳转失败流不支持快进Seek.InvalidTimeerror跳到了不存在的时间比如视频只有 10 分钟你跳到了第 20 分钟场景六NetStream.Pause/Unpause — 暂停/恢复代码Level大白话解释Pause.Notifystatus已暂停Unpause.Notifystatus已恢复播放场景七NetConnection.* — 连接服务器这是最基础的一组事件连接阶段就会触发代码Level大白话解释Connect.Successstatus连接成功可以开始推/拉流了Connect.Closedstatus连接已关闭Connect.Failederror连接失败服务器挂了网络断了Connect.Rejectederror被拒绝没权限、Token 不对Connect.InvalidApperror应用名无效rtmp://server/appName 写错了Connect.AppShutdownerror服务器正在关闭这个应用连接阶段的典型流程func handleConnectionEvent(e *NetStatusEvent) { switch e.Code { case NetConnection_Connect_Success: log.Println(连上了可以开始 createStream()) createStream() case NetConnection_Connect_Failed: log.Println(连接失败3秒后重试...) retryAfter(3 * time.Second) case NetConnection_Connect_Rejected: log.Println(被拒绝检查鉴权信息) showAuthError() } }场景八NetConnection.Call.* — 调用远程方法代码Level大白话解释Call.Failederror调用服务器方法失败Call.BadVersionerror数据包格式不对Call.Prohibitederror跨域被阻止安全策略场景九SharedObject.* — 共享对象SharedObject 是 RTMP 里的共享数据机制类似聊天室的弹幕同步代码Level大白话解释Flush.Successstatus数据保存成功Flush.Failederror数据保存失败BadPersistenceerror持久化标记冲突UriMismatcherrorURI 不匹配四、实际开发中的最佳实践统一事件分发器func DispatchNetStatusEvent(e *NetStatusEvent) { // 先按严重程度分类处理 switch e.Level { case Level_Error: log.Printf(错误: %s, e.Code) handleError(e) case Level_Warning: log.Printf(警告: %s, e.Code) handleWarning(e) case Level_Status: log.Printf(状态: %s, e.Code) handleStatus(e) } }常见业务场景的状态映射业务场景关注的关键事件处理方式观众进入直播间Connect.Success→Play.Start显示播放器观众遇到卡顿Buffer.Empty/Buffer.Full显示/隐藏 loading主播开始推流Publish.Start确认推流成功主播被踢Connect.Rejected提示重新登录房间不存在Play.StreamNotFound跳转错误页网络断开Connect.Failed/Connect.Closed自动重连func newNetStatusEvent(code, level string) (e *NetStatusEvent) { e.Code code e.Level level return e }使用时event : newNetStatusEvent(NetStream_Play_Start, Level_Status) DispatchNetStatusEvent(event)五、总结记住三句话就够了Connect系列 → 管连不连得上Play/Publish系列 → 管能不能看/能不能推Buffer系列 → 管卡不卡