Ionică Bizău

Uploading videos to YouTube using NodeJS

Using different service APIs may be difficult, especially for beginners, but not only. In this post, I will try to make clearer how to upload a video on YouTube, using NodeJS.

Back in 2013 I published my first NPM module: youtube-api–an object-oriented wrapper for the YouTube v3 API. People liked this module and the feedback came. Contributions, bug reports, stars etc. That means people actually used my module which is incredible. 💫

So, let's suppose you have a video file (codename: video.mp4) and you want to upload it on your YouTube account. While there are a couple of authenticating methods (JWT, OAuth2, Server Key etc), to upload videos on YouTube, you need OAuth2 authentication.

The documentation cleary states:

Service accounts do not work for YouTube Data API calls because service accounts require an associated YouTube channel, and you cannot associate new or existing channels with service accounts. If you use a service account to call the YouTube Data API, the API server returns an error with the error type set to unauthorized and the reason set to youtubeSignupRequired.

So, we need OAuth2 authentication. If you are not familiar with OAuth2, you may need to read the docs.

Creating a Google application

Like for other API services, you need to create an application which will be the bridge between you and the API service. To access the YouTube resources, you need to create a Google application.

  1. Open your Google console and create the project by clicking the Create Project button.

  2. Set the project name in the popup that was opened.

  3. After the application is created, go to APIs & auth and click the APIs menu item.

  4. Here you have to enable the YouTube Data API. For that, click the YouTube Data API link and then click the Enable API button.

  5. Before getting the credentials, you have to set the Consent screen information (the product name is mandatory):

  6. Now it's the time to get the application credentials. But there are no credentials yet. You have to create the OAuth2 Client ID. To do that, go to Credentials page and click Create new Client ID. A popup will be opened.

  7. Set the Authorized JavaScript origins–just put http://localhost:5000 because there will run our local server (you may add other origins like development and production urls). The callback url is http://localhost:5000/oauth2callback–after allowing the application to access your account (YouTube resources in this case), you will be redirected there.

  8. After clicking the Create Client ID button, you will get your credentials.

  9. Now click the Download JSON button to download the credentials in JSON format.

Since you have the credentials on your computer, we can now start coding our script. 😀

Using youtube-api to upload the video

We will set up a lien server which will handle the OAuth2 callback url.

See the inline comments. It's easier to understand the things.

/**
 * This script uploads a video (specifically `video.mp4` from the current
 * directory) to YouTube,
 *
 * To run this script you have to create OAuth2 credentials and download them
 * as JSON and replace the `credentials.json` file. Then install the
 * dependencies:
 *
 * npm i r-json lien opn bug-killer
 *
 * Don't forget to run an `npm i` to install the `youtube-api` dependencies.
 * */

const Youtube = require("youtube-api")
    , fs = require("fs")
    , readJson = require("r-json")
    , Lien = require("lien")
    , Logger = require("bug-killer")
    , opn = require("opn")
    , prettyBytes = require("pretty-bytes")
    ;

// I downloaded the file from OAuth2 -> Download JSON
const CREDENTIALS = readJson(`${__dirname}/credentials.json`);

// Init lien server
let server = new Lien({
    host: "localhost"
  , port: 5000
});

// Authenticate
// You can access the Youtube resources via OAuth2 only.
// https://developers.google.com/youtube/v3/guides/moving_to_oauth#service_accounts
let oauth = Youtube.authenticate({
    type: "oauth"
  , client_id: CREDENTIALS.web.client_id
  , client_secret: CREDENTIALS.web.client_secret
  , redirect_url: CREDENTIALS.web.redirect_uris[0]
});

opn(oauth.generateAuthUrl({
    access_type: "offline"
  , scope: ["https://www.googleapis.com/auth/youtube.upload"]
}));

// Handle oauth2 callback
server.addPage("/oauth2callback", lien => {
    Logger.log("Trying to get the token using the following code: " + lien.query.code);
    oauth.getToken(lien.query.code, (err, tokens) => {

        if (err) {
            lien.lien(err, 400);
            return Logger.log(err);
        }

        Logger.log("Got the tokens.");

        oauth.setCredentials(tokens);

        lien.end("The video is being uploaded. Check out the logs in the terminal.");

        var req = Youtube.videos.insert({
            resource: {
                // Video title and description
                snippet: {
                    title: "Testing YoutTube API NodeJS module"
                  , description: "Test video upload via YouTube API"
                }
                // I don't want to spam my subscribers
              , status: {
                    privacyStatus: "private"
                }
            }
            // This is for the callback function
          , part: "snippet,status"

            // Create the readable stream to upload the video
          , media: {
                body: fs.createReadStream("video.mp4")
            }
        }, (err, data) => {
            console.log("Done.");
            process.exit();
        });

        setInterval(function () {
            Logger.log(`${prettyBytes(req.req.connection._bytesDispatched)} bytes uploaded.`);
        }, 250);
    });
});

Before running the script, we have to install some dependencies:

$ npm i r-json lien opn bug-killer youtube-api pretty-bytes

Then just run the script node your-script.js. You will have to allow your Google application to access your YouTube account and be patient until your video is uploaded. 🎉

Results

If everything runs smoothly, you will see your video in your YouTube account. If you want to play with other YouTube resources check out this playground application.

If you have any questions, ideas or anything, check out the youtube-api package on GitHub and open an issue if the things are still unclear to you.

Happy uploading! 😄

Have feedback on this article? Let @IonicaBizau know on Twitter.

Have any questions? Feel free to ping me on Twitter.