skip to content

Put videos behind auth

How do you build a web app that only shows video content to logged-in users? Darius Cepulis will show us how to set it up with Mux.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON LENGSTORF: Hello, everyone, and welcome to another episode of Learn With Jason. Today, on the show, we're going to be digging into a more practical project than usual. A lot of times on this show, we will kind of go, Hello World. Today, we're actually going to work on something that I'm actively working on, which is the next iteration of the Learn With Jason site. We are going to be digging into a specific feature I need.
Welcome to the stage, Darius Cepulis. Darius, how you doing?

DARIUS CEPULIS: What's going on? Doing well. How are you?

JASON LENGSTORF: I'm doing great. I'm happy you're here, not because I'm stuck on a technical problem and need your help. [Laughter]. This area of tech, which I have not introduced yet� unless you know the title of the video� I think this area of tech is underexplored. We kind of, as a community, seated this whole ground to a handful of small players.
I want to talk a little bit about you. Can you give us a bit of a background on yourself?

DARIUS CEPULIS: Yeah. I'm currently a senior community engineer at Mux. I kind of stumbled my way upwards into this. I went to school for computer engineering, I thought I was going to do hardware and build the next whatever processor. I went to my internship at BMW and in hardware positions. Had a lot of fun there. As a side project, I built something for censor data. I'm applying to these software engineers and nobody's biting. It's jobs out of school. [Laughter]. And then out of nowhere, somebody emails me and says, do you want to be our website person? I started web development and it's amazing. Everything that I'm sure you and our viewers know and love about web development. There's just, like, in addition to being a lot easier than embedded systems, there's this really tangible interaction with the users and the parts about the internship I liked the most was interacting.
I'm a web developer at Mux and I'm writing blog posts. They're like, maybe you should be a community engineer, as well. Tried to be an embedded systems engineer and now I'm writing blog posts and doing videos.

JASON LENGSTORF: I like that as a career strategy, too. You start out with a plan, but then you're willing to make adjustments as you learn more. I've met a few folks who decided they were going to do things a certain way and they stuck to it no matter what. I think that leaves you feeling boxed in. If you notice, well, I thought I wanted this, but this is fun, too. And you end up somewhere completely different than you planned, but it is based on new input and new information.
I love that. I love that so much. Okay. So, what I want to talk about is...well, let's talk a little bit in the abstract before we get into the specifics of what I want to do and let's talk about video on the web. I remember, back in� because I've been building for the web for long time now, over 20 years. I remember, in the beginning, when you had video, you just didn't. It was easier to not do video than to try to figure out how video would work. I remember that we saw, very early on, sites would emerge that were kind of built for videos, EBaum's World. They were where that video was hosted. Later, in a kind of explosion of popularity and growth, YouTube came on the scene and became the de facto standard for users uploading videos. We see Vimeo enter, we saw� what's the other one? It's got a "w" name?

DARIUS CEPULIS: Wistia?

JASON LENGSTORF: Then we see the lowlevel stuff, there's AWS services for video. You can always throw it up on S3 or something. But it felt to me, as a industry, we threw up our hands and said, if I'm not going to throw it on Vimeo or Wistia, I'm going to leave it.
Do you have any hunches or theories as to why video� why we've kind of unanimously outsourced this to other people?

DARIUS CEPULIS: Boy, do I. [Laughter]. Video is deceptively hard and I think that there are two kinds of developers in this world. The ones that don't realize it and the ones who haven't� you know� do. Both the developers, I think, their first thoughts are, well, I know YouTube video. Why don't I toss it up there. YouTube's free and it hides all this complexity from you. If you don't know how complex it is, you're blissfully ignorant.

JASON LENGSTORF: Right. So, kind of digging into that a little bit more...is it� I guess, is it too hard to� to run video yourself? Because you say it's deceptively hard and I know that as I've dug into it in the past, one was bandwidth cost. If I selfhost a video, my bandwidth usage goes up if anyone watches that video because I've uploaded in 4K. And so now, every time somebody loads my website, they're downloading my 4K video. I'm burning bandwidth or if I open it on my phone, my phone doesn't need a 4K multigigabyte video. I guess I'll serve the big one, right. That's before we get into things like the default control with the HTML web. Video, in HTML, seems like it's got a lot better.
But it's still� you know, the controls are fairly basic when you start customizing things, it gets hard. It doesn't have a lot of the features you'd expect when you watch Netflix and YouTube. I don't know how to add chapters or markers. If you hover or the timeline, I can't see where I am in the video. All of that stuff is stuff that I've come to expect from a video service and so it all kind of drives me toward, yeah, why wouldn't I put it up on YouTube.

DARIUS CEPULIS: Uhhuh. Uhhuh. Yeah.

JASON LENGSTORF: But then I have these other needs, these other questions. For example, I really like the idea of making video not depend on a thirdparty. Like, putting all of my video up on YouTube, where YouTube has content policies, that at some point, they might decide arbitrarily that dudes with beards aren't allowed on the platform and I signed the user agreements, and all of my work is gone. Right. And that makes me nervous when I'm in a position where this video is a huge part of my business. This is what I do. Right. If I were to lose that work or lose my YouTube channel, does that mean I'm finished as a businessperson. I like the idea of owning my presence. If I want to put videos somewhere, I want to put it on my site. I want it to live on the Learn With Jason site. Obviously, there's still terms of service with everything because you're hosting platform and assets managers, they all have, like, fair use policies and I can't copyrightinfringe. I can't hate speech.
AWS isn't going to suddenly decide that you can't have a beard, right. Or that you can't say certain words that they've decided are too inflammatory for their algorithm.
All of this is me taking a very long time to get a question. What is a good reason to take on the burden of, like, managing video on your own?

DARIUS CEPULIS: Yeah. Well, you've just described is, I think, something that a lot of folks that use YouTube run into. Like, even I was� whatever� creating portfolio websites and I wanted to put a video on and I didn't want the YouTube embed. This is just for a hobby project. But anybody with a small business, all of a sudden, has concerns of not only what you described, gee whiz, somebody's content policy. Is YouTube turning Gemini? YouTube's a really good solution for a lot of people. There's some sort of reason that I want to leave. And that is. [Laughter]. � if they are� if they are overconfident developers, like I am or so many others are, well, why don't I host this MP4. Darn, I need to start making renditions, might don't I break it down and sell the smaller renditions to mobile, it's downloading the whole video and I need to break it into chunks. Then you've got the player side. Now if I don't have YouTube's player, I have to make my own player. Am I going to do the timeline hovers? There's this huge glacier of problems underneath a video that� I mean, back to your original question� brings people back to you tube.

JASON LENGSTORF: I think the major challenge is finding the right balance. I'll never stop using YouTube. If they watch your stuff, they'll see more of your stuff later, assuming they'll like it. That, to me, is a good place to be. But at the same time, I don't necessarily want to build my entire platform on YouTube. In the new version of the site, I want to allow people become supporters of the channel. Sort of a Patreon model. I want to follow in the footsteps of Nebula and Dropout, where if you're a subscriber, you can actually see stuff early, before it goes public. To me, that's really exciting because it provides a way to create a tangible benefit that doesn't put you on� on the hook, as a creator, which is one of the things that I've always been really concerned about with paid tiers and stuff. I don't have the bandwidth to make a whole second suite of content for paid folks. I'm barely able to get the content out that I get out now. If I do a paid tier, that helps me with the cost of producing stuff, but I don't have the ability to create two times the content to give bonus content.
YouTube has a way that you can become a paid member and then that lets you see things on YouTube. A lot of people right now� the majority of folks are on Twitch right now. You can see, here's one of the Vinny's on Twitch. So, the Twitch people, if they want to subscribe, they wouldn't get access to the YouTube, like early access. Am I going to say, you have to subscribe to me on multiple platforms and each of those is taking 50%, or more, so I can build bigger and better videos. All of which has led me to the core dilemma and the reason I'm thinking of selfhost video on Learn With Jason.
And, two is this membership thing. I want people to be able to have a centralized membership and I can always write custom code that says, if you are a Twitch subscriber, you get the access that a websitepaid member would get. But I can't get that on YouTube. So now that leads me to the� how long did this take me? 14minute segue. [Laughter]. How can I host my own video and make it so that only people who are logged in� and with a valid subscription� are able to view it for a limited period of time?

DARIUS CEPULIS: Well. Boy, am I glad you asked, Jason. [Laughter]. You might have heard at the beginning, I mentioned, I'm from Mux. I'm community engineer at Mux. And I'm superhappy to talk about how Mux solves so many of these problems. Problems you just didn't even realize you have. Mux is a video API for developers. We solve a lot of the things that I talked about. We create those renditions. We have a player. A whole bunch of stuff, which lets you focus on what you want to focus on, your business, your Twitch. Once you have video problems, you come to us. We've got a couple different ways, from, you know, the basic form is just going to be, like, hiding the link behind an auth. What about linksharing? We have signed URLs. The problems go on and I'm excited to get into them in the stream.

JASON LENGSTORF: Absolutely. Okay. So, in the interest� I could talk about this in the abstract forever so I'm going to stop myself from doing that. We'll talk about stuff, as it comes up. So, let's get in here and actually do some coding. So, I'm going to switch us over into this view, here, I'm then going� you want to see something cool? I switched over to Raycast�

DARIUS CEPULIS: No, way. Me, too.

JASON LENGSTORF: It's very good. But it's super lowlevel. It's called Yabai. It's a window manager that requires you to turn off system requirement checks. I kept breaking it. So, then, the Raycast team was like, you know we do that, right. I was like, okay, let me try this. So I� I was like, oh, my god. Everything that I wanted� it was� [Laughter]. � anyways. You should� [Laughter]. If you� [Laughter]. If you, like me, want to be able to manage your windows very well, this stuff, in Raycast, is dope. Anyways, that's not what we're talking about today. Let's talk about our sponsor. We've got Netlify, pitching in to make this show accessible. We have Vanessa, here with us today, doing our live captioning. I'm going to scroll the link down along the bottom, if you want to� if you want to head over there, if you need those captions.
And then...also, I� so, the origin of this episode is actually fun because I started bothering the Mux team because I had these questions and I was like, here's what I'm trying to do, here's why I'm stuck. Here's what I'm worried about. It turned into� it was like, you know what? Why don't we do an episode on this because there are so many questions. Thank you to Mux for actually choosing to sponsor this episode.
We are talking to Darius. You should go follow Darius on Twitter. Make sure you go and do that. And, we're talking about Mux. So, let's� let's do that. Let's� I mean, let's just dive into it, right.
Darius, if I want to get video on my site, protected by auth, what's my first step?

DARIUS CEPULIS: Yeah. So, your sentence, get video protected by auth. Step one, let's get video on your site. Great place to start is the docs. You'll find under Docs and Tools. One thing that is absolutely our pride and joy at Mux is we think about docs as a product. We know if we're building for developers, developers have to spend a lot of time on our docs. These docs will take you from the very beginning of not understanding video to integrating stuff on your site.
I was thinking, though, maybe because I'm here, we can skip some of the docs, at least getting video on your site so we can jump to the juicy stuff with auth.

JASON LENGSTORF: I might have a bit of a turkey in the oven here. I have been working on a new version of the Learn With Jason site. And, this site...still has� it is not quite styled yet, but what I have is, I'm trying to show seriesbased stuff so I have a collection of series. I've got the Web Dev Challenge and a short run of video called Do It Anyways. That one, I've uploaded videos on. When you click on a series, you get an overview and a list of the series and if I make a second season, it'll have a season picker. Then, if we dive into one of these videos, I have done the absolute bareminimum...of...setting up a Mux player and I will show you...what I've done here...so, in fact, I should have� you know what? You told me, beforehand, to get into my Mux dashboard and I just didn't do it. So, bear with me� oh, good, I'm still logged in. Great. So, let's maximum again. And I have my assets here...and, you can kind of see, like, this is the video that I was talking about. This is the one that we're looking at, right now, and I uploaded it to Mux. That's all I did. I went to this section of the...what was it? Here?

DARIUS CEPULIS: Uhhuh.

JASON LENGSTORF: Create a New Asset. I dragged the video in. That's all I did on Mux. And then, on this side, I went to the, uh, what is it? The episode...and so, I'm getting...the, um� we're running an API call to get the video and everything and then for the episode, itself...we� where's the video player? Here's my video player. We drop in the episode details. And, I get a playback ID, which is the Mux playback ID...here...it's a playback ID. And then, I use the Mux player� and this is literally all the code that I have. I, like, installed this package and I've copypasted this code out of the docs. So that's where I'm at right now, is that I have assets in Mux. I've used the web component Mux player and I have it pulling a playback ID out of my Astro DB storage.

DARIUS CEPULIS: Nice. That's a fantastic start. That's the thing, Mux is an API so you saw when you said, "create asset." We're giving you API calls. You can build a dashboard. Or honestly, you can upload in our dashboard and copypaste it to our own database. We're trying to teach you how to use the API. Also, if you want to do it the way you did it, absolutely fantastic.
You've got your database, you've got your videos. The next question is, how do we authenticate videos, right?

JASON LENGSTORF: Right. So the way that I'd like for this to work is on, um� on pages� like, let's say we go into the Web Dev Challenge. Season one, episode two is out. Episode one is out. Episode three is coming. When episode three comes out, what I'd like to do is list it here for a week, behind login, so you have to be a member to watch it and at the end of that, after that week, it'll go live on YouTube and become public on this site. That's the flow that I want.
And, how that ends up working...in here, is, like, once you get logged in...you have your profile. And so, you can� I've got it set up where, like, there's a subscription, you go into Stripe and you can choose whatever plan you want. We've got the Boop Enthusiast, the Boop Connoisseur. You can see which level you're currently at and in this case, I am subscribed so I should be able to see the content and we'll be able to� this is all in Test Mode. We'll be able to go in, today, and make sure we can see it and cancel my subscription and then make sure that we can't and go through all this.
This all runs through Stripe. The login, itself, runs through Clerk. That is all running. That's how I want this to function. So, the piece that I'm missing is, when I've got a loggedin user, when I've got a subscription and I've got video assets, how to I start plugging that together so the Mux player is aware whether or not an asset is available to watch? I figure I could hack this together, but I didn't want to. I feel like this should be done for me. [Laughter].

DARIUS CEPULIS: Yeah, yeah. We can absolutely help you with that. So, the first thing you might have considered doing� honestly, this is not a horrible idea, is adding a condition, "if the user is logged in, show them this video." If they're not, don't. If they're logged in, show the playback page. If not, give them a 404. This is a quiz, Jason. Do you see any concerns, any problems with that?

JASON LENGSTORF: So, I think if I was very, very careful with my data, then I could make it so that nobody knows the asset ID and so theoretically I could hide it. If somebody has the asset ID, all they need to do is watch it.

DARIUS CEPULIS: Yeah. Exactly. Head into any of your playback pages and let's take a look at your web inspector, really quick.

JASON LENGSTORF: I only have videos on a couple of these.

DARIUS CEPULIS: Check out Mux player. You can see...yeah, you can see that there is...

JASON LENGSTORF: This is the asset ID, I assume?

DARIUS CEPULIS: Right. This is Mux video. Source.stream.com. You can plop that anywhere and anyone can watch the video. The unfortunately� or fortunate� it's open source, people can inspect. We need a way to lock the video and only give keys to authorized users so only those authorized users can unlock the video. Right.

JASON LENGSTORF: Right.

DARIUS CEPULIS: To do that, we've got a nice, basic solution. It's called Signed URLs.

JASON LENGSTORF: Okay. Signed URLs� somebody was saying earlier that it sounds like� let's see, where's the comment? Sounds like S3, right. That's where I first became aware of the concept of signed URLs.

DARIUS CEPULIS: Exactly. Signed URLs. They have a couple features that I think we'll get into. The basic idea is the video is locked and you hand out keys to users and we can put some conditions on those keys. For example, the key only works� [Laughter]. � there we go. For example, the key only works for one day or one week or something like that. The key only works if you're using it on learnwithjason.com.
Let's do it, I say.

JASON LENGSTORF: Yeah, let's do it. So, from an abstract point of view, what we're going to do is, we're going to generate a different URL that� well, I'm not going to get into the specific  like, we're going to deliver something special to the browser that doesn't actually work out of the gate and I, as a user, have to ask for a key, by passing in my credentials, that say, I'm allowed to watch this thing and I assume I send it as a cookie or a header or something, that then when Mux receives that, it uses my� my credentials to, like, validate that the video can playback.

DARIUS CEPULIS: It might be lessfancier than that.

JASON LENGSTORF: That's perfect, actually. I like it when it's not complicated. [Laughter].

DARIUS CEPULIS: We give you a locked video and it's up to you to give your user a key. Step one, we're going to create a locked video and step two, we're going to create a key which you give to your user.

JASON LENGSTORF: Let's do it.

DARIUS CEPULIS: I think we can create a locked video in your dashboard. That'll be the easiest way. Do you have any videos?

JASON LENGSTORF: I almost certainly have a million videos on my computer. Let me see if I've got any that aren't giant. Here's one that I did, that was� this is, like, a� yeah, we can manage that. Talking about BenQ's ScreenBar Halo, which I'm still using today, and enjoy. Okay, so I've got it. I'm going to create a new asset.

DARIUS CEPULIS: I decided to create a new asset because it is easier to visualize. Step one, baseline and smart. Baseline is more economical, slightlylower quality. But I mean, given your� depending on a certain business model, you might use that. You probably want higherquality videos because of the code. I think Smart's going to make sense. Max resolution if you don't want to spend money distributing 4K, because 4K is expensive. And generated captions, we've got Whispers model.
And then�

JASON LENGSTORF: Whatever boats your float. [Laughter].

DARIUS CEPULIS: It's going to be as easy as changing Line 4 from "public" to "signed."

JASON LENGSTORF: I'm sorry, I just realized these are editable. I thought� I thought that this was, hey, copypaste this. This� oh, my god, I love that. So, we're going to change this to "signed." And upload directly. Okay.

DARIUS CEPULIS: Yeah, "run request." And upload that video to that direct upload.

JASON LENGSTORF: And that was� it was the Ben one, which is someone here.

DARIUS CEPULIS: Nice.

JASON LENGSTORF: It should upload fast. Let's see. There we go.

DARIUS CEPULIS: You can do this to existing videos, too. All of your existing videos are public. They are public playback IDs. You can create� make an API request to Mux and say, hey, Mux, take that one video that's public and also give it a signed playback IDs. You can have it for certain users, all the video goes public. And signed URLs for, you know, the prerelease section.

JASON LENGSTORF: So that's actually going to be important to me because I need...like, I need to switch it over after a week, right. So, can I just put both in here? Like, I can say, signed public, and it will give me both?

DARIUS CEPULIS: We're going to be doing that.

JASON LENGSTORF: Got it. Cool, yeah, I mean, that's great because that was actually� I was worried that was going to be a complicated piece, I didn't want to have to upload videos twice or something. So that's wonderful.

DARIUS CEPULIS: We're going to keep this nice and simple and make one video locked one way. I think this will make the code easy to understand.

JASON LENGSTORF: I have an asset ID, playback. I view the asset.

DARIUS CEPULIS: Notice that not even the dashboard can play it because the video is locked and the dashboard doesn't have the keys to unlock it.

JASON LENGSTORF: Oohhhh. Fascinating. Okay. This is my asset ID�

DARIUS CEPULIS: Playback ID.

JASON LENGSTORF: This is the one we need to use the Mux player on the website.

DARIUS CEPULIS: The reason we have those separate is one asset ID can have multiple playback IDs. You can have a public playback IDs. You'll keep multiple IDs that have multiple permissions.

JASON LENGSTORF: Okay. What I'm going to do then, is I'm going� I'm using Astro DB so I can autocreate�

DARIUS CEPULIS: What? Raycast�

JASON LENGSTORF: Raycast is so dope. I'm really resistant to new anything. I'm like, I'm a fool, I should have used this so long ago. [Laughter]. So, I'm just going to...do that. And then this one will be...keep it simple. If I can type...YouTube ID, I'm not going to have and then this playback ID is going to be this one, here. All right. And then, um...I'll probably just leave the thumbnail because I'm not going to bother with that.

DARIUS CEPULIS: You'll probably want some way, in your database, to identify this as a prereleased video.

JASON LENGSTORF: That's true, isn't it. Why don't we do that real quick. In the config, we'll have a resource relationship and that's going to...what's the� series episode field. So, the episodes field, we're going to include one that says, "prerelease." And that's going to be a boolean. And, we'll default it...to false, so that I don't accident break everything else on the site.
Then, we get back out to my seed and we're going to say, "prerelease is true." Okay.

DARIUS CEPULIS: I can imagine, in production, what you'll probably end up doing is having, like, prerelease playback ID, playback ID, release date field. Stuff like that. If you want, we can work through that complexity here.

JASON LENGSTORF: I think the DB admin stuff is less important than getting�

DARIUS CEPULIS: I don't go, database schemas are what get me out of bed in the morning.

JASON LENGSTORF: I mean, I do love a good database schema� is this the one I'm trying to match? 7928. 7928. I'm basically copying these so I can fake an entry here and that will put this into the Web Dev Challenge so we can actually go watch it. So then, if I come back out here, and we go to the series, the Web Dev Challenge, it's busted.

DARIUS CEPULIS: Fantastic.

JASON LENGSTORF: This one this works, though. Okay. We're in business.

DARIUS CEPULIS: Cool. So I think we want to do two things here. We wanted to only show it in the list if your user has a subscription and we wanted to be able to play the video if they have a subscription, right?

JASON LENGSTORF: Maybe. So, I think what I'd want to do is, I'd want to show it in preview. That's more going to be, like, a styling thing. Um... because, yeah, longterm, which is kind of out of the scope of what we're trying to do today, membersonly preview. If you click in, you'll be able to see� instead of the playback window, you would say, this episode is only available to members. It'll be publiclyreleased on date. So, we can keep it in the list and then let's just work on the episode page.

DARIUS CEPULIS: Cool. Where do you get the images for those, by the way? Are you getting those through Mux?

JASON LENGSTORF: That's a great question. I'm putting those images in my database and they're coming from Cloudinary. Video assets in Mux. I've used Cloudinary for all my stuff. I did look� I saw that you had� like, you had support for thumbnails and making animates GIFs and I saw you had a clipping API. I was like, oh, no, we're going to be able to make a mess with this. This is going to be great.
Okay. So...we have...a protected playback ID and a prerelease. And, yeah, like you said, what I'm probably going to end up doing is having a videos thing. It will be an array and then the YouTube version will have the public version and the signed version so I can make choices based on time and settings. But for now, this is good enough and I'm going to leave a note in here...set up for handling public and private IDs.

DARIUS CEPULIS: And, to me, this is� this is� I was a Mux user before I joined Mux so if I sound like a fanatic user, it's because I was. It's kind of all your problem, which is� I mean, like, maybe� in our case, it's flexibility. We can make decisions about how we want to serve videos. We can make decisions on how to display them. You, as a developer, can focus on what you want to develop.

JASON LENGSTORF: This is one of those "it depends" scenarios. What developers are looking for is, take all this control away from me. I don't want to think about it. I think that's why a lot of people like Clerk. Sign up for this account and drop this in and we handle it. When you have a use case, in video, if I just want a video, I go to Mux. I've designed a flow and I need it to work that way. So if you start taking control away from me, it makes the tool harder to use. So when I'm coming to you with a very specific use case and you say, here are all the components, you do all you want with these. The only thing we're going to provide is, oh, you need the MP4, the HLS, the streaming stuff. Here you go. We're not going to tell you, you have to use this language or that language or do it exactly like this. It's kind of like, here's a box of tools. You have a vision, make it happen.

DARIUS CEPULIS: Yeah, yeah. We do the video, you do the rest. And of course, we'll help you along the way. That's the hope, at least.

JASON LENGSTORF: It points more to treating the docs as a product because if you're not building, like, an SDK, like, a full UI SDK, then the docs are there. I need to have really clear guidance on what all the different components are and how I can use them together. That is something Mux has excelled at.

DARIUS CEPULIS: Speaking of SDK, we do have some SDKs. We've got Mux player and stuff. Here, we're going to use the API SDK. For the next part, we have a locked video, we need to give keys to the users and we're going to make those keys using the Mux Node SDK. So, if I can, I'd love for you to npminstall that.

JASON LENGSTORF: Mux� is it @Mux? Muxnode.

DARIUS CEPULIS: Any API call you can make to Mux, you can make using Mux Node, as well. I can't remember the last time I made an API call in terminal. I use it in Mux Node. I'm a web developer and I want web developers stuff.

JASON LENGSTORF: I'm kind of the same. I can write a Curl command. I'm way faster at throwing a junk page I can fetch on.

DARIUS CEPULIS: So the way that we handle unlocking videos is JWTs, which I found out people pronounce "Jot."

JASON LENGSTORF: If you go phonetically, it should be, "jweeet."

DARIUS CEPULIS: You can use any signing library you want. But I think that we should use Mux Node instead, because it makes it a little bit easier for JWT signing. We're going to add some information. We're going to�

JASON LENGSTORF: Am I� sorry, am I importing something or are we just talking through it right now?

DARIUS CEPULIS: Let's get started. Import the default. Import Mux. We're going to use this to create that JWT. Let's create an instance of the client, mux=newmux. Because Astro uses Vite under the hood and Vite doesn't use "process.end," we have to pass the object. So, the client needs to know� the client needs to know how to make authenticated requests to Mux. So the first things you need to pass are the token ID and the token secret, and these are just your Mux credentials.

JASON LENGSTORF: Import.meta.env and "Mux token ID." And Token Secret.

DARIUS CEPULIS: We moved over to autogenerated SDKs. The TypeScript is so good. I barely open the API reference anymore because it's just, like, all there.

JASON LENGSTORF: Is there anything else that I need in here right now?

DARIUS CEPULIS: There is. We talked about� we talked about how the video's locked and we talked about how you're going to create keys for your users. You actually need a key in order to create keys for the users. So, the key to create the key and that's your JWT signing key and your JWT private key.

JASON LENGSTORF: I recreated a private key. I will need to add them to my environment, which I'll do momentarily. Much to the [Indiscernible] chagrin, it's going to be done offscreen. This was secret.

DARIUS CEPULIS: JWT private key.

JASON LENGSTORF: Oh, JWT private key. Okay. Private. "Privage."

DARIUS CEPULIS: I think we can do this without leaking anything. You can go into the Mux dashboard and show how the keys are created.

JASON LENGSTORF: How fast are these to roll, if I were to leak?

DARIUS CEPULIS: You can hit a "delete" key in the dashboard. Dashboard.mux.com. You can go into Signing Keys.

JASON LENGSTORF: We're in...development, I think? Wait, have I been working in production? Did I not create any keys?

DARIUS CEPULIS: You promised me you created a key. [Laughter]. The key you create has to match the environment you uploaded the video into.

JASON LENGSTORF: Right now, we're working in the production environment, so why don't I create a key for the production environment and we'll upload into the testing environment. Okay. So, let's generate a new key.

DARIUS CEPULIS: This is going to happen onscreen, actually.

JASON LENGSTORF: Well, now you tell me.

DARIUS CEPULIS: I figured we're going to create one and immediately delete it because you already created one. [Laughter]. This one, you should create offscreen.

JASON LENGSTORF: Let me create a few one.

DARIUS CEPULIS: Do exactly what Jason did, except delete it at the end. The very first livestream I did at Mux, I did with my wonderful coworker, Dave. 15 minutes, I put up my entire production environment for Mux.com, with keys. I go pail. I go, oh, no. I pretend it doesn't happen. In the background, I'm deleting keys and everything. We end up taking the video down off YouTube and rotating our keys. I've been very sensitive about keys ever since.

JASON LENGSTORF: That's always a hard day.
I've got my signing key, but while I'm in here, I'm going to my access tokens, as well. The two we were using� to doublecheck I'm correct here, the Token ID and the Token Secret.

DARIUS CEPULIS: Uhhuh. Those are your standard API tokens. They are specific to whatever environment you're using.

JASON LENGSTORF: For permissions, I only need Mux video, right?

DARIUS CEPULIS: Yep. We're not doing anything with data or changing permissions.

JASON LENGSTORF: Token ID, which I'm going to put into the�.env. And then, last one I need is the Secret key, which I will put in here, Token Secret.

DARIUS CEPULIS: That is the coolest keyboard I've ever seen.

JASON LENGSTORF: The Moonlander. I got it because my wrists were bothering me. But I've still not, like, become a fast typer on it. [Laughter]. I think I was, like� it was brutal.
Okay. So, I now have...all of my stuff loading. Let me just doublecheck this, one more time, before I bring everything up... .env. Token secret. Okay. So, let me close the�.env and get us back onscreen. All right. We're back in business, everybody.

DARIUS CEPULIS: Nailed it.

JASON LENGSTORF: I have my keys saved. They are here. Let me close the terminal. Anything else I need to put in here?

DARIUS CEPULIS: You got it. You're allowed to talk to APIs and to JWTs because of the signing key and the private key. If you're talking to the API, you don't need the signing key and the private key.
Cool. So, now, what we want to do is say, if the user's logged in, then we're going to generate a key.

JASON LENGSTORF: Okay. So, then, I will be able to do� it's "user=awaitastro."

DARIUS CEPULIS: The triple hyphens, that happens on the server, right?

JASON LENGSTORF: Yes.

DARIUS CEPULIS: The last thing we want to do is leak these to the client.

JASON LENGSTORF: Right. Let's do a pre...stringify. And we're going to drop the user in there. What we should see, out here, is that the user gets dumped. Right. Okay. Good. So, yeah, I've got my user ID, all those things. And what I have in here is I have my public metadata� and this is a Clerk thing. I can use API calls, like, when the Stripe data changes, I write to the Clerk API to update public metadata and set this� this Stripe object to� to include, like, it's an active status. This is my Stripe customer number, this is my level and I use all of that for what I'm after so what I can do then is, in here, I can say, um..."const" is "subscriber." And we'll say, "user.publicmetadatastripe�

DARIUS CEPULIS: Oh, and you have types on that?

JASON LENGSTORF: You have types up to the metadata. I can go extended, if I want, but I have not done that yet. And then we're going to go with a status of "active." And...I know it is, but I can make you stop yelling at me? I sure can. Hush, you. Okay.
So now we have the "is subscriber." Let's just doublecheck that before..."is subscriber true?" Okay, great. So now, we have that and then we generate signing key.

DARIUS CEPULIS: Exactly. We're going to do this with the Mux Client. So, um...

JASON LENGSTORF: So, can you talk me through� so, I'm going to generate a key and I assume that the� I'm going to make a call to Mux, through this client that we generated, that's going to return my key and then I take that key and I� do I pass it into the Mux player?

DARIUS CEPULIS: Yeah, you'll be passing it into the Mux player. This is under the hood implementation. The client's not creating a call to Mux. The nice thing about JWTs is that they don't� you don't need to call home every time you create one. Because you have a signing key, you can create an authenticated key. So� but that's just under the hood. You're going to use the client to create a key, which is all going to happen local. You're going to send that key to the customer and they'll use it to play the video.

JASON LENGSTORF: Okay. [Laughter].

DARIUS CEPULIS: Yeah. Let's do this. So, it's going to be mux.jwt.sign/playbackid. The signed playback ID.

JASON LENGSTORF: So that's going to have to come first.

DARIUS CEPULIS: And the second argument is the body of the JWT. So, the first thing you need to tell it is, what this key is for. Type. Type is "video." Second is expiration. This is your line of security. The reason this is safe is because this JWT expires. So, the realities of the internet means that your users can still go in and still go to the video element and grab that URL and share that URL. Because this URL has an expiration, that will only work� the URL will only work for a certain period of time. If you have a 10minute video, maybe you should make an expiration that's 11 minutes. How long the expiration is, is going to be up to you and your business logic and needs.

JASON LENGSTORF: And just so I'm clear, if we have a video� like, let's say we've got a video that's one minute long and I've set the expiration for 30 seconds. When I hit "play," 30 seconds in, the video will stop playing? Every streaming chunk that comes through is being authenticated. Okay.

DARIUS CEPULIS: Chunks by chunks and if the JWT is expired, Mux is going to be like, sorry.

JASON LENGSTORF: I'd want a solid hour for a 10minute video because they might want to pause and go back. And, like, to be clear, I'm not worried about people showing these videos to other people. It's more of, like, I want to have a tangible benefit for people who decide to support the channel monetarily. And, so I don't want to make it hard for people to watch these videos, I just want it to have some kind of real benefit. A thing you can point to and say, here's what you get for your money. I get to make more videos.

DARIUS CEPULIS: You're hitting on one of the great tensions of stream security. The more secure you make it, the more hoops you make your users jump through. What if somebody stands up to go to lunch and comes back? You can solve some of this stuff. The way we see it often done, for a oneminute video, you issue a twominute key. If the user is on the page, they get a new key.

JASON LENGSTORF: We're going to be in big trouble if I have to do this next part by myself. Chat, are you still with me?

DARIUS CEPULIS: Oh, no, I can hear you just fine. Whoa, did you lose me?

JASON LENGSTORF: We're going to pretend that didn't happen. [Laughter].

DARIUS CEPULIS: What happened there, where did you lose me?

JASON LENGSTORF: You were saying this was a tradeoff is the more you add, the harder it is to lose the videos.

DARIUS CEPULIS: Oh, that was a really good spiel. Users have to jump through hoops, whether or not you mean to. It's a tradeoff inadvertently. If you were to set your expiration at two minutes, then you can make a call on your frontend to ask for a new JWT. You've still got this level of security and as long as your user's logged in, they can keep getting new keys. Or you can set the expiration to be a year, it kind of depends on what security you want.

JASON LENGSTORF: Right. And if� if� so, as long as I set it long enough that somebody doesn't get interrupted while they're watching, you can do it for a day. You can do it for 12 hours and that seems like a perfectly reasonable amount. They would reload the page, and they would generate each key which would give them another 12 hours.
How is this set? It says "stringer undefined."

DARIUS CEPULIS: PseudoEnglish. So one hour would be 1h.

JASON LENGSTORF: We'll do 1d, we'll make it a oneday expiration.

DARIUS CEPULIS: That is the video playback token.

JASON LENGSTORF: This is the video playback token?

DARIUS CEPULIS: Yeah, the video playback token. I've given you the short story. There is actually a long story. If you say "playbacktoken," you are most of the way there. Because of the way that the Mux API is structured, because of the way that you, like, might not� that's interesting. Let's walk through the other steps, first.

JASON LENGSTORF: Okay.

DARIUS CEPULIS: You're not always necessarily unlocking your videos. Sometimes you just want to unlock your thumbnail, your storyboard. Instead of passing one token, you pass multiple tokens to the player. We've created your video playback token. We have to create a thumbnail token and a storyboard token to make sure the player has access to all the parts it needs.
Earlier, I asked you how do you create your thumbnails, if you use Mux, you would use a thumbnail token. They get the thumbnail and not the storyboards. There's exchange for code overhead here.

JASON LENGSTORF: Okay. Okay. Okay.

DARIUS CEPULIS: If you copypaste that two more times. We're going to do one for thumbnail and one for storyboard.

JASON LENGSTORF: Okay.

DARIUS CEPULIS: Nice.

JASON LENGSTORF: How do I pass these in?

DARIUS CEPULIS: You'll create two more, storyboard token and thumbnail token.
All right. Now let's see if Mux player's still complaining. If it is, I messed up and did something wrong...

JASON LENGSTORF: Oops. What was that? Noooooo. Cause the download to fail...I was like, where is everything missing here? You. Bad request.

DARIUS CEPULIS: This is the signing playback ID.

JASON LENGSTORF: Should be.

DARIUS CEPULIS: Object promise.

JASON LENGSTORF: Oh, we have to "await" this.

DARIUS CEPULIS: My bad. You have to "await" it. I misled you.

JASON LENGSTORF: And, look at it go, everyone.

DARIUS CEPULIS: This whole song and dance is only going to work on signed playbook IDs. You should add a condition, if this is playback, don't pass any tokens.

JASON LENGSTORF: How do I do that?

DARIUS CEPULIS: You've got a thing in your database schema, it's "prerelease," right? You're passing everything through URL params, aren't you?

JASON LENGSTORF: We are passing the playback ID. Originally, I was passing in the whole episode and I decided not to do that, so I can always do it again. We can say, "prerelease." And it will be "fields.prerelease." And I think what I need to do, then, is update my...let's get this� we'll get this part, first, and then I'll go fix the rest of it. Rerelease. And that one's going to live in here. It's boolean. And we're going to say, uh...this, I can probably make this better. But we're going to roll with this for now.

DARIUS CEPULIS: I've actually recently been very antifancy code. Like, it just� get the basic conditional out. If it's legible, then it's probably good. And the fancier it gets, the less legible it gets.

JASON LENGSTORF: We're definitely hitting this with a hammer, but it's fine. So, then� oh, we didn't do the check to see if they are a subscriber. So, this would be, like, "if is subscriber." Right. And then we're going to have to do this one...

DARIUS CEPULIS: Yeah. Or you can, like, create an object and spread that object on to the player, down in Astro. There's a couple different ways to do this.

JASON LENGSTORF: That's a good idea. Yeah. That could be a good way to refactor this and clean this up. But we'll live with it for now. There's valid code. All right. So, then this should be good, now, um...that's TypeScript and now we have� now we have a file that's not fighting us. However, before I forget, I need to do one, quick thing because I don't think we're currently getting the episode. Episode by slug. We're getting the fields. Am I...I think fields are just going to work then? I'm not sure if I'm getting that prerelease so I just got to doublecheck. Fields. Fields just comes through. This is going to be fine.
Theoreticallyspeaking, this will work. Let's go to the other one...

DARIUS CEPULIS: Nice. No errors.

JASON LENGSTORF: And it just works.

DARIUS CEPULIS: And the last thing you'll probably want to build is if a user's not a subscriber, probably show them some sort of UI saying, hey, like, sorry, you need to join� join Jason to�

JASON LENGSTORF: Yeah, I think that is what we were originally talking about doing and then I didn't do it.

DARIUS CEPULIS: Otherwise, they're going to get a player with an error on it, which is one way of communicating.

JASON LENGSTORF: Right. Right. Oh, this sucks.

DARIUS CEPULIS: Yeah.

JASON LENGSTORF: Okay. Maybe� see, we don't have enough time. I want to get to the DRM. I'm going to leave myself a todo for that...show UI for unsubscribed, um...people on prerelease. And that way, I'll come back to that because really, that's refactoring this to have another conditional that if they're subscriber, show them the Mux player if not, hey, you need to be subscribed for this.
There was another whole piece and we're coming up on time, so I want to make sure we have it.

DARIUS CEPULIS: Yeah, yeah. Let's do that real quick. We have a strategy of the keys expire after a certain period of time, right. But some people want more. Some people want more security and we've got two ways. One, I'm going to wave my hands at really quick, before we talk about DRM. That is refer restrictions and user agent restrictions. If you only want your video to work on learnwithjason.com, or for Chromecast and AirPlay or Android phones, you can add those restrictions, as well, through Mux. We've got information about how to do that in the docs. Actually� yeah. We'll scroll by those docs in a second.
Yeah, at the very bottom, there is Access and Permissions. Secure Video Playback. Create Optional Playback Restrictions for Your Mux Environment. Something you might consider is creating a Learn With Jason restriction and attach that to your JWT. You can use your user IDs to the JWT so if the video gets leaked, you can decode it and find out who leaked it.

JASON LENGSTORF: I think that would make sense. If you were running your own� like something sensitive. If you set up your own version of Only Fans, you want to trace that back to its origin. For me, I don't care. Again, all I want is to provide people a benefit for supporting the channel. I can see huge reasons why that would be important. But I do like the idea of restricting it to the learnwithjason.dev domain. Yeah. I think that's great.

DARIUS CEPULIS: And of course, not all devices send refer headers. If you built an iOS. It's nice to know there are tools out there.
The last tool I think we should talk about is DRM. It looks like you uploaded a video to your DRM environment.

JASON LENGSTORF: I did. I'm going to go into my seed. This is the Ben one. So I'm going to duplicate this, if I can remember�

DARIUS CEPULIS: You uploaded it� I was talking, I wasn't paying enough attention. Did you change it?

JASON LENGSTORF: Public and signed.

DARIUS CEPULIS: There's a third kind of playback policy. [Laughter].

JASON LENGSTORF: Oh, no! Can I update it here?

DARIUS CEPULIS: We can make an API call to upload this video. If we don't want to set up the Curl command, we can create a new asset.

JASON LENGSTORF: It uploaded fast enough. We've got public. We've got signed. The third?

DARIUS CEPULIS: This is the tricky part. Here, you're going to replace lines 35 with Advanced Playback Policy, because DRM is an advanced playback policy. Advanced Playback Policy's an object, rather than an array. And, in that object, we've got� I'm doing this off the top of my head because I straightup cannot find my notes. [Laughter]. Whoa, what if we just use the docs? Actually, I think we should open the docs. Protect videos with DRM. Create an asset. There's the Advanced Playback Policy.

JASON LENGSTORF: Why don't I do this?

DARIUS CEPULIS: Oh, it is an array.

JASON LENGSTORF: It is an array. I'm going to bring that through, to here. Okay. It's good that we looked at this then.

DARIUS CEPULIS: Nice. And the DRM configuration ID is something I sent out before and that's not a huge deal if you leak that.

JASON LENGSTORF: Okay. And, I'll run that. Uploading a file. Here we go. And, while that's happening, um, maybe let's talk about what� like, what is happening with DRM? Because I feel like it's one of those things that got a really bad rap because most of it� okay, I'm about to date myself. Those of us who grew up in the Napster era may remember the huge issues that were happening where, like, everybody was stealing music. We are torrenting things and then the drummer from Metallica decided to fully light his reputation on file by being the DRM king. Everybody who heard it� like, I was introduced to DRM as a bad thing, introduced by businesses to stop people from having fun. I don't think that is what it is. We can use it like that. What is it?

DARIUS CEPULIS: DRM is a way of making sure that the device you are using is allowed to play a certain type of video. And not allowed, as in this person is allowed. But rather, allowed, as in this computer is a safe environment to play this video and to understand what a safe environment is, maybe we should talk about what an unsafe environment. Folks who want DRM, Hollywood Studios, they care a lot that it is being played in a browser and not a terminal command that's downloading the video. The browser's a safe environment; the terminal command is not a safe environment. To guarantee to these content holders that the video's not being downloaded in terminal or rebroadcasted on Twitch. They have built hardwarelevel security that's called, as an umbrella term, DRM. It is our way of promising the content owner, this is fine. You're playing this in the browser. This is not get rebroadcasted to another Twitch final. The video is playing where you expected it to be played.
So you might have noticed DRM without even noticing. Sometimes I want to take a screenshot in Netflix, and it's all block. That's DRM. That's a standard example.

JASON LENGSTORF: I'm just� I'm doublechecking because there was an issue...

DARIUS CEPULIS: Uhhuh.

JASON LENGSTORF: I typoed something and I'm just making sure� I don't know if it did the thing. Is there a thing where you can see, the policy is DRM?

DARIUS CEPULIS: Yes. Why don't you� okay, the first place I know� off the top of my head� I don't know if it's in the UI. DRM is in beta currently. The first place I would check is in your Network Activity. You can see it's making calls to Mux's API. Check out the requests. You can tell I'm a developer at Mux. It looks like the asset ID. Nice, let's take a look at the payload. This is� yeah. Data. Upload ID. And...playback Policy's is going to be somewhere in there.

JASON LENGSTORF: It is not, because we screwed it up. So, okay, that is where we went wrong. I uploaded the default one. So let's see if we can find it in here.

DARIUS CEPULIS: This is not normal Mux activity. This is hanging out with a Mux developer.

JASON LENGSTORF: Policy DRM. What I did, I screwed that up and typoed, Advanced Playback Policy, when it should have been "policies."

DARIUS CEPULIS: I think I told you "policy."

JASON LENGSTORF: Well, I wasn't going to throw you under the bus, but, yeah, it was your fault. [Laughter].

DARIUS CEPULIS: Playback on thumbnails.

JASON LENGSTORF: Thumbnails.

DARIUS CEPULIS: DRM. It is in the URI.

JASON LENGSTORF: Zero playback IDs because we screwed up. Perfect. Perfect. Let's just use this one, because it's here and it works. This is the default one and I'm realizing, now, that I also need to create, I think access tokens and stuff. So, I have those ready, but I need to create the� the access tokens. And these are the production ones. Let me take that offscreen real quick.

DARIUS CEPULIS: DRM is in beta. We encourage users to create a separate testing environment so if anything goes wrong, it doesn't happen to your production environment. Before the stream, we had Jason create an environment. This is on me.

JASON LENGSTORF: I'm taking all of my production environment ones and I'm swapping out for the nonproduction ones.

DARIUS CEPULIS: We'll be able to view the DRM video and the DRM video only.

JASON LENGSTORF: I'm copying over my signing key and my private key and the private key is a monster.
[Laughter].

DARIUS CEPULIS: It sure is. I think it's [Indiscernible] 64encoded, too.

JASON LENGSTORF: It is. Has the smell of that. Then that should be set and then what I need to do, then, is let's go get the asset� let me put this back up on screen. I need to go to get the, um, assets.

DARIUS CEPULIS: Stick it back in your database.

JASON LENGSTORF: Here is the actual thing, so I'm going to get my DRM playback ID and then let's go to this Ben one and I'm just going to swap this out.

DARIUS CEPULIS: Yep.

JASON LENGSTORF: Okay. So then, coming back out here, we are going to go to the BenQ ScreenBar Halo and this one fails.

DARIUS CEPULIS: Error.

JASON LENGSTORF: Because?

DARIUS CEPULIS: You remember those three, wonderful� there's one, last step. The three keys we passed to Mux player. There's a fourth player to pass for DRM. It is �DRM_license,� as the type. All you got to do is changed the type.

JASON LENGSTORF: Oh, oh, that's it?

DARIUS CEPULIS: Yeah. It's just a fourth key. We love our JWTs around here.

JASON LENGSTORF: Okay. So, we're going to get DRM license and then�

DARIUS CEPULIS: And then you pass that to Mux playerrrrrrrrrrrr, somehow. DRMtoken.

JASON LENGSTORF: DRMtoken. And call DRM license.

DARIUS CEPULIS: Sweet. If this worked, our viewers would not be able to see the video. If it didn't, there would be an error. I wonder what the error is? What does your console say?

JASON LENGSTORF: My console says nothing.

DARIUS CEPULIS: I feel like we are running up against a beta bug.

JASON LENGSTORF: I might have gotten environments wrong.

DARIUS CEPULIS: Yeah, we, we could be missing a token, as well.

JASON LENGSTORF: Let me just doublecheck, real quick, that I have the right now. So, take this offscreen real quick. Get into my env.

DARIUS CEPULIS: Most users will have one environment and not trying to hide keys from their viewers.

JASON LENGSTORF: Yeah. It's like, what not do it on Hard Mode? I want to doublecheck that this one matches. My signing key doesn't� you know what? It's not showing me what the key is, which leads me to believe� oh, I definitely have the wrong one. I don't know what I generated, but it's not this. Okay. So, we're just going to replace that entirely. So that's my JWT signing key. I've got a token ID in Secret that I've generated. And then I'm going to come out here and it still is erroring.

DARIUS CEPULIS: Hmmmm.

JASON LENGSTORF: Am I doing something wrong? Okay, let's bring� oh, my god, I almost showed all my keys just now. [Laughter].

DARIUS CEPULIS: Noooo. I'm so sorry. I've put you in a precarious position.

JASON LENGSTORF: Okay. Okay. So, we're fine. We're fine.

DARIUS CEPULIS: DRMtoken. What version are you on? We released DRM into beta two weeks ago. Yeah, let's give this an update. We got it. I bet this is it. Mux player 2.8, I believe, is out.

JASON LENGSTORF: Npminstall.

DARIUS CEPULIS: Our incredible engineers� actually implementing DRM is, in my opinion, the most painful thing upon the face of this earth. Did it work? Do you see the video, Jason? Because our livestream viewers do not, which I believe is the point.

JASON LENGSTORF: I hear it, but I don't see it.

DARIUS CEPULIS: Nooooo.

JASON LENGSTORF: I don't know what's in it.

DARIUS CEPULIS: Or, maybe because you're screenrecording?

JASON LENGSTORF: No way. Let me stop� and it came back! Oh!
[Laughter]. No way! Okay. No, that's so dope. Okay, so it did, in fact, work. That's a huge pain in the ass and I don't know that I like it. [Laughter].

DARIUS CEPULIS: But some people want that. I'm glad we talked about it.

JASON LENGSTORF: This is actually wonderful. Shame there's no DRM for my keys. [Laughter]. True.
[Laughter]. But, no, this did exactly what I expected. As soon as I stopped sharing my screen, the video showed up. So, it is doing� it is doing what it says on the TIN. And if I, for example, was a� I don't know� like, corporate company that wanted to have, um, internal training or, like, internal updates, where I'm sharing data with the rest of the team or anything that would be sensitive, right. I want my team to be able to watch it, and they're signed in. If they're trying to screenrecord or broadcast that to somebody on another channel. I don't know who would do that, maybe government. It makes sense it would be limited, right. I get it.

DARIUS CEPULIS: There's one more case, too, that I wanted to mention. It's a real bummer� I don't know how worried you are. Their videos show up unnew to me. If you can throw up barriers, that might be worth the trouble.

JASON LENGSTORF: Yeah. I mean, if you're a course creator� actually, that's a really good point. If I create a course, I put a lot of work into that course and I want you to have access to it, but I don't necessarily want� it should be hard to share. It should be hard to get for free because it's not a free thing and so giving someone the ability to release a course that can't be screenshare d, that requires a valid license in order to view, that's a perfectly reasonable thing to do, I think. I dig that.

DARIUS CEPULIS: Stream security is a tradeoff between complexity, maintenance and user friction and security. And, like, we've got a couple tools, at Mux, you can use, you can add expiration, refer, DRM. It's up to you build it how you want and use our tools to build something cool.

JASON LENGSTORF: I mean, this is supercool stuff. That brings us to the end of our time. Originally, I was thinking, we'll look at DRM, but I won't use it. I'm working on something with Astro and that's good. On the Learn With Jason site, I'll be using signed asset IDs. I like being able to switch from private to public without any hassle and if people want to watch it together or a screenshare, that's great. I love it when people do stuff together. If I can help bring people together for a minute, that's the goal.
Where should people go if they would like to learn more? I'm going to start by throwing everybody to your Twitter.

DARIUS CEPULIS: Follow me for my bad occasional web developer takes. I'm happy to answer a DM. If you're not bothering me on Twitter, check out our marketing website. I spend my day on this. It has good content. And really, we've got a really cool blog. We're talking about all the stuff we're doing, around pricing. We want video to be accessible. We're adding levers to our pricing and finally, if you're ready to get started, hop into our docs. If you don't like them, there's a feedback form that goes straight to our inbox. Dive in, start building. You can just plop a player in and go from there.

JASON LENGSTORF: It is� it is very nice to work with. And, you know, I think somebody mentioned earlier that for livestreaming, it might get a little expensive. Depending on what you're doing, run through the pricing. One of the things I thought was cool, on the pricing, is that you had an estimator that I thought was nice. Where was it?

DARIUS CEPULIS: You're remembering our old pricing page. We've buried that estimator in docs. We're working on redesigning our calculator. You'll find pricing doc at the bottom of docs.

JASON LENGSTORF: Understand your estimated costs. This is a whole spreadsheet.

DARIUS CEPULIS: I promise, I'm working on a new calculator. It's going to be superslick. [Laughter].

JASON LENGSTORF: I ran the math for what it would cost to run Learn With Jason and I'm looking at the hosted versions, not the live versions. For me, it was� it was not� it was not getting into the price range where I felt like it wasn't absolutely worth what I was going to spend on it. For $10, is what I'm subscribed at right now, and it's going to take some effort before I get to breaking through the credits that are included with that. And after that point, I'll run some math and figure out where the right tradeoffs are. I have the YouTube ID and can use the YouTube ID. It's really up to you, right. So, anyways. With that being said, we're out of time, so Darius, any final thoughts for everyone, before we send you off into the sunset?

DARIUS CEPULIS: Video's cool. The web is pretty neat and I'm glad that we got to do this.

JASON LENGSTORF: I'm very glad we got to do this, as well. Chat, thank you, all, for hanging out. Thank you for not stealing my keys when I showed them to you. Netlify making this episode more accessible. We've had Vanessa, from White Coat Captioning, here doing the live captions. Thank you, Vanessa.
And thank you, Mux, for hearing all my problems and turning that into a sponsorship opportunity.

Make sure you go and check out the schedule because we've got a lot of good stuff coming up. In a week, I've got an episode� I'm trying to get it scheduled right now. Then we've got the next week, Matt, talk about TypeScript. Then Sarah and Ryan, we're going to talk about some of the new stuff in Solid. It's going to be a killer August. Make sure you are marking your calendar. You can find everything on the site, on the schedule.
We will see you all next time. Thank you so much. Take care, y'all.

Learn With Jason is made possible by our sponsors: