Make Video With Code
Making slick, animated video using React might sound far-fetched, but Remotion makes it possible! Jonathan Burger will teach us how.
Links & Resources
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: Hello, everyone. And welcome to another episode of Learn with Jason. Today on the show we have, joining us from Switzerland, Jonny Burger. I did get that right? How close was I?
Jonny: Yes, that's pretty good. Yeah, thanks for having me.
Jason: Thank you so much for joining us. This is going to be a whole lot of fun. So, for folks who are not familiar with your work, do you want to give us a little bit of a background on yourself?
Jonny: Okay. So, until recently, I like pretty much worked on a few apps that I guess are not so much known. So, I've been trying to bring out my own apps. I did a sticker app and like an app which is pretty popular here in Zurich for students, but not many people know about it. Also, like one thing that I was always position gnat about was making these videos and motion graphics, also so I could make videos to advertise my apps. So like about a month ago, I launched Remotion, which I would say is my biggest hit yet, which allows you to make videos in React.
Jason: Yeah, so this is a really cool concept. I'm excited to learn about it because honestly, I don't even know how it works, right. Like, my brain isn't wrapped around how you would take React code and turn it into a video. So, I'm really, really interested. But before we talk about the how, I'm kind of curious about the why. So, when you started looking at this project, what got you thinking that React was a good platform for making video?
Jonny: Yes, that's a great question. So, I used to make all my animations in Aftereffects, the Adobe program. So, I mean, it works well. You can like do everything with a cursor and edit everything, but let's say you have like elements that you want to reuse. There's a concept called composition, and you can copy/paste the layers, which works, but then if you want to change something in a composition, it's not like a React component where you change it once and it applies to all the instances. It makes a literal copy, and then if you want to -- if you make 40 copies and you want to change one thing, it's completely busted, and you have to adjust all the compositions yourself. I was just so used to React because I'm also a developer, and I said, you know, it should work like React. In the end, I ended up creating a program to make videos in React, yeah.
Jason: Nice, nice. The chat is asking if you don't mind either moving your mic a little closer to your face or speaking just a little bit more loudly. I think the problem is I have my mic all compressed to hell, so I whisper and it's real loud. (Laughter)
Jonny: Okay. Yeah.
Jason: Yeah, that's way better.
Jonny: Wow. Oh, and I also want to open the chat, actually.
Jason: Oh, yeah, yeah. That's a great call. One of my favorite things about this show is the chat. It is an absolutely wonderful group of people. They're delightful, and I'm so happy to see so many familiar faces. I see Ximena. Linda. What's up? I'm particularly excited today because video is something that I love. You know, I've done a lot of little one-off things with video. I've made silly stuff like I made this goofy little overlay for the chat where you can kind of see my goofy face walk out over the top of it.
Jonny: Oh, wow.
Jason: This is like a little After Effects thing I made. Then the transition between scenes on here, that's another thing I pieced together in After Effects without actually knowing how any of it works. I'm basically just flailing around between tutorials. So, having something that might make me more competent at making videos by virtue of using the skills I have is really appealing to me. It's something that I see a lot of potential in and a lot of fun that we can really get into. So, I have one kind of practical question, which is, how does this work under the hood? So, I know how React components work, and I know how to make videos, but I'm not sure how you're doing the transfer between the two.
Jonny: Okay. First of all, this sounds great. Sounds like you're going to have a lot of fun. It's great that you already know a bit how to do such things in After Effects. That's going to help a lot. So, how it works, the basic idea is that you get a frame from Remotion. It's your responsibility to render anything. Then, of course, if you have a lot of still frames, then it animates to a video. Then during the render process, we use Puppeteer to make basically a whole lot of screen shots. We have optimized it so it does like ten screen shots in parallel, for example, to make it decently fast. Then we stitch it together using a tool called FFM Peg. That's like one thing you'll have to install first.
Jason: I think I have it. We'll find out, I guess. (Laughter)
Jonny: Yes, and basically just make a lot of still images by screen shotting, and then add them together, and you'll see it works really well.
Jason: Yeah, I'm really excited. Okay. So, let's -- I just want to see this in action. Let's switch over, and let's take a look here. What I want to do is I want to first tell everyone to go and follow you on Twitter. You've got a lot of really interesting projects that you're working on. I think this Remotion is, you know, as you said, it might be your biggest hit, but it's definitely not the only thing you've built. So, make sure you check that out. Also, this is the library. Remotion.dev is what we're working with today. I don't have an uptime command. But we're just getting started. We're about ten minutes in. So, you haven't missed anything yet. You'll probably want to go back and see some of the motivation and all that stuff, but otherwise we're in good shape. And before we get too deep, I want to do a quick shoutout. We have Rachel from White Coat Captioning with us today. Oh, god. Stop. (Echoing) Mute the tab. Okay. Woo, always forget when I do that. So, this is the site. Look at this. We have this live captioning. That's thanks to Rachel. White Coat Captioning is with us every show. You can always go to the site home page, learnwithjason.dev.
Jonny: Oh, is she typing it in?
Jason: She is, yeah. As we speak. It's amazing. Like, one of these days, I feel like I just want to figure out how transcription works because -- actually, I don't know how Rachel does it. I've seen some transcription get done with like a stenographer's keyboard. So, you play chords to make sounds. It's amazing. It's really, really cool stuff. It's such a cool Google -- like it's a Google rabbit hole to fall down. Definitely go check that out. But that --
Jonny: Wow, fastest typer ever. (Laughter)
Jason: But yeah, so this is all made possible through the generous support of our sponsors. So, we have Netlify, Fauna, Auth0, and Hasura all kicking in to make this show more accessible to all of us, which means a lot to me. I hope it means a lot to you. I hope that it is helpful. So remember, you can go find that on learnwithjason.dev. With that being said, Jonny, if I want to do this, if I want to like get started with my first video, where should I -- what should be the first thing that I do?
Jonny: Okay. So, it's quite cool. You can type into the command line yarn create video.
Jason: No way.
Jonny: Yeah, we recently sped it up, I would say. Previously, you had to like download a whole copy of Puppeteer, like 200 megabytes. Now it will use the Chrome instance you have on your computer. It likes like you're using Firefox.
Jason: Oh, that's cool.
Jonny: Well, yeah, let's see what happens. You can test it out if it works. Even if you are a Firefox user.
Jason: I have both Firefox and Chrome, so I think it should be okay. Let me get in here, and let's fire this thing up and take a look at what we've got. So here is -- let's see, that's in the wrong window. Let's put it over here. So, let's take a look. In here we've got our package json. We can see a Remotion suite of things. This is Typescript.
Jonny: Yes. I wanted to force like TypeScript on everybody, but recently I also added plain JavaScript.
Jason: Okay, cool. Yeah. So, that's very cool. We've got some start commands. I assume this is just ready to roll. So if I run yarn start, I can take a look at the default.
Jonny: Yes.
Jason: All right. Let's see what happens. What? Don't act like you don't know what yarn is. I literally just ran yarn. Come on.
Jonny: Oh, no. Npm start maybe.
Jason: What? Okay. All right, computer.
Jonny: Must be something with -- at least nobody has complained about that. (Laughter)
Jason: Yeah, geez, who knows. What are you doing, computer? Why? Why are you like this?
Jason: That is exactly how I feel about that. Okay. So, I'm already -- I didn't think this is what I was going to be looking at. I thought I was going to be looking at the final video. So, the fact that this is like a scrubber where I can bounce back and forth and kind of like see anything. This is really, really cool. Okay.
Jonny: Yeah, so there's like two different modes, like with normal React developing. You have the development mode. And if you want to make the video, you can run npm run build or yarn run build, and then it will make the video.
Jason: Okay. So, let's make a video. We're going to see if I have FFM Peg installed. I think I do. It's not yelling at us, at least.
Jonny: Okay. So, yeah, now it's doing a lot of screen shots.
Jason: Yep. 4X concurrency. That's cool. Oh, it didn't like -- library not loaded.
Jonny: Okay, I see. So, now you don't have --
Jason: Dyld?
Jonny: An FFM Peg problem.
Jason: Okay. Is FFMpeg something I can brew install?
Jonny: Yeah, you should be able to do brew install ffmpeg. If you just type in ffmpeg, does it -- it would be interesting to see if that works.
Jason: Wonderful question. Yeah, well, I've started this now.
Jonny: Okay, yeah.
Jason: (Laughter)
Jonny: Hopefully going to resolve it.
Jason: Yeah, we'll find out. And I guess, you know, worst case -- wait, already installed. (Elevator music) Once you start a brew command, it just kind of -- it's like one of those dominos where thing one is you watched a reality show, and the last domino is like toppling western democracy. So, let's see here what version I have. Dyld library not loaded. Okay. So, now we get to do a little debugging to figure out why that is happening.
Jonny: So, it says something like apt. Are you running on Lenox or something?
Jason: Not that I'm aware of. Doesn't mean it's not happening. Brew upgrade node? Oh, boy.
Jonny: Oh, really?
Jason: Here we go. Okay. Do I need to use like node 14? Wait. I'm on nvm. Hold on. We're not doing that. Get out of here. Nvm use 14. Okay. Now if I run ffmpeg version, still doesn't like it. Okay. So upgrading node doesn't make any sense.
Jonny: No, I also don't think that will help you. I also don't know how you can even get a messed up version of ffmpeg. It's kind of an experience to fix it.
Jason: See, something is wrong. Like, I've done something incorrect here. How is this a shallow clone? Like, what have I done? Everybody get ready because I'm going to do bad stuff. Oh, that didn't work either.
Jonny: There's always a few back-up things we can do. You can commit it to a GitHub repository. You can store your video in Git, and I can render it for you. There's also a docker file, which if you build it, it's like a docker server. Then you can send an HTTP request to it. So, like you type in the URL in your browser and get served back the video. That will probably work. Also, there's like a cool thing where we have like included a GitHub workflow yaml file. So, if you commit this to GitHub, there will be a button activated on GitHub where you can render the video on GitHub.
Jason: Okay. So, I'm going to create a new public repo. And we're going to -- remote origin already exists? There's no way that remote origin already exists.
Jonny: Oh, wait. You're using Apple silicon? Is this the thing?
Jason: Am I? I'm using Catalina.
Jonny: No, no. I mean, do you have one of the new M1 Apple silicone --
Jason: I don't, no. This is an old one, actually. And I've run ffmpeg on this computer before, which leads me to believe I've done something silly. That brew error has me very concerned that I've broken my home brew install.
Jonny: And the yarn thing was also really strange, if you think about it.
Jason: Yeah, all of that is weird, right? Like, everything about this seems like something has gone horribly wrong, which is exactly what I want to find out when I'm going live in front of a whole bunch of people. So, let's try -- let's see. Maybe it'll just work in code. Nah. No, that would have been too easy. Can I run brew update from here, though? No. Updating shallow clones is an extremely -- like, who did this? Unshallow. I'm also confused as to how I got truncated commands here, because before it changed that to unshlow -- like it just took -- did that run? It did. It's running. So, in the meantime, what I'm going to try to do is I'm going to first see if this actually got created. So, let's open this repo. Yes. Then in another tab here, I'm going to git remote and look. So then what we're going to do is we're going to git add all. Good. Then we're going to git commit, set up the example. Then we'll git push -- oh, wait. Git remote add origin. That'll be git@github.com, learn with Jason, make video with code. Okay. So, now that this is going --
Jonny: You're also quite fast to type and no typos.
Jason: I have a lot of practice with that particular flow. Wait, why did my push not work? Could not read. Oh, my god. Everything has broken. Like, what is -- for real, how did you lose everything? Ahem.
Jason: What up, chat? There was a typo. Oh! I said gif at GitHub. We spoke too soon.
Jonny: Now I fear that like if you run yarn create video, it's just going to delete your whole computer.
Jason: That's going to be the end.
Jonny: Like, nobody has reported that. But if you figure this out, let me know.
Jason: There's zero chance this was your code. This was absolutely my rickety setup. One of the side effects of running the show is I install and uninstall all sorts of software twice a week. So, my computer tends to be a little -- I push it hard. Okay. So, let's try that one more time. All right.
Jonny: All these tools that use like ruby, fast lane, home brew, they always break for me as well. Really hard.
Jason: So now this works, and I should be able to run one, is that right?
Jonny: Yes, so now you can click on render video. Then you should be able to press run workflow. You can even customize it, customize the color and the text. So now you refresh the page, I think.
Jason: There it goes. This is unbelievably cool. Like, I got to get Brian Douglas back on here to talk more about this workflow. These git actions are so cool. Brew doctor. Oh, I could brew doctor. Let's see what happened over here. Still doing that, okay. Now I'm afraid to touch it because this is still running. Okay. So this is running. I'm going to click in here. Adult supervision here.
Jason: I 100% need adult supervision. Okay. Installing ffmpeg. Installing tendencies. That's all good. Okay. So, that's fine. What happens if I run brew doctor? Oh, boy. Look at this mess. Do you ever just look at your computer and just think to yourself, like, what have I done? Okay.
Jonny: Yeah, it's pretty bad. Like, once it's f'ed up, it's hard to fix it.
Jason: Just burn it down.
Jonny: Same happened to me actually on the computer that I am on right now. But if it helps you or if it makes you more happy, I also just had big computer problems. I tried to use a completely different computer, and the display went black. So now I'm staring down at a laptop. Also, sorry that I'm not staring at the web cam. It's because of that.
Jason: No, it's all good. All good. Henri, that's really funny. The computer looks back like, what have you done? You are correct. That was my fault. So, this ran, and it says it was complete. Everything did what I wanted. Where did it upload to?
Jonny: So, click back on the actions tab.
Jason: Actions tab.
Jonny: I don't know if there's a faster way to do it. Now click again on the title. It should be -- there should be -- now scroll down. And see, there's like artifacts.
Jason: Oh! That's cool. Okay. Then that opens over -- wow, my downloads folder looks like trash. How about this. I'm going to bring this over here. So, here's the video. Let me make that smaller so that it's -- oh, boy. Make this smaller. Okay. So, this is the video that we just exported. So, that's extremely cool. All right. So, let's do this. Let's just use this workflow on GitHub. It'll be a little slower, but it's probably actually faster than me trying to fix home brew on stream. So, instead --
Jonny: Yes, and also it's like -- what you see is what you get. What you see in the preview, it's going to be pretty much the same if you export it.
Jason: Cool, okay. So, with that being said, then we do know we've got over here -- if I yarn start again, did you remember how yarn works? No, you didn't. Oh, boy. I'm going to have to just burn this whole thing down and start over. But here we go. We've got our Remotion player running here. We'll be able to kind of edit the timeline there. Over here, I have -- let's look at the files themselves. So, I have an index. This index includes video, video.
Jonny: Yes, so the video is basically the entry file. This is where you can define compositions. So a composition is basically a component, but we annotate some data like frames per second, duration, width, and height. And you can give it default props because you can parameterize everything and renderer the same video with different props.
Jason: Okay. So if I'm looking at this, to just kind of map what I'm looking at here to what I'm looking at over here, a composition is mapped to these layers here? Is that right?
Jonny: Yes.
Jason: Okay.
Jonny: Yeah, so the hello world composition, it actually uses the other two compositions, but you can define them also separately as a composition. So, you can work on just one single component and not have to worry about the rest. It's like Storybook where you can just render a single component and work on that.
Jason: Yeah, yeah. That's very cool. So then in here, I have all of these bits. So, let's look at HelloWorld. HelloWorld has -- I'm going to collapse this down so we can see what's going on. We pull in some pieces from Remotion. Then we have our actual component. So, logo, I'm assuming, is like -- that's got a little bit of stuff going on. Okay. Then we have the atom. Okay. I can sort of see what's going on, but I'm not 100% clear on how we actually use all of this. So, here's what I'd love to do. I would love to make -- like, just switch this over to a view of let's use -- I have some files we can use for this. So, let's take a look in the Learn with Jason repo, if I can get to it. Okay. So, in here, I'm pretty sure we have some SVGs we can use. Do I not have SVGs?
Jonny: Yeah, SVGs, PNGs, whatever works on web you can use.
Jason: PNGs? Okay, yeah, maybe we can use a PNG then. That'll probably be a little bit easier. Is there a big one? Yeah, this is probably fine. Let's look for a PNG. Is there a bigger one?
Jonny: Yeah, these are like great things we can use.
Jason: Okay. So let's use this one. I'm going to move this over into -- I guess for now I'll drop it right into the source folder, and we'll move it around as needed. Then I'm going to close and reopen this so that we don't get the dimmed like git ignored thing.
Jonny: Sounds good. And then if you want, you can like delete all the HelloWorld stuff. We can start from scratch.
Jason: Okay, perfect. So, I'm going to start by getting out -- let's get HelloWorld, logo, and subtitle out of here. Then we're going to remove all the compositions.
Jonny: And just leave an empty fragment. And the HelloWorld tsx and folder. Then you have like a blank video.
Jason: Gone, gone, gone. Okay. So, that brings us back to empty. Okay.
Jonny: Okay. So, now you just create some React component somewhere, create a new file, create React component and export it. It can be empty for now.
Jason: Okay. So let's call this one -- we'll do like a spinning boop. And I'm going to do TypeScript and regret it. So export default function spinning boop. That's going to return -- for now, I think, we can just do image source. Is that going to work? That's probably not going to work.
Jonny: So, it's not going to work, but I've tried to help you by giving you some learnings. There are some plug-ins which will tell you what's not going to work.
Jason: Okay.
Jonny: So, this warning actually you can ignore. I think you're just using a different --
Jason: We can just make that go away, I think.
Jonny: Actually, I might want to remove this rule. Just remove the default.
Jason: Oh, it doesn't let me name if I do that. All right, fine. Fine, fine, fine. Missing return type on function. This part I don't -- what's the return type on a function? Is it like react.fc?
Jonny: I think like react node. Okay. Yeah, try that.
Jason: That makes it happy.
Jonny: Yeah, sorry about that. Actually, it's a good node. I might want to remove this rule because it's actually not -- oh, wait. You don't have to import image.
Jason: Oh, wait, I don't have to import it?
Jonny: You don't have to import it. You should be able to just run eslint safe.
Jason: Okay. So I run eslint save, you said?
Jonny: Eslint auto fix enabled? Wait a moment, sorry. It was too fast. First thing is you should use the img, but if you upper case the I, you can import it. If you don't, then eslint will also automatically.
Jason: Auto saved, which is nice. Don't reference local assets by string. Okay. So then I need to what? Import --
Jonny: So, you just need like import boop from, and do exactly that. Yeah. Then source equals boop. Then that's going to work.
Jason: Hey, look at that! I wrote TypeScript, everybody! So, this doesn't actually spin right now, but it does exist, and it should give us an actual image when we look at it on the screen, which means then I can do one of these. So, if I import spinning boop from spinning boop and I do a composition, then it gets an ID, and I can make that whatever I want. So, I'll call it spinning boop. Then what else happens? Here? I need the component. I'm just using your TypeScript autocomplete and showing why it's worth doing TypeScript.
Jonny: Yeah, exactly. The reason I like TypeScript because it does like a lot of validation. It helps you figure out what to do.
Jason: Yeah, I mean, this is very, very cool. So, we get a height, and it looked like there was a width. What else is in here? Do I need any of these other things?
Jonny: No. The other ones are okay. With the props thing, you could parameterize the video. It's actually pretty cool. It's a new feature where it doesn't compile your component until you like click on the left on the side bar and use like a dynamic import and React suspends. That makes it faster to start. But it's too advanced.
Jason: Okay, okay. So, yeah, that's fine. We can skip that from here. What?
Jonny: Okay. So, it's a TypeScript thing. So, what I would recommend, just use like the different syntax to define a component. Like export const spinning boop: React.fc. But yeah, I should loosen it up a bit, actually. What you're doing is like perfectly fine.
Jason: Okay. It's not unhappy now. So that works. Then I get duration in frames. So, I guess these values kind of vary. So, if I want 30 frames per second, which is a standard video length, then the duration of my video should be like the number of seconds times the fps. Is that right?
Jonny: Yes, correct.
Jason: Is this the right -- like, what's the right amount of frames her second in terms of, you know, this particular approach?
Jonny: I think 30 is totally fine. This is what most YouTube videos are. Most likely also what the frame rate of the Twitch stream. Then of course you can opt for 60 frames per second. There's like this debate. Some people, they upload YouTube videos in 60 frames per second. Yeah, I don't have an opinion on that, to be honest. You can do anything you want. 30 is totally fine.
Jason: Okay. Then so if I want to do -- what's a good aspect ratio here? We can do 16x9. Then we would multiply that times like 600. So is there an easy --
Jonny: Or you can just do like 720p maybe. 720 by 1280. So, that's HD. Pretty common.
Jason: Okay. So that's 720p. I'm just going to add a little comment in here about that. Okay. Is this breaking a React component? Nope, it works. Perfect. Hey, look at that. We can see our component now, and we can see how long it is. We've got our four seconds. So, these are frames. So, we can see each frame along the way. And because we set it to 30, there are 30 per second. Okay. So, intuitively, this is making sense to me. I'm getting what we're doing. Oh, that's cool that it just fits. All right, all right. Okay. I'm with you. So then I guess now we need to make it do stuff. So, how do we make that happen?
Jonny: Okay. Yeah, absolutely. So, the main thing that we are going to use is the use current frame hook. So if you are at frame ten, it will return ten. If you are at frame 100, it will return 100. That's basically it. You don't get much more help, unfortunately. So, it's actually pretty hard. But it also keeps it unopinionated, flexible, no constraints.
Jason: Okay, I get you.
Jonny: But no worries. I'm going to help you. So, yeah, I would just suggest you to do const frame equals use current frame.
Jason: Okay. So, const frame equals use current frame. That's going to auto import from Remotion. No arguments there?
Jonny: No, should be fine.
Jason: Okay, is there a way to get the total number of frames?
Jonny: Yes. So you can do use const config equals use video config. If you want, you can log it. You will see that it's exactly the data that you have just defined. It's width, height, and dimensions.
Jason: Okay. So, then we can do something like we've got our percent complete. This will be a number between zero and one based on the frame.
Jonny: Not exactly. So, what you just did is you calculated the current --
Jason: Oh, you're totally right.
Jonny: Total time in seconds. So yes, now you have --
Jason: Right, okay. So, what I can do from here is I could do like if we go really rudimentary, I could do a style component and do like, let's see, transform, and that could be rotate. Is this going to work? Maybe. Let's try it. And I'm going to say percent complete turn. Does that work?
Jonny: Wow, you just teached me.
Jason: Heyo! Look at it go.
Jonny: That's the whole thing. You just learned it. Now it's just we have to practice a lot.
Jason: Aha! Okay. I'm like super excited about this. What's up, Luke. I love those coins, and I love that you found the marquee. Aha! Behold, my bucket! (Laughter) We got a bucket loop going. Okay. So, this is really exciting. Then the other thing that I'm curious about here is we figured out how to do animation. What I don't see how to do yet is how I would do positioning. So, the composition is one size. All right. I think I need adult supervision here.
Jason: But right now I have this boop and this image is kind of absolutely positioned at the left. It's full size. So, how do I go about changing positioning and stuff like that?
Jonny: So actually, I think it's inside a flex box container. It's just on the left because by default, css puts things on the left.
Jason: Oh, so the video is a flex box container. Like the composition is a flex box container.
Jonny: Yes. There's an absolute fill helper component. Everything you put inside is absolutely positioned. But by default, yeah, it's like a website.
Jason: So, I don't need to do anything special. This here, this could be everything that I use from Remotion, and I'm going to get videos out of it if I just kind of take this -- this is a fascinating formatting style it's got here. So if I do -- let's see. Okay. So what I can do is if I have my spinning boop, then I can make this into a div, and my div is going to have -- do we have access to like css modules or anything in here?
Jonny: Wow, css modules. So, you can create a css file and import it.
Jason: Okay.
Jonny: That's going to work. But css modules, I haven't checked, and I don't use them personally.
Jason: Yeah, no worries. So, here's what I'm going to do. I'm just going to do all this at the top level. Let's do styles.css. Then we're going to do import styles.css. Is that going to work? Didn't explode at least. That's a good sign. Then I'm going to change this to a class name of spinning boop. And I'm going to take this. Oh, I can't really do that part. Okay. That's fine. Oh, you know what we can do that's fun? I'm going to do -- all right. I'm going to do something a little fun here. What I'm going to do is I'm going to declare a variable.
Jonny: Oh, interesting.
Jason: And we're going to set it to percent complete. Then I'm going to take this part out. Are you going to argue with me? I disagree.
Jonny: So, I don't know what's going on. It's probably TypeScript.
Jason: Yeah, I think you're right.
Jonny: Just using regular React types, node types. So, yeah, I'm not sure if you could do it in a regular React app.
Jason: I mean, it should just work.
Jonny: What you're about to do now might very well work. Can you like control the css variables from JavaScript?
Jason: Oh, yeah. Yeah, it's really, really cool. So, what I'm going to do is change this over here, and then we can do a turn like that. Then if I'm right, there it is. So what I've done with this video container now is I've put it up here. So video container. Then I'm going to make this one display flex so that I just have like -- I'm basically making a box on my page. I want this one to be justify content center, and we'll do align items center. Now we have -- I'm going to make this width 100%. There we go. Okay. So now we vertically centered our image here. I'm going to change all that. Then let's make this -- do a white background for now. Okay, that's good. And if I want to do like a gradient, I can go over to the Learn with Jason site. There's a gradient here that we can pull out. So, I'm going to grab -- (echoing). Stop helping!
Jonny: But yeah, it's great. You're exactly how I imagined -- how the users would use it. They just immediately jump on all the technology stuff. I use css variables. I use linear gradient inside my videos. So yes, it's great. I didn't even test it with that.
Jason: It's just so much fun how much you can do with these, right? Because I can take something like this, and then I can down here and -- I need my pink, yellow, blue. So, let's grab those. And I can drop these in here. So now we've got our yellow. We can get rid of that one, get rid of those. Now we have like a pink, yellow, blue. And I can make my background gradient. So, what I should be able to do over here now -- there we go. So, now I've got like a gradient going on. Then I can make the image itself -- let's do a width of, I don't know, we'll call it 30%. Okay. That makes me happy. Then maybe I want to make this stand out from the background a little bit. So, I can do a box shadow. And this is going to be gross. So, nobody judge me. No movement, but we'll spread it like 20 pixels. Then we'll do white. Ugh, gross. That's not what I wanted at all.
Jonny: You can use a css filter. If you remember the syntax, it's like filter: Drop shadow. Then you put in the same -- but you might have to Google if it's correct.
Jason: Yeah, I'm going to have to. So css png shadow filter. How does this actually work? Drop shadow. Is it just this? Filter url drop shadow. Where is that coming from?
Jonny: Oh, that's like for Internet Explorer 6 or something. You don't need that.
Jason: Filter drop shadow. I think this will work. Okay. So drop shadow, and then we go 0020 px white.
Jonny: But I think it's drop dash shadow.
Jason: Is it? Oh, it is! My goodness. All right. We're learning things today. I'm so happy about this. Okay. So let's also do like a little bit of extra spread. No, that didn't work. All right, fine. But that is -- I mean, that's incredibly cool stuff, right. How cool is it that we can just do something like that. So, now this would be like a video. If I wanted to make this a video and if I want to -- what's the stacking order? If I wanted it to be like rgb, we could do 255. Is that right? That's wrong.
Jonny: Oh, is this something you can do?
Jason: Yeah, you can stack your backgrounds.
Jonny: Don't you need like --
Jason: This is the new rgb syntax.
Jonny: Oh, wow.
Jason: What am I doing wrong?
Jonny: You're also teaching me a lot of things.
Jason: It's my favorite thing about this show. It's just like nonstop, everybody is learning from everybody. Why doesn't that work, though? Okay. That just doesn't work. I'm going to forget about that because I'm sure something -- wait, now what's broken? Oh, I didn't hit the play button. Okay. So we've got -- I mean, we've got this nice little thing in here. Then if I want to add text on it or something, the text that I would add on it is really whatever I want, and I would just say like -- then I can give this a class name. And we can do something like -- let's call it title. Then we'll give it a style. The style will be like -- and we can do like a bunch of these, right? So, we can do like title position, and we could do something like the height. We know the height, so I could just do it against 100% or something. So, we can start at minus 20%. How would we do this? So, here's what I want. I want it to be -- it starts 20% off screen and then ends at the middle of the screen.
Jonny: Okay. So, the middle of the screen, I think it's good to have that as a default. So, like absolutely positioned fill and justify content and the line item so the text is in the center. Then I would work with transform and translation, I think.
Jason: Okay. So, let's try --
Jonny: Yeah, you can do like minus 50%, or you can do absolutely using the values that you get from use video config.
Jason: Okay. So we have a request from chat that I'm going to do before we do this, which is they want to see this rolling across the screen. So, let's make that happen. We can go -- you know what we can do that'll make this easier? Let's just set the percentage amount on here. So, we can do percent complete, and then we can set it to percent complete, right. Then what we can do with that is we can do something like instead of doing this, we have percent complete here is going to be zero. Then down here what we'll do is we can do a calc. I love css. And we can multiply this times one turn. Okay. Now, that should still continue to work. It doesn't. I broke it. Oh, because it's the percentage. Okay. So now we can just do calculations in our css based on how far along this thing is. So, the next thing that I want to do as we're transforming is I want to do a left position. We'll calculate the percent complete times, let's go with -- how do we want to do this? We want it to be 100% plus 50%. I think what that should do, if I did my math right, which I didn't --
Jonny: Oh, it should be a semicolon between the transform and the left segment. And I think you have a comma.
Jason: Yeah, so it's the calc.
Jonny: At the end of line 26, it should be a semicolon and another comma.
Jason: Yeah, everything that I just did was so wrong. Okay. That's actual css, but I broke it. The part that I broke is --
Jonny: Oh, you need to add pixel at the end.
Jason: Wait, can't we translate -- I thought we could translate percentages.
Jonny: Okay. I see you're doing it with percentages.
Jason: So, it's calculating something incorrectly. And that's definitely me. So the percentage is changing, and that's what we expect. The part that's not doing what I expect is this rotation, which -- okay. Maybe we just try this without the calculations just to make sure I'm doing what I think it's doing. And it's not. It is not doing what I think it's doing, which means that I'm screwing this up.
Jonny: But you know what, it's like really interesting that you are doing like all the calculation in css, but actually, I would advocate we do the calculation in JavaScript. So for example, if you have an extra bracket, it will actually recognize that. And later on, we're going to use like a function called interplate, and we have a spring function.
Jason: Oh, you've got stuff for this. Okay. I thought I was on my own. (Laughter) Yeah, let's bring that in.
Jonny: I let you do a little math in css.
Jason: No, this is all good.
Jonny: You seem to want to do everything in css. I would recommend putting the math back in JavaScript so that we can use the helper functions interplate and spring.
Jason: Okay. So, if I want to do the same thing that I just did using interplate and spring, what do I -- like, how would I do that here?
Jonny: Yes, okay. So, you can write something like const left position above the return statement. Equals interpolate. Then the first argument -- so we can put in percent complete, or we can put in frame. Both is okay. So, let's just put in frame. Then you specify what is the possible range for frame. So then you put in two elements and say zero comma config.duration in frames. So, we want to map it from the left of the screen to the right.
Jason: Yeah.
Jonny: So, what would make sense is that you pass in another.
Jason: Okay. So, what I want to do is do like a negative 0.2 and then a config.width times -- or wait, that's not right because it would be --
Jonny: So, if you want to do it in percentage, you can do 0,100. Or if you want to do it in absolute pixel, you can do 0,the width of the composition.
Jason: So, that'll give us percentages. I want it to be off screen and then roll across. That's my thinking here.
Jonny: Yeah, that makes sense.
Jason: Okay. So then I just set left?
Jonny: Yeah. Then it's just add the left. Times 100, I suppose, plus percentage.
Jason: So, that needs to go in, and then this needs to be a percentage.
Jonny: Yes.
Jason: Okay. So, then assuming I didn't typo any of that, okay, so that did mostly what we want. Then I need to add this transform back in, so we'll do the transform and rotate, percent complete turn. There we go. Booping tumbleweeds, y'all.
Jonny: Nice, nice. There we go. So, right now it looks pretty linear. You could pass into the interpolate function and ease it so it looks a bit smoother, for example.
Jason: Easing, okay.
Jonny: Then you say easing.
Jason: Are there helpers for this
Jonny: You type easing with upper case and you should find that.
Jason: Here?
Jonny: Yeah.
Jason: Oh.
Jonny: So you can do like a cubic base if you want.
Jason: Let's do an easier one. Let's do an in out. And is this a function?
Jonny: No, I think you should not call the function.
Jason: Did it come in? Here's easing. Doesn't like that. What have I done wrong?
Jonny: Okay. Then maybe it's -- these are all a bit different. Actually, what I prefer to use is the spring animation. This is why I don't use the easing so much. Let me quickly see how you're supposed to use that. So, you did easing in out. Okay. So, this is a wrapped function. So you should do easing in out and then put in another easing function. So, easing in out and then easing.ease. I think that's how you make it work.
Jason: Like that?
Jonny: Yeah, I think that's it.
Jason: I get it. Okay. That makes sense.
Jonny: But yeah, this is actually straight up stolen from React Native, like line by line. It just works nicely.
Jason: This is like pretty slick. And I can see how we could pretty quickly start putting together some, you know, multiple instances of this, and we could make them bigger and smaller, and suddenly it looks like a crowd of boops rolling across the screen at different depths. There's actually -- those of you who are subscribers, and I just saw Andy Brown. Thank you so much for the sub. You can spam some corgis right now, and we can actually see an instance of that, that is done with CSS. But a storm of corgis across the screen. Yeah, so this is -- I mean, the wheels are turning here. This didn't feel particularly out of the realm of like what I would do to build a component anyways. Here they come. (Barking) Here's the stampede. So, we could do something similar to this where you can see some of them are bigger, some of them are smaller. It gives us a sense of depth. Now we're very quickly building a whole kind of scene out of this. And it's all done programmatically. That, to me, feels really powerful that I can just do that with some code because, you know, building that thing with CSS was a pain in my butt. But I love it. And I would love to be able to do that even more easily using something like this, which is really exciting. And here's another thing that I just realized. One of the things that we can do with videos is we can chrome them. So, instead of this background being -- like, I don't know what the actual color is.
Jonny: You want to like green screen it or something?
Jason: Yeah, then I can drop this right on top of my screen, and this would like overlay now. So, we can chromakey like this.
Jonny: Actually, this is a good idea, but out of the box, there is support for this. So, you don't need to have a green screen.
Jason: Hold up. Okay.
Jonny: So, you just set the background to transparent instead of green.
Jason: Okay.
Jonny: And now you see there's a checkerboard icon next to the play button.
Jason: What?
Jonny: Yes. So, there are two ways of how you can make transparent videos. One is you can just export it as a PNG sequence and many video editing programs will understand PNG sequences. There's also -- you can export it as a transparent web M video. For this thing, you need to change like three settings, which I don't remember. But it's also documented. And then you can play a transparent video in the web, which you see super rarely.
Jason: Right. I mean, yeah, the potential here -- you know, chat, are your gears turning? Because my gears are turning. I see so many really interesting applications of this where we can very quickly come up with an idea, and instead of having to figure out how to translate our web animation knowledge to video animation, which is where I've been, where I'm like, oh, I could make it do this, and then I have no idea how to get After Effects to do that thing. So I have to look up a tutorial and learn all the different controls in After Effects. After Effects is incredibly powerful, but it has a million buttons. So, I've already learned the million buttons for writing React and CSS. So, if I don't have to learn another set of a million buttons to get similar outputs, and granted I know there are limitations here because there are things you can do with something like After Effects, like you would have to learn a whole lot about Canvas or WebGL to do the same things. So, it's definitely like I can see -- but I can see this whole huge swath of options that just opened up for I need a video. Even the one I made for this overlay here with me walking out on the screen and these hearts. I could have done that with React so much faster than I did it in after Effects. Figuring out how to make those hearts like randomly generate --
Jonny: Yeah, and change the color of the hearts to yellow. Then it would be quite hard in After Effects.
Jason: Yeah, I would basically have to remake the entire video. It would be a huge pain. So, what I think I would be able to do with this, if I had the opportunity, knowing this exists, I can see a lot of really, really exciting things that will happen much more quickly because I get to use the skill set I have. So, that's -- I'm excited. Anybody who's streaming, anybody who's working with video or has ideas around video, this is a very, very cool thing that's going to unlock a lot of potential.
Jonny: Awesome. Yeah, I'm really glad you see it like that. And yeah, of course it's really complicated. You have like a blank slate. You get very little helpers. But yeah, it's nice that you see it and you immediately jump on all the things like CSS variables and gradient and web technology, and you are excited to use React. So I think it's definitely like a product for you. We are these type of people who want to write everything in React, even though it's like not the traditional and fast route, but yeah, of course we want to push this. In the future, I think we might be right to do everything in React.
Jason: Yeah, I mean, I think the thing that I always take away from this is what we really want to do is we want to use the right tool for a given job. What the right tool is depends very much on who the person is trying to do the job. If I have, you know, ten years of writing code for the web and three months of making video in After Effects, it doesn't matter if React is actually more cumbersome or kind of a workaround to get to video if I can do that in one day versus doing the After Effects thing in a week. For somebody who's good at After Effects, yeah, this is a long walk for a video. But, you know, if you already have the skill set and you're already solving similar sets of problems, this is a great way to open up a door to get things done quickly using the skills you already have. And I think that is what I find really exciting. You know, I do think that there is a tendency to try to use -- once you have a hammer, everything becomes a nail. I think React is definitely one of the biggest hammers out there right now. But that doesn't necessarily mean that -- like, there are definitely instances where it makes sense to turn a video into a nail. I need to get something done quickly, I can do this in 15 minutes because I know the animation properties that I need to make that thing work. The fact that you've got this interpolation set up, this alone is huge because I was going to have to do all this math myself in CSS to figure out how to get it, you know, start 20% and end up at 20% over, and all that stuff. I could have gotten there, but woof, so much easier to not have to. (Laughter)
Jonny: Yeah, yeah. There are more things to explore if you have some time. A few directions we could go. We could explore how to parameterize the videos, or you can make a video where you can call it via an API or the GitHub action. With the click of a button, you can every time generate a different video. We could explore the spring API that is in there. I think spring animations are like generally superior to this interpolation and easing stuff. It looks so much smoother.
Jason: Okay, yeah. Well, let's do that. So, here's what I think we should do. Let's play with springs. The way that I would like to do that is I'm going to -- can we create like another layer so that we can keep both -- like just another composition?
Jonny: Yes. Yes, let's do that. That's perfect because then I can also show you a concept called sequence. So, that's basically -- so, you're isolating another -- yeah, nice. Now you have two compositions. We have the same component. That works. Could be useful if you want to have like the same video but in different sizes.
Jason: Yeah, I think if I was going to do some different things in here, I would change up the way we're doing it, but because -- basically, for the same of time, we have about ten minutes before we start breaking down, and I want to make sure we have time to get it done. So, I'm going to get our bouncing boop in here, and then this one instead of left position, let's just turn this off for now. And we're going to keep that one right in the middle. And there it is. Okay. So, here's our bouncing boop. So, we've got this video over here, the spinning. This one is bouncing. Now, if I go to export these, will Remotion make two videos now that I have two compositions?
Jonny: No. So, the build script of npm build, they have to specify the composition name, actually. So, you would just have to call it twice. What you could do is you could import the bouncing boop into the sequence boop and make them run after each other or something like that.
Jason: Okay. So, let's use spring. Here's what I want to do this time. Let's have it kind of come out to the front of the screen like it's bouncing toward us. And we can use spring to do that. So, if I want to do that setup, what should I do to make that happen?
Jonny: How you should do it is just type in const scale equals spring
Jason: Okay.
Jonny: Then spring takes an object as its first argument. Then you have to pass in the current frame and the fps. So just type in frame -- yes.
Jason: Okay.
Jonny: Of course, if you want to delay the animation by 20 frames, you could type in frame equals frame minus 20.
Jason: Oh, I got you. Okay.
Jonny: But by default, the animation starts from the beginning.
Jason: Okay.
Jonny: Then there's config. Yes. Yeah, you can leave it at object for now and add the default. Yeah, that's it. Then just assign the style to a transform style.
Jason: And so just like that? Or like how am I --
Jonny: Um, so it's a string scale and then parentheses, and then you put in the scale, yeah. Yeah, I think that's it.
Jason: Okay. Do I need to do -- like, I don't have to set a firmer, too?
Jonny: Let's have a look.
Jason: Oh, wow. Look at that. Right off the bat. Okay. So, that's very pleasant that just worked. So then if I wanted to do -- what if I wanted to do a rotation with a spring? Can I --
Jonny: Yeah, sounds good. Then we can interpolate the scale. So, you can say const rotation equals interpolate scale. Now your rotation will also follow the spring animation, which is nice.
Jason: So, I'm interpolating scale. Then I need to do an input range. So it would be zero and one. Okay. And my output range would be zero to one. Because I can do it times a turn.
Jonny: Okay. So, I would have done like zero to 360 because I was not aware of turn. But yes, you can do zero to one to zero to one. Then the point is it's the same. So you don't need to do the interpolation at all. So you can just rotate.
Jason: Now, is scale going to -- okay. Yeah, let's do it the easy way, right. Less work. So then I can rotate, and we'll do scale turn.
Jonny: Yes. And I think you are not supposed to have the comma in between the scale and the rotation transform. That's a CSS thing.
Jason: I always forget. Look at it go.
Jonny: Yes, nice.
Jason: So now we've got all this personality in here, right. And what an amazing amount of personality to put into an animation for that much config, right. How cool is that? So, Linda is asking, do we get these super helpful pop-ups if you don't have TypeScript set up? No. So, like VS code has TypeScript built in. I think you have to have the checker on. That's a great question, actually. I don't know.
Jonny: Yeah, but I also see it like you. If you are writing plain JavaScript files, then it will -- you will still sometimes get help because I shipped Remotion with all the TypeScript definition files. It's generally not as good. You get autocompletion for the components Remotion has built in. But if you make a mistake, it will not catch that. Yeah, I would recommend to learn a little bit of TypeScript.
Jason: Yeah, and if you want to learn TypeScript, we actually do have a great episode of that on -- let's go over here to the episodes. Let's find --
Jonny: And like Remotion might be a good opportunity to do that because you have a TypeScript project set up. So, I ship everything out of the box, and you get this completion. Now all you have to do is to not remove the TypeScript and then you're fine.
Jason: Yeah.
Jonny: This react.fc thing is a bit weird. We had that. But actually, I might want to change it and make it a bit more loose so you don't get this problem.
Jason: Yeah, I mean, and I feel like that's definitely one of those things. It all comes down to preference. And we have the ability to turn this off if we want, which is always important. So, the next thing I'm going to do is I'm going to run this job again. So, I want to run the work flow because I just --
Jonny: Hold on.
Jason: Oh, no. Cancel.
Jonny: Okay. Wait a minute. Did you in the package json change the composition name?
Jason: I did. So, I came in here and I changed it to spinning boop, which is, if I'm understanding this correctly, we match it to the ID. Is that right?
Jonny: Yes, correct. Isn't it the bouncing boop?
Jason: I mean, we can do either one. I was just going to get one to build on GitHub.
Jonny: And there's a little bit more. So now you have to decide, do you want to either render a PNG sequence, or do you want to render a transparent webm?
Jason: Let's try the webm and see what happens.
Jonny: Okay. Can you quickly pull up the Remotion documentation? So there's like three settings that you need to change. Go to techniques. Then transparent videos. Yes. There you can see a demo.
Jason: Extremely cool.
Jonny: Yeah, scroll down a little bit.
Jason: Okay.
Jonny: And you see these three lines of code. Image format. Just put this into the Remotion TS file and you will be able to --
Jason: Okay. Then I'll just change these?
Jonny: Yes, yes. Remove all of this.
Jason: Remove all of it, okay.
Jonny: Yes. One last step is in the package json, now you have -- oh, actually two more steps. Sorry. You go into the package json. You change the out.mp to out.webm. Because you ran it on GitHub, you also need to change the GitHub workflow file. It's in the .github folder. Yeah, and now switch whenever it says mp4 to webm.
Jason: Got it, okay.
Jonny: Now I think you're good to go.
Jason: Okay. So let's push that up. That's up. I'm going to go in here, reload, and rerun the job.
Jonny: Oh, wait a moment. I think if you rerun the job from there, you're going to rerender the previous video.
Jason: Oh, okay.
Jonny: It's also pretty cool that you can like run -- like render a previous video in your history. But you should run it the same way as you did the last time. So, click on the workflow name and run workflow.
Jason: Okay. So here. Workflow name.
Jonny: Oh, this is the one you canceled, I think. Because it says number one. So, can you click again on actions.
Jonny: Okay. I'm at actions.
Jonny: On the left, can you increase -- oh, there's a select workflow button at the top left. Now click render video. Now you can press run workflow.
Jason: Oh, I was just missing the button. Okay. All right. Here we go. Now let's run this workflow. Okay.
Jonny: Let's hope for the best.
Jason: There it goes. And while we're waiting for that --
Jonny: Probably one shot with the time remaining.
Jason: If it doesn't work, that's fine. We saw the other one work. We'll be able to run through that. While we're doing that -- oh, thank you for the bits. Everybody, make sure you go and follow Jonny on Twitter. Also, make sure you go and check out the Remotion docs. I am really excited about this. I think it opens up some fun doors. I would love to see what you create. So, if you go and use this, make sure you send it to us. Like tag us on Twitter and show us what you're making because this is super, super fun. On top of that, like, what else we got? Let's do another shout out to the sponsors. We've had Rachel with us all day. Thank you so much, Rachel, for taking the time to do the live captioning. She's from White Coat Captioning. And that's made possible through the support of our sponsors. Netlify, Fauna, Auth0, and Hasura all kicking in to make this show more accessible, which I very deeply appreciate. While you're over at the site, make sure you check the schedule. We have a whole bunch of fun stuff. Later this week, I'm going to do a solo episode. We're going to work on Twitch overlays. Maybe we'll even play with Remotion. I don't know. Let's see what happens. I've got Gant Laborde coming back. We're going to do more ridiculous stuff. I don't know if you've seen the TikTok timewarp filter. Always a hoot. David K. Is coming back. We're going to do more on state machines. Lots of new things in that environment. If you've seen previous episodes on state machines, I'm a big fan. I think they're really, really powerful. And David is kind of the, you know, Papa state machine. So, it'll be fun to have him back. We have all state machine material. Prince is coming back. It was just Prince's birthday. So many good things. So, so many good things are happening. So, make sure you go here. Check the schedule, add it to your calendar. Jonny, is there anywhere else people should go if they want to keep up with you?
Jonny: No, I think Twitter is where I hang out the most. Actually, I have a YouTube channel where I post Remotion tutorials. I did a Spotify, for example.
Jason: Okay. So let's --
Jonny: Remotion, Jonny Burger, yeah.
Jason: Here you are.
Jonny: Yeah, so if you would like to learn to make the really crazy animations, I try to show more complicated examples over there.
Jason: Very, very cool. All right, y'all. Well, with that, that's all the time we have for today. So, thank you all so much for hanging out with us. This was an absolute blast. Jonny, thank you so much for spending your time with us today and teaching us about this. I'm super excited to see what everybody can go and create. Chat, stay tuned. We're going to go find somebody to d. Jonny, thank you so much for your time. And we will see y'all next time.
Jonny: Thanks a lot. See you.
Learn With Jason is made possible by our sponsors: