github.com/pion/webrtc/v3@v3.2.24/examples/insertable-streams/jsfiddle/demo.js (about)

     1  /* eslint-env browser */
     2  
     3  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     4  // SPDX-License-Identifier: MIT
     5  
     6  // cipherKey that video is encrypted with
     7  const cipherKey = 0xAA
     8  
     9  const pc = new RTCPeerConnection({ encodedInsertableStreams: true, forceEncodedVideoInsertableStreams: true })
    10  const log = msg => {
    11    document.getElementById('div').innerHTML += msg + '<br>'
    12  }
    13  
    14  // Offer to receive 1 video
    15  const transceiver = pc.addTransceiver('video')
    16  
    17  // The API has seen two iterations, support both
    18  // In the future this will just be `createEncodedStreams`
    19  const receiverStreams = getInsertableStream(transceiver)
    20  
    21  // boolean controlled by checkbox to enable/disable encryption
    22  let applyDecryption = true
    23  window.toggleDecryption = () => {
    24    applyDecryption = !applyDecryption
    25  }
    26  
    27  // Loop that is called for each video frame
    28  const reader = receiverStreams.readable.getReader()
    29  const writer = receiverStreams.writable.getWriter()
    30  reader.read().then(function processVideo ({ done, value }) {
    31    const decrypted = new DataView(value.data)
    32  
    33    if (applyDecryption) {
    34      for (let i = 0; i < decrypted.buffer.byteLength; i++) {
    35        decrypted.setInt8(i, decrypted.getInt8(i) ^ cipherKey)
    36      }
    37    }
    38  
    39    value.data = decrypted.buffer
    40    writer.write(value)
    41    return reader.read().then(processVideo)
    42  })
    43  
    44  // Fire when remote video arrives
    45  pc.ontrack = function (event) {
    46    document.getElementById('remote-video').srcObject = event.streams[0]
    47    document.getElementById('remote-video').style = ''
    48  }
    49  
    50  // Populate SDP field when finished gathering
    51  pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
    52  pc.onicecandidate = event => {
    53    if (event.candidate === null) {
    54      document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
    55    }
    56  }
    57  pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
    58  
    59  window.startSession = () => {
    60    const sd = document.getElementById('remoteSessionDescription').value
    61    if (sd === '') {
    62      return alert('Session Description must not be empty')
    63    }
    64  
    65    try {
    66      pc.setRemoteDescription(JSON.parse(atob(sd)))
    67    } catch (e) {
    68      alert(e)
    69    }
    70  }
    71  
    72  // DOM code to show banner if insertable streams not supported
    73  let insertableStreamsSupported = true
    74  const updateSupportBanner = () => {
    75    const el = document.getElementById('no-support-banner')
    76    if (insertableStreamsSupported && el) {
    77      el.style = 'display: none'
    78    }
    79  }
    80  document.addEventListener('DOMContentLoaded', updateSupportBanner)
    81  
    82  // Shim to support both versions of API
    83  function getInsertableStream (transceiver) {
    84    let insertableStreams = null
    85    if (transceiver.receiver.createEncodedVideoStreams) {
    86      insertableStreams = transceiver.receiver.createEncodedVideoStreams()
    87    } else if (transceiver.receiver.createEncodedStreams) {
    88      insertableStreams = transceiver.receiver.createEncodedStreams()
    89    }
    90  
    91    if (!insertableStreams) {
    92      insertableStreamsSupported = false
    93      updateSupportBanner()
    94      throw new Error('Insertable Streams are not supported')
    95    }
    96  
    97    return insertableStreams
    98  }