Concatenate Videos with FFmpeg and Node.js [Advanced Tutorial]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome to a covalence advanced tutorial on using ffmpeg in a node environment if you've never heard of ffmpeg it's a super cool open source project uh it's a suite of libraries that allows you to basically like handle manipulate video and audio files and also streams as well and it can get kind of tricky because you know essentially it's a binary and we're using it in node environments you know node a lot of times is wants to be kind of cross-platform or environment independent and so we're going to do all of that in this tutorial and we're going to allow you to basically deploy it to any server on any platform with the exact same code so please if you haven't subscribed already make sure you subscribe and if you have any questions please post them in the comments below but let's go ahead and get started all right so we're going to go ahead and assume that you already have node installed we're going to open up this terminal here and if you haven't installed note already you can install it from nodejs.org but i'm currently running version 16.13.2 um and if you have an earlier version of node it shouldn't matter if you're running a newer version of node it also shouldn't matter this code should work across all versions of node to be honest but we're going to go ahead and npm init and let's call this let's just call it pre-roll merge and then we're not going to worry about all the versioning and everything so let's go ahead and create that and it's going to create our package.json we don't currently have any dependencies so we're going to have to install those dependencies so in this particular project we're going to be using something called fluent ffmpeg so npmi fluent ffmpeg we're also going to need ffmpeg installer slash ffmpeg we're going to need ffmpeg or sorry it's ff probe installer and ff probe we're going to need mk derpy not drip mk derpy which we're going to create some folders i like typescript i think everybody should use typescript definitely use typescript if you don't learn it if you don't know it and you know you will basically see how it works here and we're also going to use since we're using typescript let's download the types4 fluent ffmpeg and we're going to save that so basically the the at ffmpeg installer and that ff probe installer basically install the binaries that you need to run ffmpeg on you know a platform independent environment so no matter what server you're hosting your node environment on it'll actually download the correct binary and then allow to allow give you a path variable that you can point your code towards to execute the executable so it's a very cool package highly recommend using it as opposed to just manually trying to do that and it makes you know using ffmpeg in um you know deployed like hosting sites like gcp aws all those things azure extremely easy and extremely uh convenient so definitely recommend you looking into that um we're not going to use this test script so we'll keep that empty for now but we will be creating some scripts so let's go ahead and init typescript so we're going to say npx tsc dash init all right so that's going to create our ts config dot json um i think the target es 2016 should be fine but it creates a whole bunch of just preset stuff that we probably don't need to mess with we'll come back if we need to but what we will do is let's create a script for ts and this is just going to be tsc dash p dot that's going to say just use this ts config.json to compile everything and we'll also create a start script npm run ts and nodeindex.js so what that means is we're actually going to run this ts function we're going to pile everything and then we're going to start index.js so our file here is actually going to be index.ts that we're going to create so our start function will compile the index.ts into an index.js file and then it'll run that index.js file we also need folders in here so what we actually could do is create a post install so that whenever somebody actually npm installs your node packages or your dependencies here it'll actually create the folders upon post install so what we can do is we can use mk derpy let's call one folder pre-roll let's call it an input folder and we will have an output folder and we'll probably need a temp folder as well so we're going to create all these folders as post install and for now because we already installed our node packages let's just run the post install so it'll actually create these folders as you can see we have input output pre-roll and temp now and so we have the folders that we need we could also use something like an insured directory function something along those lines but might as well just create this post install function whenever the mpmi it'll actually create these folders for you so they exist when you're going to run your project so let's go ahead and we can start actually coding here so let's give ourselves a little bit of space and we're going to need to import ffmpeg in here so that'll be from fluent um we're going to import let's see promises and this is going to be from uh the file system package so promises is basically a it's an object that contains functions that are promise based in the fs package and so we're gonna call that fs promises make the name a little bit more clear for us and then let's do base name and join from path all right so let's first we're going to actually define our ffmpeg path and so to do that we're going to require the at ffmpeg installer and we're going to grab something called the path off of that and then we're also going to grab our ff probe path and basically what these are is it is the path to those executables so we now have the paths that go to those executables to allow the um executables to run and you know take in our inputs and then create the outputs that we desire so let's also create a folders variable that'll just kind of define our folders so we don't have to put you know uh strings everywhere so we're gonna have our pre-roll folder of real pre-roll folder which is just let's see just this directory and it's called pre-roll we're gonna have our input folder this directory is called input uh we're gonna have our output folder this directory called output and we're gonna have our temp folder which is again just this directory all right so we have our folders defined now we're going to actually call ffmpeg.set ffmpeg path which is a function and we're going to pass in ffmpeg path we're going to do the exact same thing for the probe path so ffmpeg dot set pro path um let's see ff probe path ff pro path there we go and they also also have tooling you could actually download tools as well and set the tool path we shouldn't need it for this particular one but what we do need we don't actually need this but it would be nice to have some helper functions so i particularly like just creating something along the lines of like an is null function where you can pass anything into it and we're going to return object usually or type of object equals equals equals undefined so it's kind of like an is nil function so actually let's do it's not necessarily is null so let's do is nil let's do an is empty function and this is empty function will basically just be something similar but it will also include empty string so it's either is nil or empty string and then let's see is object and this will be a return object does not equal null and type of object equals object all right so now we can actually check if something is an object and then lastly lastly let's do like an array function so we know if something is an array and this one will be i actually like doing this way so i actually do object.prototype pass in the object and if that equals this string then we know it's an actual array all right so now we have um a few helper functions uh and then we may want something we might want to actually do something on error so let's create an on error function you know pass in some kind of error here and we can say if is object error then we're going to console.error let's see error error dot message and let's go ahead and just give it a new line after that as well um else we're going to console.error um just the entire thing see what it prints out as well as a new line so in one case we want to actually just log the message in another case we're just going to log whatever the heck the error was and then we want to say process dot exit code equals one since it was an error right all right so we now want to kind of essentially have a merge function and a merge all function right so the idea here is going to be it's going to save this that we're going to actually take the pre-roll and any files that are in the input folder we're going to attach the pre-roll video as pre-roll to every video in the input folder and we're going to produce a corresponding output video in the output folder if that makes sense so i think i said that right it's a little confusing but we're going to basically want to create a merge function that's going to merge a single pre-roll path to an input path and then we're going to want to have a merge all function which is going to cycle through all of the inputs and attach that pre-roll there so let's go ahead and create our merge function first so we're going to pass in the pre-roll path and then we're going to have our input path as well so what we can do is we can actually return new promise which is going to have a void return but we are going to have our resolve and reject all right and inside the funk the promise function itself let's grab our input name which is going to be the base name of the input path and what we can do is we can call ffmpeg on the pre-path and we're going to call the dot input function on the input path and let's see now we can actually define our events so on error we're going to reject and on start we're gonna actually have a function here and we're gonna have the same type deal for it on end and so let's see on start we're going to let's just log something to the console so i'll say starting merge for and then let's put the input name just so we can see if we had multiple files we could actually see what's going on there and then let's see on end we want to console.log something similar so input name and then merged we'll get a little excited and then we're going to want to resolve as well and then let's see dot merge to file and we're going to join the folders dot output with an input name um and it requires a temp folder so folders.temp and let's see this is not liking this let's see expression has no call signatures um so let's just import ffmpeg then there we go so clearly the way that i have the ts set up it actually wants to just take in the default import here so a little debugging so thank you type script and now let's see what this error is uh so it actually looks like the typings might be wrong so let's just go ahead and oh pass this to any for now all right so the typings are probably off here got to deal with this sometimes with typescript i know i'm probably the worst worst practice i could possibly do but in this particular case i'm going to allow it especially for time's sake here we're not going to go too much into that but again we have our merge function now and we're going to want to again just to make sure that we understood this we're going to do the default import here and not just import star as and we still have our function set here so that was just a mistake on my point on my part and again we're going to also have an async function for merging all all right so what we can do is we can actually put a little try catch block here and we'll call on error e if there's an error but inside the try block we're going to get our pre-roll files and this is going to be fs promises dot read der folders.pre-roll so we're going to read that pre-roll file and we're going to say if not is array pre-roll files or pre-roll file dot length equals equals zero then we're going to throw new error please add a pre-roll video [Music] to the pre-roll folder all right so we're going to manually have to add a video to the pre-roll file itself um let's see it does not like this oh any or unknown all right so let's just make it unknown then and then well this on error function let's just say basically any so onair can take in anything not just an error and then let's see for the profiles.length actually let's we lose our typings if we do that so again i am changing my mind here we want to have this be error because we want the message to be in there as a string and this is just going to be any here and then we'll handle you know the case where it's not an error in the function itself all right so after this let's say let pre-roll equal a string and then we'll use const p of pre-roll files so we're going to iterate through these and we're going to say const ap path let's call it ap path why not and it's going to be joining folders dot pre-roll and p and we're going to say constat equals await fs promises dot stat ap path and what this is going to allow us to do is we're actually going to check if stat that is directory so if it's if it's not a directory then we're going to assume that we want this to be our pre-roll video and so basically we're going to go through all of the pre-roll files and we're grabbing the last instance of whatever you know whatever the last one is in that particular folder all right and then we're going to go ahead and break um actually sorry i've said that totally wrong with this break here we're going to grab the first instance so we're only going to get as far as we need to and then we're going to break if we didn't have this break it would be grabbing the last one but why do we want to do all the extra processing if we don't need to we'll just grab the very first file that is not a directory all right now if is empty pre-roll we never assign anything then we know that we actually have to see oh so i guess now that this is potentially being used and not defined it wants us to actually have a definition in here so let's just say you know we can say this for typescript so we're going to go ahead and just say or we don't need to actually set it equal to something i'll just say that it is pre-roll or undefined so if it is undefined then we want to throw a new error and that error can be please add a pre-roll video to the pre-roll folder so it's basically this exact same error we could clean that up a little bit we could have default errors you know we could actually create a variable for this if we don't want to let's just go ahead and do that let's just say const pre-roll error equals and it'll be a string i think i should have a copy there yep so now we can go ahead and just call that just so we don't have to cut you know repeat code if we change it we like change in one place much better that way all right so now we know that we have a pre-roll video and so we have to grab our input files reder very similar function here and we're going to again iterate through each one now and we could actually do something very similar to here where we say if not is an array pre-roll files whoops or pre-roll input or input files i like we can actually create another error here we can say input error um and actually let's go ahead and just create an object for this make it a little bit cleaner [Music] all right and then we're going to have errors dot pre-roll errors.preroll and this is going to be errors.input all right and so we're going to iterate through all of the input files themselves and we'll say ipath equals join folders dot input oh wrong variable i and then we're going to say const stat equals await fs promises dot stat ipath and if not stat that is directory so if it's a file we're going to await the merge of pre-roll and ipath so we'll actually see it let's see an actual string right so this function we probably could define a little bit better um to allow it to know that if this is true then that would actually by definition be a string but we're going to go ahead and skip that now we'll create another video on that in the future and then finally we're going to actually just call this merge all function so technically we could just make this a self executing function it doesn't need to be defined like this but we're going to go ahead and just keep it keep it kosher and just leave it like this all right so we're going to go ahead and save all this and if we haven't messed anything up we should be able to add some videos to this now and technically it should work so let's see let's go ahead and look for a video here so it looks like i have this video here from another lifetime let's see um if i can actually pull it over to this screen there we go yeah so i have this video up here uh literally back when the only aspect ratio was four three and uh megapixels i don't even know if mega was a thing yet when it came to pixels um but let's go ahead and use this as our input and so this is called wake.mp4 we're gonna go ahead and put this in our input here that's our input folder and for a pre-roll um i went ahead and just created this the kgb it's a quick little pre-roll just kind of defines the trick and we're going to pop that in our pre-roll folder here and if all goes according to plan we should see something pop up in this output folder so we're going to go ahead we're going to run npm start it runs the ts function first which is going to use tsc it worked and it actually started the merge and merged it right so now we have this let's go ahead and open this real quick we'll play it what you're about to see is a kgb and bam videos have been merged so again this might not be completely error proof uh wrote this pretty quickly so there might be a few things but it is fairly robust and i highly recommend that you you know play with this find the errors make it better and figure out some different functions that ffmpeg provides because honestly f mpeg has a ton of functionality and it's super awesome for video processing one thing to note is there is a lot of kind of inconsistencies at times and the errors aren't great so you may have to look at errors for instance if you're not using if you're using two videos that are different sizes you actually have to resize the videos to be the right size first before trying to merge them so whenever you're merging videos make sure they're the exact same size as you saw the aspect ratios were the same in those videos and so it worked without issue but again if you have any problems with this feel free to drop them in the comments and let us know because we would love to uh we'd love to make a follow-up video so alright everyone until next time all right so hope you all enjoyed that i hope you all learned something i don't think anything we did was too complex or complicated so i think it was pretty straightforward but you have any questions definitely just feel free to throw them below we'll get to you know answering them as best we can but i think the real power in this was the you know creating a reusable starting template for any ffmpeg-based project right so completely platform independent um using the ffmpeg installer and the ff probe installer you can really kind of transport this to whatever environment you need and still use ffmpeg and there is a whole slew of options in terms of what you can do with this with this project so i highly encourage you to take this code run with it and kind of create more and more complex and advanced projects if you do anything really cool let us know because we'd love to kind of feature you in a future future episode and definitely if you haven't subscribed make sure you subscribe otherwise i'll see you later
Info
Channel: Covalence
Views: 6,605
Rating: undefined out of 5
Keywords: Covalence, Programming, Coding, Software Development, learn to code, online coding bootcamp, intro to javascript, intro to typescript, node.js, free web development tutorials, software development bootcamp, web development, javascript, typescript, become a programmer, how to become a software developer, programming tutorials, become a full stack developer, software careers, ffmpeg, ffprobe, ffmpeg in node
Id: Yx4D9IfBHks
Channel Id: undefined
Length: 26min 5sec (1565 seconds)
Published: Fri Mar 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.