github.com/pion/webrtc/v4@v4.0.1/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 }