15 flvjs 播放 ws 服务代理的不存在的 rtsp 连接, Cannot read properties of null (reading ‘flushStashedSamples‘)

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15 flvjs 播放 ws 服务代理的不存在的 rtsp 连接, Cannot read properties of null (reading ‘flushStashedSamples‘)相关的知识,希望对你有一定的参考价值。

前言

这是基于 flvjs 播放 rtsp视频服务 基于node+ffmpeg 转换为 flv 视频服务 的时候, 衍生出来的一个问题 

在生产环境上面, 很大一部分 rtsp 服务是正常的可以播放的, 但是 还存在一部分 rtsp 服务是播放不出来的, 我们需要再 产生异常的时候做一些 回调处理 

但是 这时候就会抛出异常如下 

Uncaught TypeError: Cannot read properties of null (reading 'flushStashedSamples')
    at __webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onIOComplete (flv.js?20b0:3357:1)
    at __webpack_modules__../src/io/io-controller.js.IOController._onLoaderComplete (flv.js?20b0:6328:1)
    at __webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketClose (flv.js?20b0:6902:1)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onIOComplete @ flv.js?20b0:3357
__webpack_modules__../src/io/io-controller.js.IOController._onLoaderComplete @ flv.js?20b0:6328
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketClose @ flv.js?20b0:6902
10HelloWorld.vue?18db:55 

我们这里 参考的代码来自于 GitHub - LorinHan/flvjs_test: 采用flvjs实现摄像头直播

问题复现

1. 启动 node 代理服务 "node index.js" 

2. 在 flvjs_test 项目下的 front 项目, 调整 HelloWorld.vue, 调整 ws 的链接, 更新 rtsp 的链接为一个不存在的链接即可 

问题的原因

## 如果待加载的 rtsp 连接不正确, _remuxer 的 NPE 的问题
// 需要有一个正常的 websocket 响应, 才会初始化 _remuxer
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketMessage (flv.js?20b0:6908)
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._dispatchArrayBuffer (flv.js?20b0:6933)
__webpack_modules__../src/io/io-controller.js.IOController._onLoaderChunkArrival (flv.js?20b0:6261)
__webpack_modules__../src/io/io-controller.js.IOController._dispatchChunks (flv.js?20b0:6173)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onInitChunkArrival (flv.js?20b0:3282)
    里面初始化 _remuxer

# 我们这里异常情况下是是直接走的 ws.close, 而此时 _remuxer 尚未初始化
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketClose (flv.js?20b0:6902)
__webpack_modules__../src/io/io-controller.js.IOController._onLoaderComplete (flv.js?20b0:6328)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onIOComplete (flv.js?20b0:3351)

基于调整 flvjs 代码处理问题

_remuxer 增加 null check, 然后 重新打包 发布依赖 

这个处理 相对比较简单, 一了百了, 本身按道理来说 这个应该也算是 flvjs 的 bug 

花式操作初始化 _remuxer 处理问题 

好处是 不用修改 flvjs 的代码, 以免造成一些 意料之外的问题  

// createPlayer 的时候增加 deferLoadAfterSourceOpen 的配置 
this.player = flvjs.createPlayer(
    type: "flv",
    isLive: true,
    url: `ws://localhost:9999/rtsp/$this.id/?url=$this.rtsp`
, 
    deferLoadAfterSourceOpen: false
);


// 在 this.player.load() 之后增加如下代码, 初始化 _remuxer 
let controller = this.player._transmuxer._controller
controller._remuxer = 
  flushStashedSamples: function () 
    console.log("flushStashedSamples")
  

刷新一下页面, 发现 那个错误已经被我们绕过了 

但是直接这样的话, 我们兼容不了 rtsp 服务正常的情况, 正常的视频 会包 bindDataSource 的 "is not a function"

花式操作初始化 _remuxer 处理问题, 兼容正常/异常情况

调整上面的代码, 我们将 _remuxer 的初始化调整为 在需要的时候 才自己手动模拟一个 _remuxer 

这时候 就兼容了 正常情况 和 异常情况了 

// createPlayer 的时候增加 deferLoadAfterSourceOpen 的配置 
this.player = flvjs.createPlayer(
    type: "flv",
    isLive: true,
    url: `ws://localhost:9999/rtsp/$this.id/?url=$this.rtsp`
, 
    deferLoadAfterSourceOpen: false
);


// 在 this.player.load() 之后增加如下代码, 需要的时候, 初始化 _remuxer 
let controller = this.player._transmuxer._controller
let wsLoader = controller._ioctl._loader
var oldWsOnCompleteFunc = wsLoader._onComplete
wsLoader._onComplete = function() 
  if(!controller._remuxer) 
    controller._remuxer = 
      flushStashedSamples: function () 
        _this.loadingVisiable = false
        console.log("flushStashedSamples")
      
    
  
  oldWsOnCompleteFunc()

异常情况如下 

正常情况如下  

为什么能这样?, 那就需要你去稍微 捋一下 flv.js 的代码了 

以及对 javascript 稍微有所了解

正常状态的监听 和 异常状态的监听

正常状态的监听可以使用 : flvjs 的 MEDIA_INFO, METADATA_ARRIVED, SCRIPTDATA_ARRIVED, 或者 video 的 canpaly 事件 

异常状态可以使用 : video 的 error 事件

异常状态为什么不能使用 flvjs 的 ERROR 事件?

因为 flvjs 的 ERROR 是在播放的过程中产生的异常, 才会提交 ERROR 事件 

flvjs 的 ERROR 会在 appendInitSegment/_doAppendSegments 中可能提交 

但是这两个的处理都是在 正常的拿到了 flv 的数据之后, 才会执行 

因此 请注意 flvjs 的 ERROR 事件的细节 

# 处理 第一个 AVCVideoPacket 为 AVCSequence Header 的调用栈
__webpack_modules__../src/core/mse-controller.js.MSEController.appendInitSegment (flv.js?20b0:2409)
(anonymous) (flv.js?20b0:7735)
emit (flv.js?20b0:1248)
(anonymous) (flv.js?20b0:2932)
Promise.then (async)
__webpack_modules__../src/core/transmuxer.js.Transmuxer._onInitSegment (flv.js?20b0:2931)
emit (flv.js?20b0:1248)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onRemuxerInitSegmentArrival (flv.js?20b0:3379)
__webpack_modules__../src/remux/mp4-remuxer.js.MP4Remuxer._onTrackMetadataReceived (flv.js?20b0:9255)
__webpack_modules__../src/demux/flv-demuxer.js.FLVDemuxer._parseAVCDecoderConfigurationRecord (flv.js?20b0:5023)
__webpack_modules__../src/demux/flv-demuxer.js.FLVDemuxer._parseAVCVideoPacket (flv.js?20b0:4866)
__webpack_modules__../src/demux/flv-demuxer.js.FLVDemuxer._parseVideoData (flv.js?20b0:4853)
__webpack_modules__../src/demux/flv-demuxer.js.FLVDemuxer.parseChunks (flv.js?20b0:4400)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onInitChunkArrival (flv.js?20b0:3303)
__webpack_modules__../src/io/io-controller.js.IOController._dispatchChunks (flv.js?20b0:6173)
__webpack_modules__../src/io/io-controller.js.IOController._onLoaderChunkArrival (flv.js?20b0:6261)
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._dispatchArrayBuffer (flv.js?20b0:6933)
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketMessage (flv.js?20b0:6908)


# 处理 渲染当前 pakcet 的 flv 的视频数据 的调用栈
__webpack_modules__../src/core/mse-controller.js.MSEController._doAppendSegments (flv.js?20b0:2627)
__webpack_modules__../src/core/mse-controller.js.MSEController.appendMediaSegment (flv.js?20b0:2469)
(anonymous) (flv.js?20b0:7738)
emit (flv.js?20b0:1248)
(anonymous) (flv.js?20b0:2938)
Promise.then (async)
__webpack_modules__../src/core/transmuxer.js.Transmuxer._onMediaSegment (flv.js?20b0:2937)
emit (flv.js?20b0:1248)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onRemuxerMediaSegmentArrival (flv.js?20b0:3386)
__webpack_modules__../src/remux/mp4-remuxer.js.MP4Remuxer._remuxVideo (flv.js?20b0:9754)
__webpack_modules__../src/remux/mp4-remuxer.js.MP4Remuxer.remux (flv.js?20b0:9224)
__webpack_modules__../src/demux/flv-demuxer.js.FLVDemuxer.parseChunks (flv.js?20b0:4415)
__webpack_modules__../src/core/transmuxing-controller.js.TransmuxingController._onInitChunkArrival (flv.js?20b0:3303)
__webpack_modules__../src/io/io-controller.js.IOController._dispatchChunks (flv.js?20b0:6173)
__webpack_modules__../src/io/io-controller.js.IOController._onLoaderChunkArrival (flv.js?20b0:6261)
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._dispatchArrayBuffer (flv.js?20b0:6933)
__webpack_modules__../src/io/websocket-loader.js.WebSocketLoader._onWebSocketMessage (flv.js?20b0:6908)

以上是关于15 flvjs 播放 ws 服务代理的不存在的 rtsp 连接, Cannot read properties of null (reading ‘flushStashedSamples‘)的主要内容,如果未能解决你的问题,请参考以下文章

01 flv 的 binary 解析

01 flv 的 binary 解析

01 flv 的 binary 解析

通过Vue+flvjs在HTML5中播放flv格式视频文件—demo及api

通过Vue+flvjs在HTML5中播放flv格式视频文件—demo及api

播放框架 - 使用 WS API