最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - TypeError: Failed to execute 'appendBuffer' on 'SourceBuffer': No function was foun

programmeradmin1浏览0评论

Edit: To help illustrate the error I keep getting I have created a CodePen of the issue I am seeing. Open up the console and you will see the error. []

I wanted to design my own streaming camera service in my home using React/Node. So far I have gone a long way with a Client/Server approach. The server is a raspberry pi with camera attached to it. Using FFMpeg I can see all the video from it and using websockets I can successfully send the data (I mean I see the data being sent to the client will get into why it will not render).

The issue I am running into is why cannot I append the data to the buffer. For starters, I am using this demo about Media Source as a guide and example on what I am supposed to be doing. .html I got this link from my research about Media Source's here: Also would like to mention that I have received a lot of inspiration from this post and got really far because of this answer HTML5 Video: Streaming Video with Blob URLs

With that in mind I can successfully create a MediaSource and open the buffer, but what I cannot understand is why am I unable to append to the buffer? The error I am recieving is this:

TypeError: Failed to execute 'appendBuffer' on 'SourceBuffer': No function was found that matched the signature provided.

The client side code is the following

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),
    };
  }

  ponentDidMount() {
    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>
    );
  }
}

The error es from the handleData event from my WebSocket when the server is sending the next streaming byte array data.

As I mentioned about the example and the guide from the link I have posted I looked at their code and stepped through it. According to them Append Buffer should work fine, however even in their code appendbuffer() is only listed in the proto section see here: and yet the code doesn't plain about their appendbuffer(). When I console log my buffer it looks like theirs . What am I missing?

I feel like the answer is very obvious but it is escaping me as to what I am doing wrong.

Edit: To help illustrate the error I keep getting I have created a CodePen of the issue I am seeing. Open up the console and you will see the error. [https://codepen.io/FifthCloud/pen/eYpqJLN]

I wanted to design my own streaming camera service in my home using React/Node. So far I have gone a long way with a Client/Server approach. The server is a raspberry pi with camera attached to it. Using FFMpeg I can see all the video from it and using websockets I can successfully send the data (I mean I see the data being sent to the client will get into why it will not render).

The issue I am running into is why cannot I append the data to the buffer. For starters, I am using this demo about Media Source as a guide and example on what I am supposed to be doing. http://nickdesaulniers.github.io/netfix/demo/bufferAll.html I got this link from my research about Media Source's here: https://developer.mozilla/en-US/docs/Web/API/MediaSource/readyState Also would like to mention that I have received a lot of inspiration from this post and got really far because of this answer HTML5 Video: Streaming Video with Blob URLs

With that in mind I can successfully create a MediaSource and open the buffer, but what I cannot understand is why am I unable to append to the buffer? The error I am recieving is this:

TypeError: Failed to execute 'appendBuffer' on 'SourceBuffer': No function was found that matched the signature provided.

The client side code is the following

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),
    };
  }

  ponentDidMount() {
    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>
    );
  }
}

The error es from the handleData event from my WebSocket when the server is sending the next streaming byte array data.

As I mentioned about the example and the guide from the link I have posted I looked at their code and stepped through it. According to them Append Buffer should work fine, however even in their code appendbuffer() is only listed in the proto section see here:https://drive.google./open?id=1vOU4oM-XoKe71DofQuLU2THxMdgiown_ and yet the code doesn't plain about their appendbuffer(). When I console log my buffer it looks like theirs https://drive.google./open?id=1T4Ix-y124NgQJ9xu97xv4U2yFTn2k7vF. What am I missing?

I feel like the answer is very obvious but it is escaping me as to what I am doing wrong.

Share edited May 30, 2020 at 2:26 Fifth Cloud asked May 28, 2020 at 13:21 Fifth CloudFifth Cloud 1601 gold badge2 silver badges9 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

I'm building a similar project myself, using several high-end RTSP-enabled IP cameras, and just ran into the same error today. First of all, keep in mind that this API is experimental, according to the Mozilla Developer Network (MDN) documentation (link below).

That being said, I seem to have found the root cause of the issue, even though I'm not a JavaScript expert by any stretch. It turns out that you can't directly pass the "Blob" object from data.data in handleData() into the appendBuffer() method. Instead, you need to convert the Blob to a data type that's supported by the appendBuffer() method first, before passing it in.

  1. Turn you event handler into an async function
  2. Use the Blob.arrayBuffer() to convert the data blobs into a JavaScript ArrayBuffer

Change this:

  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);
      }
    }
  }

Into this:

  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);
  }

The problem is, once you do this, you'll start getting a new error, because there is too much data being passed into the SourceBuffer object on the MediaSource. Since it can't keep up with the input stream, you'll see something similar to the following error:

Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer is still processing an 'appendBuffer' or 'remove' operation

It seems like we need to "buffer the buffers," as odd as that sounds.

I haven't solved this new error yet. If you find a solution, I would love some help.

Related Reading

  • SourceBuffer.appendBuffer() MDN Docs
  • MessageEvent (from WebSocket.onmessage event handler)
  • Blob.arrayBuffer() method
  • Exceeding the Buffering Quota (Google Dev Docs)

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>