Holidays like Halloween are shaping up to look a bit different this year, with most office celebrations going virtual. But have no fear, spooky season always finds a way!
At Daily, we power 1-click video for websites and apps. Developers use our tools to embed fully functional prebuilt video chat widgets in minutes, and to build completely custom call experiences. In this tutorial, we’ll use Daily’s prebuilt UI to play trick-or-treat in our next virtual standup.
What we’ll build
We’re going to embed Daily’s video chat widget into a webpage. We’ll decorate the page using a little CSS, JavaScript, and a whole lot of gifs. We’ll also listen for Daily API events to set random background images and sound effects when participants join the call.
What you’ll need to build it
- Daily account: Sign up if you don’t have one already!
- GIPHY API key: So that we can have some fun with gifs.
How to build it
Create a Daily room and embed the room on your webpage
A Daily room URL is made up of your unique Daily domain followed by the room name. Each room URL points to a unique video chat location, and looks something like:
https://your-domain.daily.co/<room-name>/
You can create rooms either through a POST request to the /rooms Daily API endpoint, or from the Daily dashboard. Pick whichever method and name you’d like. I went for the dashboard and set the room name to spooky
, of course.
Once you have a room, you can use Daily’s prebuilt UI by embedding the room URL into any website or app, for example:
<html>
<script src="https://unpkg.com/@daily-co/daily-js"></script>
<body>
<script>
callFrame = window.DailyIframe.createFrame();
callFrame.join({ url: 'https://your-team.daily.co/<room-name>' })
</script>
</body>
</html>
In our demo, we also take advantage of the DailyIframe iframeStyle
property to position our video chat before we call the .join
method:
callFrame = window.DailyIframe.createFrame({
iframeStyle: {
border: 0,
display: 'block',
margin: 'auto',
width: '50%',
height: '100%',
},
});
Note: While we’re hard-coding our room URLs for the purpose of this demo, in production code you’ll want to generate your meeting rooms dynamically server side, without revealing them on the frontend. Read about how to set up an instant server with Glitch.
Randomize the background image
I definitely spent more time deciding what images to use for the backdrop of the call than I spent integrating the Daily video chat widget. I went down a little bit of a rabbit hole, and ultimately wound up using images from Unsplash, pixabay, and Pexels. I also really appreciated the Halloween illustrations on Mixkit and Undraw. Choose whatever speaks to you, the world is your cauldron!
Once you’ve picked your images, it’s time to turn to Daily events, and listen for whenever a local participant joins a call. Whenever the joined-meeting
event fires, we’ll call a function to set the background image:
callFrame
...
.on('joined-meeting', setBackground)
...
Our setBackground
function stores a list of our photos’ names in an array. It then uses the length of the array and the built-in JavaScript Math object to pick a random array index. Once the random index is selected, the function manipulates the DOM body property to set the page's background image.
async function setBackground(event) {
try {
const photos = ['candy.jpg', 'forest.jpg', 'jack-o-lanterns.jpg'];
let randomIndex = Math.ceil(Math.random() * (photos.length - 1));
document.body.style.backgroundImage = `url('/static-demos/spooky-demo/assets/${photos[randomIndex]}')`;
} catch (error) {
console.error(error);
}
}
In spooky.css
, we set the body’s background-size
property to cover
, so the image, like the spooky forest below, will cover the entire screen behind the call.
Rotate gifs
If random festive backgrounds are the trick, then rotating random gifs are the treat. To add these to your call, first you’ll need your GIPHY API key.
Our getGifs
function makes a request to the GIPHY API search endpoint, and passes in a search query for Halloween gifs that are rated pg. It saves the response, an object full of gifs, in the gifs
variable, which it returns.
async function getGifs() {
try {
// TODO: replace the below with you giphy API key
// In production, you'll need to store your key securely, vs. hard coding
const token = 'YOUR-GIPHY-API-KEY';
const giphyEndpoint = `https://api.giphy.com/v1/gifs/search?api_key=${token}&q=halloween&rating=pg`;
const response = await fetch(giphyEndpoint);
const gifs = await response.json();
return gifs;
} catch (error) {
console.error(error);
}
}
We’ll call getGifs()
within our run
function. We call run()
as soon as the page loads. Within run()
, every 20 seconds we extract a random gif's url from the gifs response object. We save the randomly selected url in a url
variable. We can now set the src
property of <img id='gifs'>
to url
.
const gifSearchResults = await getGifs();
setInterval(() => {
try {
let url =
gifSearchResults.data[Math.floor(Math.random() * 50)].images
.original.url;
document.getElementById('gifs').src = url;
} catch (error) {
console.error(error);
}
}, 20 * 1000);
If you’re curious about how we styled our gifs, here’s how we made them rotate through a circular "moon" in the top-right corner:
#gifs {
object-fit: contain;
}
#gif-wrapper {
position: fixed;
border-radius: 50%;
border: 2px solid #e2dccd;
background: black;
width: 15vw;
height: 25vh;
top: 2%;
right: 5%;
display: flex;
justify-content: space-evenly;
align-items: center;
overflow: hidden;
}
But you should feel free to style however you like! Much like costumes, no one CSS style suits everyone. Make it your own!
Add sound effects to Daily events
Much like picking a background image, landing on my sound effect of choice was tough. I wound up going with a clip of The Addams Family theme song, but there are lots of options out there for creaky doors, cackling witches, and anything else you can imagine. I just couldn’t say no to these faces.
Once you have your sound, save it in your project. I put mine in my /assets
folder along with my background images. Then, add an <audio>
tag to your HTML:
<audio src='assets/the-addams-family-intro-theme-song.mp3'></audio>
Just like we did whenever the local participant joins a call, we added an event listener to play a sound whenever another participant logs on. We listen for the participant-joined
event.
callFrame
...
.on('participant-joined', playSound)
...
When that happens, playSound
finds our <audio>
element and calls the DOM play()
method.
async function playSound(event) {
try {
const sound = document.querySelector('audio');
sound.play();
} catch (error) {
console.error(error);
}
}
What’s next
There’s so much more you can do to customize your call: experiment with different event listeners, styles, etc. You could even build an entirely custom call using the Daily call object, e.g. placing participants' video streams in the windows of a haunted house.
You can customize Daily calls for any spooky or special occasion. I got the idea for this post from all of the fun wedding send-offs and birthday surprises my colleagues have built (especially Mattie Ruth!). If you want to get in on all that fun and more, including the challenges of building video chat infrastructure, we’re hiring! Please send me a note if you’re interested in joining the team. I’m happy to help any way I can.
Top comments (0)