title: Difference between "update" and "updateend" events in Media Source Extensions
body: <p>Could anyone explain the difference between the two <code>SourceBuffer</code> events and when to use one over the other?  The <a href="https://www.w3.org/TR/media-source/#sourcebuffer-events" rel="nofollow noreferrer">W3C spec</a> is confusing to me because it reads like the same thing ("completed" vs "ended"):</p>
  
  <ol>
  <li><em>update</em> - The append or remove has successfully completed</li>
  <li><em>updateend</em> - The append or remove has ended.</li>
  </ol>
  
  <p>Testing with the following code below. Chrome fires the <code>error</code> event, Firefox does not:</p>
  
  <pre><code>const tests = {
    //  64K of invalid bytes
    'Invalid Bytes': new Int8Array(1024 * 64),
  
    // valid WebM Opus header bytes (from a random file)
    'Valid Header Bytes': new Uint8Array([26,69,223,163,1,0,0,0,0,0,0,31,66,134,129,1,66,247,129,1,66,242,129,4,66,243,129,8,66,130,132,119,101,98,109,66,135,129,4,66,133,129,2,24,83,128,103,1,0,0,0,0,0,217,18,17,77,155,116,64,29,77,187,139,83,171,132,21,73,169,102,83,172,129,223,77,187,140,83,171,132,22,84,174,107,83,172,130,1,48,236,1,0,0,0,0,0,0,179,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,73,169,102,1,0,0,0,0,0,0,69,42,215,177,131,15,66,64,77,128,141,76,97,118,102,53,54,46,52,48,46,49,48,49,87,65,141,76,97,118,102,53,54,46,52,48,46,49,48,49,115,164,144,52,234,234,126,227,12,45,154,239,221,105,21,212,101,42,213,68,137,136,64,184,70,0,0,0,0,0,22,84,174,107,1,0,0,0,0,0,0,98,174,1,0,0,0,0,0,0,89,215,129,1,115,197,129,1,156,129,0,34,181,156,131,117,110,100,134,134,65,95,79,80,85,83,86,170,131,99,46,160,86,187,132,4,196,180,0,131,129,2,225,1,0,0,0,0,0,0,17,159,129,2,181,136,64,231,112,0,0,0,0,0,98,100,129,16,99,162,147,79,112,117,115,72,101,97,100,1,2,56,1,128,187,0,0,0,0,0])
  };
  
  (async () =&gt; {
    for (let testName of Object.keys(tests)) {
      console.group(testName);
      await testSourceBuffer(tests[testName])
      console.groupEnd();
    };
    console.log('All tests done!');
  })()
  
  async function testSourceBuffer(byteArray) {
    return new Promise(resolve =&gt; {
      const audio = new Audio();
      const mediaSource = new MediaSource();
  
      // debug other MediaSource Events
      ['sourceended', 'sourceclose'].forEach(name =&gt; {
        mediaSource.addEventListener(name, e =&gt; {
          console.log('MediaSource', e.type);
          if (e.type === 'sourceended') {
            resolve();
          }
        })
      })
  
      mediaSource.onsourceopen = e =&gt; {
        console.log('MediaSource', e.type);
        URL.revokeObjectURL(audio.src);
        const sourceBuffer = mediaSource.addSourceBuffer('audio/webm; codecs=opus');
  
        // debug SoruceBuffer events
        ['abort', 'error', 'update', 'updateend', 'updatestart'].forEach(name =&gt; {
          sourceBuffer.addEventListener(name, e =&gt; {
            const color = e.type === 'error'? 'color: red' : ''
            console.log(`%cSourceBuffer ${name}`, color);
            if (e.type === 'updateend') {
              if (mediaSource.readyState === 'open') {
                mediaSource.endOfStream();
              }
            }
          })
        })
  
        sourceBuffer.appendBuffer(byteArray);
      }
  
      audio.src = URL.createObjectURL(mediaSource)
    });
  }
  </code></pre>