Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
  <!-- AR screen -->
  <!--   <div class="fixed-fullscreen" id="ar-screen"> -->
  <!-- Agora -->
  <div id="main-container">
    <div id="full-screen-video"></div>
    <div id="lower-video-bar" class="row fixed-bottom mb-1">
      <div id="remote-streams-container" class="container col-9 ml-1">
        <div id="remote-streams" class="row">
          <!-- insert remote streams dynamically -->
        </div>
      </div>
      <div id="local-stream-container" class="col p-0">
        <div class="col p-0 fixed-fullscreen" id="ar-screen"></div>
        <button id="change-effect-button">Change effect</button>
      </div>
    </div>
  </div>
  </div>
</body>
              
            
!

CSS

              
                body {
  margin: 0px;
  padding: 0px;
  font-family: sans-serif;
}

#full-screen-video {
  position: absolute;
  width: 100vw;
  height: 100vh;
}

#lower-video-bar {
  height: 30vh;
}

#local-stream-container {
  position: relative;
  display: inline-block;
}

#ar-screen {
  position: absolute;
  z-index: 1;
  height: 30vh;
}

.remote-stream-container {
  display: inline-block;
}

#remote-streams {
  height: 100%;
}

.remote-video {
  position: absolute;
  z-index: 1;
  height: 100% !important;
  width: 80%;
  max-width: 500px;
}

#change-effect-button {
  font-size: 15px;
  position: absolute;
  bottom: 5px;
  right: 20px;
  z-index: 2;
  border-radius: 10px;
  font-family: Avenir;
  font-size: 1rem;
  font-weight: 600;
  border: 1px solid rgb(73, 144, 226);
  display: block;
  width: fit-content;
}

              
            
!

JS

              
                import deepar from "https://esm.sh/deepar";
import AgoraRTC from "https://esm.sh/agora-rtc-sdk-ng";

const licenseKey = "your_license_key_goes_here"; // create project and license key at developer.deepar.ai, set domain to cdpn.io

/*
- Sign up on Agora.
- Create a project and get the App ID.
- Generate a temp RTC token. Get the token and the channel name associated with it.
*/
const appId = "**appId**";
const token = "**token**";
const channel = "**channel name**";

// Log the version. Just in case.
console.log("Deepar version: " + deepar.version);
console.log("Agora version: " + AgoraRTC.VERSION);

(async function () {
  // Get the element you want to place DeepAR into. DeepAR will inherit its width and height from this and fill it.
  const previewElement = document.getElementById("ar-screen");

  const effectUrls = [
    "https://s3.eu-west-1.amazonaws.com/demo.deepar.ai/assets/background-replacement-stars/background-replacement-stars.deepar",
    "https://s3.eu-west-1.amazonaws.com/demo.deepar.ai/assets/cracked-porcelain-face/cracked-porcelain-face.deepar",
    "https://s3.eu-west-1.amazonaws.com/demo.deepar.ai/assets/cute-virtual-pet/cute-virtual-pet.deepar"
  ];

  // Initialize DeepAR with an effect file.
  let deepAR;
  try {
    deepAR = await deepar.initialize({
      licenseKey: licenseKey,
      previewElement,
      effect: effectUrls[0]
    });
  } catch (error) {
    console.error(error);
    return;
  }

  const remotePlayerContainer = document.getElementById("subscriber");

  // Agora
  var cameraVideoProfile = "480p_4"; // 640 × 480 @ 30fps  & 750kbs

  let agoraEngine = new AgoraRTC.createClient({ mode: "rtc", codec: "vp9" });

  var remoteStreams = {};
  var mainStreamId;

  agoraEngine.on("user-published", async (user, mediaType) => {
    await agoraEngine.subscribe(user, mediaType);
    user["type"] = mediaType;
    let remoteAudioTrack, remoteVideoTrack;
    let remoteId = user.uid;

    if (mediaType == "video") {
      remoteAudioTrack = user.audioTrack;
      remoteVideoTrack = user.videoTrack;
      if ($("#full-screen-video").is(":empty")) {
        // first remote, set as main stream
        remoteStreams[remoteId] = user;
        mainStreamId = remoteId;
        remoteVideoTrack.play("full-screen-video");
      } else {
        // add as mini view
        agoraEngine.setRemoteVideoStreamType(user.uid, 1); // subscribe to the low stream
        addRemoteStreamMiniView(user);
      }
    }
    if (mediaType == "audio") {
      remoteAudioTrack = user.audioTrack;
      // Play the remote audio track. No need to pass any DOM element.
      remoteAudioTrack.play();
    }
    console.log("Subscribe remote stream successfully: " + remoteId);
  });
  agoraEngine.on("user-unpublished", (user) => {
    console.log(user.uid + " has left the channel");
    var streamId = user.uid; // the the stream id
    if (remoteStreams[streamId] != undefined) {
      delete remoteStreams[streamId]; // remove stream from list
      if (streamId == mainStreamId) {
        var streamIds = Object.keys(remoteStreams);
        if (streamIds.length == 0) {
          return;
        }
        var randomId = streamIds[Math.floor(Math.random() * streamIds.length)]; // select from the remaining streams
        var remoteContainerID = "#" + randomId + "_container";
        $(remoteContainerID).empty().remove(); // remove the stream's miniView container
        remoteStreams[randomId].videoTrack.play("full-screen-video"); // play the random stream as the main stream
        mainStreamId = randomId; // set the new main remote stream
      } else {
        var remoteContainerID = "#" + streamId + "_container";
        $(remoteContainerID).empty().remove(); //
      }
    }
  });

  function addRemoteStreamMiniView(user) {
    var streamId = user.uid;
    // append the remote stream template to #remote-streams
    $("#remote-streams").append(
      $("<div/>", {
        id: streamId + "_container",
        class: "remote-stream-container col"
      }).append(
        $("<div/>", { id: "agora_remote_" + streamId, class: "remote-video" })
      )
    );
    user.videoTrack.play("agora_remote_" + streamId);
    user.audioTrack.play();
    remoteStreams[streamId] = user;

    var containerId = "#" + streamId + "_container";
    $(containerId).dblclick(function () {
      // play selected container as full screen - swap out current full screen stream
      remoteStreams[mainStreamId].videoTrack.stop(); // stop the main video stream playback
      addRemoteStreamMiniView(remoteStreams[mainStreamId]); // send the main video stream to a container
      $(containerId).empty().remove(); // remove the stream's miniView container
      remoteStreams[streamId].videoTrack.stop(); // stop the container's video stream playback
      remoteStreams[streamId].videoTrack.play("full-screen-video"); // play the remote stream as the full screen video
      mainStreamId = streamId; // set the container stream id as the new main stream id
    });
  }

  await agoraEngine.join(appId, channel, token);

  const canvas = deepAR.getCanvas();

  const canvasContext = canvas.getContext("webgl2"); // If this is not called, captureStream() throws on Firefox.
  const outputStream = canvas.captureStream(30);
  let videoTrack = outputStream.getVideoTracks()[0];
  let localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
  let localVideoTrack = AgoraRTC.createCustomVideoTrack({
    mediaStreamTrack: videoTrack
  });
  agoraEngine.publish([localVideoTrack, localAudioTrack]);

  // Off screen rendering when tab is not in focus
  let visible = true;
  document.addEventListener("visibilitychange", function (event) {
    visible = !visible;
    if (!visible) {
      deepAR.setOffscreenRenderingEnabled(true);
    } else {
      deepAR.setOffscreenRenderingEnabled(false);
    }
  });

  // Change effect button
  let effectIndex = 0;
  const changeEffectButton = document.getElementById("change-effect-button");
  changeEffectButton.onclick = async function () {
    changeEffectButton.disabled = true;
    effectIndex = (effectIndex + 1) % effectUrls.length;
    await deepAR.switchEffect(effectUrls[effectIndex]);
    changeEffectButton.disabled = false;
  };
})();

              
            
!
999px

Console