【问题标题】:TypeError: Failed to execute 'appendBuffer' on 'SourceBuffer': No function was found that matched the signature providedTypeError:无法在“SourceBuffer”上执行“appendBuffer”:未找到与提供的签名匹配的函数
【发布时间】:2020-09-15 19:58:47
【问题描述】:

编辑:为了帮助说明我不断遇到的错误,我创建了我所看到的问题的 CodePen。打开控制台,您将看到错误。 [https://codepen.io/FifthCloud/pen/eYpqJLN]

我想在家里使用 React/Node 设计自己的流媒体摄像头服务。到目前为止,我在客户端/服务器方法方面已经走了很长一段路。服务器是一个带有摄像头的树莓派。使用 FFMpeg 我可以看到其中的所有视频,并且使用 websockets 我可以成功发送数据(我的意思是我看到发送到客户端的数据会解释为什么它不会渲染)。

我遇到的问题是为什么我不能将数据附加到缓冲区。对于初学者,我使用这个关于媒体源的演示作为我应该做什么的指南和示例。 http://nickdesaulniers.github.io/netfix/demo/bufferAll.html我从我对媒体源的研究中得到了这个链接:https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/readyState 还要提一下,我从这篇文章中获得了很多灵感,并且因为这个答案而走得很远HTML5 Video: Streaming Video with Blob URLs

考虑到这一点,我可以成功创建MediaSource 并打开缓冲区,但我不明白为什么我无法追加到缓冲区?我收到的错误是这样的:

TypeError:无法在“SourceBuffer”上执行“appendBuffer”:未找到与提供的签名匹配的函数。

客户端代码如下

class ProductDetail extends React.Component {
  constructor(props) {
    super(props);
    this.handleData = this.handleData.bind(this);
    this.handleOpen = this.handleOpen.bind(this);
    this.appendToSourceBuffer = this.appendToSourceBuffer.bind(this);
    this.mediaStreaming = new MediaSource();
    this.blobArr = [];
    this.buffer = null;
    this.myRef = React.createRef();

    console.log("buffer initialized");
    console.log("ReadyState [Initialized]: " + this.mediaStreaming.readyState);
    this.state = {
      msg: "",
      stream: "",
      streaming: URL.createObjectURL(this.mediaStreaming),
    };
  }

  componentDidMount() {
    this.mediaStreaming.addEventListener("sourceopen", () => {
      console.log(
        "ReadyState [Source Open]: " + this.mediaStreaming.readyState
      );
      this.buffer = this.mediaStreaming.addSourceBuffer(
        'video/mp4;codecs="avc1.42E01E"'
      );
      this.buffer.addEventListener("updateend", () => {
        this.mediaStreaming.endOfStream();
        document.getElementById("streaming").play();
        console.log(
          "ReadyState [UpdateEnd]: " + this.mediaStreaming.readyState
        );
      });
    });
  }

  handleData(data) {
    const videoStream = JSON.parse(data);
    if (videoStream.msg === "videoStream") {
      this.blobArr.push(videoStream.chunk.data);
      if (
        this.mediaStreaming.readyState === "open" &&
        this.buffer &&
        this.buffer.updating === false &&
        this.blobArr.length > 0
      ) {
        console.log(
          "ReadyState [AppendBuffer]: " + this.mediaStreaming.readyState
        );
        this.buffer.appendBuffer(this.blobArr.shift()); // Error message shows at this line!
        document.getElementById("streaming").play();
        console.log("Buffer Updating", this.buffer.updating);
      }
    }
  }

  handleOpen() {
    console.log("Status: connected");
  }

  handleClose() {
    console.log("Status: disconnected");
  }

  render() {
    return (
      <div>
        <Websocket
          url="ws://192.168.1.20:5000"
          onMessage={this.handleData}
          onOpen={this.handleOpen}
          onClose={this.handleClose}
          reconnect={true}
          debug={true}
          ref={(Websocket) => {
            this.refWebSocket = Websocket;
          }}
          protocol="stream-protocol"
        />
        <video width="640" height="480" id="streaming" controls autoPlay>
          <source
            ref={this.myRef}
            src={this.state.streaming}
            type="video/mp4"
          />
          Your browser does not support the video tag.
        </video>
      </div>
    );
  }
}

当服务器发送下一个流字节数组数据时,错误来自我的 WebSocket 中的 handleData 事件。

正如我提到的示例和我发布的链接中的指南,我查看了他们的代码并逐步完成了它。根据他们的说法,附加缓冲区应该可以正常工作,但是即使在他们的代码中 appendbuffer() 也只列在 proto 部分,请参见此处:https://drive.google.com/open?id=1vOU4oM-XoKe71DofQuLU2THxMdgiown_,但代码并没有抱怨他们的 appendbuffer() .当我控制台记录我的缓冲区时,它看起来像他们的https://drive.google.com/open?id=1T4Ix-y124NgQJ9xu97xv4U2yFTn2k7vF。我错过了什么?

我觉得答案很明显,但它让我不知道我做错了什么。

【问题讨论】:

    标签: javascript media-source


    【解决方案1】:

    我自己也在构建一个类似的项目,使用了几个支持 RTSP 的高端 IP 摄像机,但今天遇到了同样的错误。首先,请记住,根据 Mozilla 开发者网络 (MDN) 文档(以下链接),此 API 是实验性的。

    话虽如此,我似乎找到了问题的根本原因,尽管我不是 JavaScript 专家。事实证明,您不能将 data.data 中的 handleData() 中的“Blob”对象直接传递给 appendBuffer() 方法。相反,您需要先将 Blob 转换为 appendBuffer() 方法支持的数据类型,然后再将其传入。

    1. 将您的事件处理程序转换为async 函数
    2. 使用Blob.arrayBuffer() 将数据块转换为JavaScript ArrayBuffer

    改变这个:

      handleData(data) {
        const videoStream = JSON.parse(data);
        if (videoStream.msg === "videoStream") {
          this.blobArr.push(videoStream.chunk.data);
          if (
            this.mediaStreaming.readyState === "open" &&
            this.buffer &&
            this.buffer.updating === false &&
            this.blobArr.length > 0
          ) {
            console.log(
              "ReadyState [AppendBuffer]: " + this.mediaStreaming.readyState
            );
            this.buffer.appendBuffer(this.blobArr.shift()); // Error message shows at this line!
            document.getElementById("streaming").play();
            console.log("Buffer Updating", this.buffer.updating);
          }
        }
      }
    

    进入这个:

      async handleData(event) {
        var buffer = await event.data.arrayBuffer(); // convert the message Blob into an ArrayBuffer
        appendBuffer(buffer);
        document.getElementById("streaming").play();
        console.log("Buffer Updating", this.buffer.updating);
      }
    

    问题是,一旦你这样做了,你就会开始得到一个新的错误,因为有太多的数据被传递到MediaSource 上的SourceBuffer 对象中。由于它跟不上输入流,您会看到类似于以下错误的内容:

    在“SourceBuffer”上执行“appendBuffer”失败:此 SourceBuffer 仍在处理“appendBuffer”或“删除”操作

    看起来我们需要“缓冲缓冲区”,这听起来很奇怪。

    我还没有解决这个新错误。如果您找到解决方案,我会很乐意提供帮助。

    相关阅读

    【讨论】:

    • 感谢您的帮助。至于你关于缓冲缓冲区的问题的答案。由于我所做的所有研究,我提前找到了这个帮助,我知道我必须达到你所说的那个点。 stackoverflow.com/a/50354182/13634541> 这个人想出了一个好主意,即一旦缓冲区达到一定数量,就删除缓冲区中的项目。没错,这都是实验性的,但请阅读:developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/buffered> 它使用 TimeRange 数据类型。用它来看看你是否会在缓冲区中达到高位。
    • 感谢其他问答的链接。看起来他只是将数据块缓冲到一个通用的 JavaScript 数组中,然后每秒最多将它们出列一次。我可能必须将 1000 毫秒间隔减少到更像 100 毫秒,以确保我有稳定的输入数据流,但理论上这可能有效。当我有更多时间时,我将不得不玩它。干杯
    • "未能在 'SourceBuffer' 上执行 'appendBuffer':此 SourceBuffer 仍在处理 'appendBuffer' 或 'remove' 操作" 我遇到了这个问题,并意识到我的 sourceopen 回调正在被调用多次...不知道为什么,但请看一下,看看它是否不会使您的错误消失。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    • 2017-12-06
    • 1970-01-01
    • 2019-01-25
    • 2015-05-26
    • 2022-12-27
    • 1970-01-01
    相关资源
    最近更新 更多