How I create 100s of viral UGC videos in n8n (free template)

Rory Ridgers shows how to build an n8n workflow that automatically generates UGC-style videos from a product image. The workflow uses OpenAI to analyze the image and write a script, Nanobanana to create the first frame, then Sora to generate the full video. A free template is included.
Chapters
What's up guys? In this video, I'm gonna be teaching you how you can use Sora and Nanobanana to create viral UGC videos completely autonomously, and you can create as many as you like. So let's not waste any more time. Let's jump straight into it and I can show you how it all works. By the way though, before we get into it, I just wanna say that the template for this is completely free. So if you go down to description, there'll be a link that says free template and you just go ahead and grab it for free. You can get started with this straight away. Okay, so we're in NAN now and this is the system. And as you can see, it's not that complicated. There's not too many nodes. So what we're gonna do is I'm gonna break down each of them and then we'll run through a quick demo and then I'll go a little bit more in depth in here so you can see what actually went down. So to begin with, we just have an on form submission, and in here you can put in your product and the product name. So in this video, we're going to be making UGC videos for products. So you can upload any kind of product and just tell the system the name of the product, and it's going to make a UGC style video around that particular product. So in there, you upload an image and you upload the name, and then we do some data manipulation things here that I'll show you a little bit later on. But we basically move it from a file to Base64, and then move it back from Base64 into a file so that we can give it to our OpenAI step here that's going to analyze the image and basically give a breakdown of how the model should look. So in this, there's going to be a model and there's going to be some kind of setting which is going to need to be planned by an AI agent. There's also going to be a little script for the model as well in the video. So with this first one, it's just going through, it's looking at the image, and then it's coming up with a model that best fits that. So for example, if it's something like a football, then it might be a football player for example. So that's going to give us a detailed output of how the model should look. And then same thing here, but we're doing it with the settings. So it's going to take the image as well as the model description and then come up with a detailed description of how the settings should look. And then this last LLM step here is going to take all of that, it's going to come up with sort of a plan for the video as well as a script for what the person's actually going to be saying. And then we use the Nano Banana, the Gemini model here, to generate the first frame. So this just gives Sora, our AI video model, something to sort of go on If we give it one, like the first frame, it gives it something to go on a reference. So we send that all over, Nanabanana creates us our first frame, and then we just resize it to make sure it's fitting the right dimensions. And then we generate that video with Sora. So we give it the model description, setting description, the script, and the reference image as well, which is the first frame. We give it all to Sora, and then it's going to generate that video for us. And then here, basically the way it works with Sora is you first send off a request to make the video, and then you kind of have to poll it to actually get the results of the video. So that's what these two steps are here. And then we upload it to Google Drive, of course, to get a link for it so we can actually view it. So we're going to run this through quickly, and this is going to be the image that we're going to be using. So this product is what we're going to be using for our UGC video. So I'm going to upload that and then just give it a name. So I've uploaded it, and we're just going to say something like flask, uh, bottle, and then hit submit. And then what we're going to do is we're going to let this run all the way through. I'm not going to make you sit here and watch it run all the way through, but I'm going to let this run all the way through we'll have a look at the outputs, and then we'll go into a bit of a breakdown of what actually happened inside the system. Sorry to interrupt the video, guys, but I just want to say, if you're really serious about learning NAN and actually implementing these NAN solutions into a business, I've just opened up the waitlist for my new NAN community where I'll teach you exactly how to do all of this. I will take you from a complete beginner in NAN to an absolute master and then teach you exactly how to implement this into a business as well. So if you want to sign up for the waitlist and get notified as soon as the community drops, as well as getting an early bird discount, then I will leave the link to sign up for the waitlist in the description of this video. Okay, so it's finished running through now, and this is what the result looks like. So it looks a little bit squashed at the moment, it's just because of the preview. Uh, but if we play this through—
hey guys, just soaking up the sun at the park this afternoon, and I had to share my new favorite flask bottle. It keeps my infused water cold for hours even when—
okay, cool. So obviously with this system, you can take it away, you can do what you like with it, and you can adjust it. So for this for the script, it probably would have made a little bit more sense to do a longer video because you can see it got cut off a little bit. But this gives you an idea of how they can look. And of course, the bottle is the exact one that we uploaded, which is really, really cool. So yeah, it's literally taken the exact one we uploaded, the exact product, and it's put that straight into the video. It's not something that kind of looks like it or resembles it. It is the actual product we uploaded. So now let's have a breakdown of what actually happened here. So let's just start from the beginning. So on form submission, this is what we received. We received the product name, which is Flas Bottle, and then we received binary data. And binary data, if you don't know what it is, for this we're going to be mentioning it a few times, so I might as well just tell you. Binary data is basically just sort of a bunch of ones and zeros that make up images. Well, they make up a lot of different things, but in this example they make up images. So basically just a random jumble of numbers and letters, or to us it looks random, but then to a computer it's able to determine what those numbers and letters actually mean. So you can see here we can view it, and this is of course the image we uploaded. And then what we do is we extract from file. So we move that file into a base64 string. And this is what it looks like as base64. You can see just random jumble. To us, it's completely random. Of course, it's not actually random, but to us it looks completely random. And the reason we do this is because it's much easier to work with. So when we want to send that over to like Gemini, the Nanabanana, or where we want to send over to Sora, things like that, it's much easier to do that when it's in the base64 format rather than as a file. So that's why we do that. Um, but then what we do immediately after that is we convert it straight from Base64 back into a file, which sounds sort of counterintuitive and sounds silly. The reason we do that is because to do anything with binary data, the binary data that you're trying to use has to be coming from the step before. So the form submission, that was where the binary data came from. Then we need it as a Base64. So we move that over and turn it into a Base64 because the binary was right before it. But we don't need it in base64 right now, if that makes sense. Right now we actually need it as a file, so then we turn it back into a file so then we can use the OpenAI analyze an image and we can just go down here, input type binary files, and then put in that file. So yeah, that's the reason we do it like that. We first get the binary, turn it into base64 because we need it later on and we can reference that variable, but we do actually need the binary as a file, so we turn it back into a file temporarily to use in this step. So this step here, basically what we've done is of course we give it— it's our Analyze Image. So we give it this image by giving it the binary file, and then we've just got this long prompt in here that essentially just says to it, analyze the image, and then you are an expert creating UGC ads, you need to act like a producer for UGC style videos, I want you to take the image and then give us a detailed output of how a model should look like. So this this is what it gives us, something like this. So model description: gender female, age 28, hair color light brown, hair length— so you can see it's very, very specific, and it's been prompted to do that because it could kind of say like gender could be male or female. Maybe for this, female works a little bit better, but I found when I was first testing it out for sort of these like, I guess, gender-neutral things like a bottle, it was saying, oh, it could be male or female. And then when it comes to the image generator a little bit later on, it gets a little bit confusing to know what to do. It's better if you just have clear instructions exactly how they look, even if it's not necessarily right. Like maybe it should have been better if they were a man, but it's no good basically in this prompt. It's saying men or women or blonde or brown hair. It's better for it to just say one of them, like just this color, just this gender. And then we pass that over to the models, to the model and setting prompt, and we give it the information on the model. So what was just outputted here, And then we say to it a similar kind of thing. You're an expert at crafting UGC style videos. You need to act as a producer for UGC style videos, but this time don't mention the model at all. You are just taking the information on what the model looks like and what the product is, and then you're going to craft us an output of what these settings, of what these settings should look like. So you can see here again, it's really, really detailed. It's better to be really, really detailed with these AI image generators and video generators because if you're not, it kind of does its own thing and it doesn't usually end up looking that good. If you just tell it exactly how it should look and then it just actually does it rather than having to think about it, you just get way better outputs. So this is what it looks like. We're not going to read through the whole thing, but of course you saw the video, so this is what it was describing. And then we talk— and then we pass it to a Plan and Script LLM where we give it the model, we give it the setting, and we give it the product name that we uploaded. And then we say to this, basically craft out a direction for this video and what's actually going to happen in the video, and also generate a script for us. So you can see it kind of just plans out the video. So UGC style hyper for realistic video continues from the first frame. An athletic 28-year-old woman with light brown hair, da da da, she's casually dressed in a light airy blouse. And then it basically just merges it all together and gives us a plan for the video of how the model should look, how the setting should look. And then there's also gonna be a script. So yeah, script. Hey guys, just soaking up the sun in the park this afternoon. I had to share my new favorite flask bottle. Yeah, perfect. So it just merges it all together, gives a direction for the video, and gives us a script. Then what we do is we just run that through a JavaScript node. And the reason we do this is because these outputs are going to be sent over in a JSON body, um, to the— even Nanabanana or to Sora. So we need to make sure it's in a perfect format because when you're sending things over in JSON body, there's sort of certain characters and things like this that you can't send over. So if it was to include, let's say, an exclamation mark or some quotation marks in the wrong format in its output, and we try to send that over in a JSON body, it would just break and it would break the whole system. So we just run it through this JavaScript here that JavaScript was generated by AI. And it's basically just going to make sure that its output is sort of like legal. I like to say it's allowed to go in the JSON body. It's not going to throw up any errors. So it just goes through it and it just cleans it and makes sure it's all right. So you can see this is the actual output. And then this is what it gave us. It just made it fit to go into a JSON body. And then now we move on to the actual fun stuff, generating the first image. So we're using Nano Banana here, which is actually Gemini 2.5 Flash image generation model, but the codename sort of is Nano Banana. And that's probably where you've heard it the most. Is nanobanana. So this is how the API call looks. Method is going to be POST. This is going to be the URL here to just make sure we're talking to the right AI model. And then usually you would send over headers, but we're not going to send over headers. What you're going to do is you're going to go to predefined. At the moment, your authentication would be on none by default. You want to go to predefined credential type, and then you're just going to do your Google Gemini, uh, credential that you should already have in NAN. If you don't have that, don't worry. All you do is you go over to the Google AI Studio and then you can just go to API keys, create a new API key, and just copy it and paste it in. It's as simple as that. It's not like setting up the other Google credentials, which can be a little bit of a nightmare. It's literally just an API key. So now we have our method, we have our endpoint, and then we have our authentication. So we just need to send over a JSON body, and the JSON body is basically just going to be the prompt for our image. So this is how it looks, and the only parts you really need to worry about is in the text part here. So we have a role user, so it's just the user prompt, and then text, and then this is our prompt. So make a first scene for a UGC style ad using the attach— that should say product— and this info. It should be a close-up of the product. And then setting, we just give it the setting. And then we say no logos or trademarks, don't include any humans. And now this might seem a little bit weird that we've obviously generated the model, we're not including the model in the first frame. The reason we do that is because ideally you would have the model in the first frame for a UGC style ad, but I found that it can be really, really difficult with Sora where they will basically just block your request. Because if you're sending over— you're sending over a reference image, which is the first image in the frame. You're sending that over. It's the same thing as if you was inside the ChatGPT interface, just like uploading an image and then typing something out. It's the same kind of thing. But the issue is with Sora, when you send over an image with a human in it and it's sort of a realistic image of a human, it thinks that you're impersonating them and trying to get them to do things that, you know, they wouldn't do in real life. Sort of, yeah, impersonating someone. Um, so 9 times out of 10, they just block it if there's a human in your reference image. So what we do is we get Nanobanana to create the first frame, and it's just going to be the product with the setting. And then we just give the prompt for the model, how the model should look, to Sora, and then get Sora to generate that model. Because then that way Sora knows that this person isn't real, it's just a text prompt, and it's generating it itself. So yeah, hope that makes sense. We do it to make sure that Sora doesn't block our request, because when I was testing this out It's happening all the time and it was so annoying. So I found the best way is to just make sure that no humans are included in this first image. And then we have a section down here called inline data and then MIME type image PNG and the data. And here we put in that Base64 string that we got from the start. So this one here, extract from file. Like I said, it's easier when it's in Base64. Um, and I said we're going to need it later. This is when we need it. So then we just drag that variable in And then basically what we've done there is we've just attached the image. So like I said, it's as if you are talking to it through the interface and when you just sort of drag in a file or an image and say, uh, what's in this image, for example, that's what we are basically doing here. We're just attaching an image with our text prompt. So then, so the outputs again in binary, and if I hit show data, I'm not going to, cuz it'll probably lag a little bit, but it's just gonna be like ones and zeros like I said before, but it contains the actual image. So then we just convert this into a file like we did earlier, and now we can actually view it. So if we go to view, You can see this is what it gave us. So this is the exact product which was in the image that we uploaded, which is really, really cool. The exact product. And then we edit that image, so we just resize it to 720 by 1280. You can crop it as well if you want, um, otherwise you might get a little bit of a squish look if you do resize it. So it's up to you, resize or crop, you can play around with it. And that just gives us the resized version, um, and it's sort of like the, you know, TikTok format, like that portrait format. That's what we're going for there. And then now we come over to Sora. We're actually generating the video. So in here, the method is POST. The URL is just api.openai.com/v1/videos. This is going to be for Sora. Well, this is going to be for their any Sora model, but we're using Sora 2, which we define down below. And then headers is just authorization and then our API key, content type application/json. So just your standard. And then we send over a body. This time we don't send over as JSON just because we don't need to. We send over as formData. And basically what formData is, is it's a JSON body on the backend. But to us, it just looks like, I guess you could say, like these form data where we put a name of the variable and then the actual value, which is the same thing as a JSON body. But it's just a little bit easier for us. Like if we look at this JSON body, it's the same thing, like the name of the variable and then the value of it. But you can see this one is sort of wrapped in all of these variables and arrays and it's just a little bit harder to do it. But with this API call, you don't need to do all of that, so you might as well just do it like this where it's just name and then value. So to begin with, we have the prompt which looks like this. This is going to be the output from our plan and script node here. So this is how it looks, uh, you can see pretty long, perfect. And then what we do is we do model Sora-2, and you can do Sora-2 Pro if you want to use the Pro model. Of course, it's going to be a bit more expensive. For this, we're just going to do Sora-2. And then you do the parameters and make sure the parameters— so this is gonna be like the dimensions, the size— is the exact same as what you just resized it to. Because you are attaching this image, which are these dimensions, you have to do the exact same dimensions in here. Otherwise it'll just throw up an error and not work for you. And then you can do the amount of seconds for this. I just did 8. I think off the top of my head it goes up in 4, 8, and 12. Um, so it goes up in increments of 4, I believe. You can't just do anytime you want. There are like set ones. But yeah, you can have a play around with that. I did 8 seconds. And then we switch this from form data to NaN binary file, and then the name is input reference. And then we just do the input data field name is data, as you can see from the step before. Data— this is our image generated by the Nanobanana, and we're again just attaching that like we did with Nanobanana with the image that we uploaded of that bottle. We're now doing the same thing with Sora, but we're attaching the image that Nanobananamade. And then what it does is it just gives us an output like this where it gives us a video ID and just says that it's queued. So video ID, and then it says that it's queued. And what we need to do now is we need to poll it. So we basically just need to keep going over and calling a different endpoint and seeing if the video is done. So what we do is first of all we just wait 10 seconds, and here we're creating a bit of a loop. We wait 10 seconds and then it goes to this API call here, which is literally just going to be method is GET, and then this endpoint here, and you just drag in your video ID that you got before. So here we get our video ID, you just drag that in as a variable, and then that time, every time it calls the endpoint URL, it's going to be referencing that video that you've just queued. And then for the headers, you can just do the predefined credential type OpenAI like we did with the Nanobanana with the Gemini API token. And then this is going to keep running through, and what we do here, this is really nice actually, And this is a little NAN top tip as well. The good thing about this is, is when the, the no data comes through, when the video isn't ready yet, actually errors. Um, so what we can do here is we can come to settings and then we can do on error continue using error output. And what that does, if we zoom in, you can see there's two prongs here, there's two outputs, there's success and error. And all that happens every time it errors, instead of stopping the whole workflow, it just goes down this error route. So it's kind of acting like a switch node or a true or false node that we have inside of N8N already. But yeah, when it's a success, it means the video is generated, so it carries on. But when it isn't, it errors, which just means it goes back round. And this here just creates a loop. So it will wait 10 seconds, it will try and do it, it'll probably error because it's going to take more than 10 seconds, and it'll come back round, wait another 10 seconds, do it, error again, and then keep going around. You can see this went round 10 times. On the 11th time, it actually succeeded and we got the video. So now again, we have the binary data. Should be familiar with this binary data stuff now. Get the binary data. If we view this, you can see— guys, just soaking up the video I just showed you. And then all we do, because it's binary and we want like an actual link or a way to download it, simply just upload it to Google Drive. So you just do, uh, resources file, operations upload, input data field name is going to be data. As you can see, this is the binary that we just made. It's going to be data, and then you can name it whatever you want, and you can save it to whichever folder. I've just saved it to my root folder on Google Drive. But yeah, you can save it to wherever you want and you can call it wherever you want. And then we get a web view link. And if I open this up, yeah, so as you can see, the sun at the park, this app— as you can see, it's now loaded. You'll probably find, um, when you immediately go and try and view it in your Google Drive, it will still be like rendering or processing. It says all you have to do is you can just download it and then of course just view it like this as the downloaded version.
More from Rory

Dynamic Workflows are crazy. This is how to actually use them (beginner's guide)










