title: "encrypted" event not firing albeit feeding source buffer with cenc mp4 data
body: <p>I am trying to understand how DRM systems work so my journey begins by trying to play a cenc encrypted mp4 video using the Clear Key DRM system without using any library like dash.js or Shaka Player.</p>
  <p>The first problem I encountered is that I do not always receive the &quot;encrypted&quot; event.
  I receive the &quot;encrypted&quot; only on Safari, but not on Google Chrome nor on Firefox.</p>
  <p>Interestingly I do receive the &quot;waitingforkey&quot; on Google Chrome and Safari, but not on Firefox.</p>
  <p>This fact confuses me the most, because if Google Chrome knows it needs a key, I assume it has to know that the media is encrypted, so why does it not fire the &quot;encrypted&quot; event?</p>
  <p>Below you can find the code I use. I am using some convenience functions. I hope it is clear what they do. If not you see their definitions <a href="https://alex1s.github.io/EME/utils.js" rel="nofollow noreferrer">here</a>. Also my example is online <a href="https://alex1s.github.io/EME/encrypted_event.html" rel="nofollow noreferrer">here</a> for you to test and debug right in the browser.</p>
  <pre><code>async function playClearkeyVideoFromUrls(videoElement, initUrl, urls) {
      // for debugging purposes
      videoElement.addEventListener(`waitingforkey`, () =&gt; console.log(`Event: waitingforkey`))
      videoElement.addEventListener(`encrypted`, () =&gt; console.log(`Event: encrypted`))
      videoElement.addEventListener(`error`, function () {
          console.log(`Event: HTMLMediaElement.onerror`)
          console.log(this.error)
      })
  
      // we create a MediaSource
      const mediaSource = new MediaSource()
  
      // attach the MediaSource to the Video tag, only then it will fire the &quot;sourceopen&quot; event
      videoElement.src = URL.createObjectURL(mediaSource)
  
      // add a SourceBuffer to the MediaSource, we need to specify the MIME type of the video we want to play
      const sourceBuffer = await mediaSource.asyncAddSourceBuffer(`video/mp4;codecs=&quot;avc1.64001f&quot;`)
  
      // for debugging purposes
      sourceBuffer.addEventListener(`error`, e =&gt; {
          console.log(`Event: SourceBuffer.onerror`);
          console.log(e)
      })
  
      // append the first (init) segment
      console.log(`Appending the first (init) segment`)
      await sourceBuffer.asyncAppendBuffer(await fetchArrayBuffer(initUrl), videoElement)
  
      // here I expect the &quot;encrypted&quot; AND &quot;waitingforkey&quot; event to fire
  
      // now append the rest of the segments
      for (let i = 0; i &lt; urls.length; i++) {
          const url = urls[i]
          console.log(`Appending a segment ...`)
          if (!await sourceBuffer.asyncAppendBuffer(await fetchArrayBuffer(url), videoElement)) {
              console.log(`Canceling playback as an error has occurred.`)
              console.log(videoElement.error)
              break
          }
      }
  }
  </code></pre>
  <p>The cenc encrpyted mp4 files I have are from the dash.js examples page, so I assume that this is not the root of my problem.</p>
  <p>To sum up my main question is: Why is the &quot;encrypted&quot; event not fired or is my assumption wrong that it should be fired?</p>
  <p>I also thought that my fancy util functions could be the cause of the problem. Sadly this is not the case. You can check out my version without the utils file <a href="https://alex1s.github.io/EME/encrypted_event.html" rel="nofollow noreferrer">here</a>. It behaves just like the other version.</p>
  <pre><code>let initUrl
  let urls
  let segmentIndex = 0
  
  
  Number.prototype.toStringPadded = function(size) {
      let thisString = this.toString();
      while (thisString.length &lt; size) thisString = &quot;0&quot; + thisString;
      return thisString;
  }
  
  async function fetchArrayBuffer(url) {
      return await (await (await fetch(url)).blob()).arrayBuffer()
  }
  
  async function updateend() {
      console.log(`Event: updateend`)
  
      this.appendBuffer(await fetchArrayBuffer(urls[segmentIndex]))
      segmentIndex++
      if (segmentIndex === urls.length) {
          this.removeEventListener(`updateend`, updateend)
      }
      console.log(`Appended segment with id ${segmentIndex}.`)
  }
  
  async function sourceopen() {
      console.log(`Event: sourceopen`)
  
      // add a SourceBuffer to the MediaSource, we need to specify the MIME type of the video we want to play
      const sourceBuffer = this.addSourceBuffer(`video/mp4;codecs=&quot;avc1.64001f&quot;`)
  
      // for debugging purposes
      sourceBuffer.addEventListener(`error`, e =&gt; {
          console.log(`Event: SourceBuffer.onerror`);
          console.log(e)
      })
  
      sourceBuffer.addEventListener(`updateend`, updateend)
      sourceBuffer.appendBuffer(await fetchArrayBuffer(initUrl))
  }
  
  async function playClearkeyVideoFromUrls(videoElement) {
      // for debugging purposes
      videoElement.addEventListener(`waitingforkey`, (event) =&gt; {
          console.log(`Event: waitingforkey`)
          console.log(event)
      })
      videoElement.addEventListener(`encrypted`, (mediaEncryptedEvent) =&gt; {
          console.log(`Event: encrypted`)
          console.log(mediaEncryptedEvent)
      })
      videoElement.addEventListener(`error`, function () {
          console.log(`Event: HTMLMediaElement.onerror`)
          console.log(this.error)
      })
  
      // we create a MediaSource
      const mediaSource = new MediaSource()
      mediaSource.addEventListener(`sourceopen`, sourceopen)
  
      // attach the MediaSource to the Video tag, only then it will fire the &quot;sourceopen&quot; event
      videoElement.src = URL.createObjectURL(mediaSource)
  }
  
  async function testPlayClearkeyVideoFromUrls() {
      // video urls are from here https://reference.dashif.org/dash.js/nightly/samples/drm/clearkey.html
      // and here https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_ClearKey.mpd
      const streamId = 1
      initUrl = `https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/${streamId}/init.mp4`
      const videoUrlPrefix = `https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/${streamId}/`
      const videoUrlSuffix = `.m4s`
      const numberOfSegments = 4
  
      // first we generate our urls we will download
      urls = []
      for (let i = 0; i &lt; numberOfSegments; i++) {
          const url = `${videoUrlPrefix}${(i + 1).toStringPadded(4)}${videoUrlSuffix}`
          urls.push(url)
      }
      const videoElement = document.querySelector(`video`)
  
      await playClearkeyVideoFromUrls(videoElement)
  }
  
  testPlayClearkeyVideoFromUrls()
  </code></pre>