Subir vídeo a YouTube con NodeJS

David's Devel - Subir vídeo a Youtube con NodeJS
Subir un vídeo a YouTube desde propio tu sitio web es algo que te facilitara el proceso, te dará mayor control y te ayudara a automatizar la tarea de enlazar un canal de YouTube a tu sitio web.

¿Para que montar un vídeo a YouTube desde mi sitio web?

Pues como mencione, te hará mas fácil el proceso de subir el vídeo ya que desde tu propio sitio web puedes administrar tu canal da YouTube. Te dará mayor control, ya que tu mismo puedes establecer tu propia UI para el proceso. Te ayudara a enlazar el canal a tu pagina, cuando se sube un vídeo puedes guardar la URL, el titulo y la descripción para crear una galería con los vídeos de YouTube.

Y algo importante: Ahorras espacio en la Base de Datos, Al usar el almacenamiento que ofrece YouTube.

Vamos a Empezar

Obtener Credenciales.

  1. Entramos a Developers Console de Google
  2. Seleccionamos el proyecto o Creamos uno nuevo.
  3. En el Panel izquierdo seleccionamos Biblioteca.
    Subir Video a Youtube - David's Devel - API Y Servicios
  4. Buscamos "youtube". Y seleccionamos YouTube Data API v3.
    Subir Video a Youtube - David's Devel - Youtube Data API
  5. Entonces Habilitamos la API. Y en el panel de la izquierda seleccionamos credenciales.
    Subir Video a Youtube - David's Devel - Habilitar Youtube Data API
  6. Le damos en crear credenciales y seleccionamos ID de cliente de OAuth.
    Subir Video a Youtube - David's Devel - ID OAuth
  7. En tipo de aplicación seleccionamos Web. E ingresamos el nombre de la Aplicación.
    Subir Video a Youtube - David's Devel - Nombre de la App


  8. Añadimos el dominio de la pagina y la URL de redirección al completar la autenticación.(Si no tenemos registrado el dominio en la aplicación hay que registrarlo).
    Subir Video a Youtube - David's Devel - Dominio de la App
  9. Le damos crear y Obtenemos nuestras credenciales de Autenticación.
    Subir Video a Youtube - David's Devel - credenciales de autenticación
Una vez obtenidos nuestros Tokens vamos a configurar una de la partes mas esenciales de este ejemplo.

Configurar el Servidor.

Para esto usaremos los módulos: express, express-fileupload, googleapis e isomorphic-fetch.


  npm i --save express express-fileupload googleapis isomorphic-fetch es6-promise

Declaramos todas las constantes:

  //Server Const
  const express = require("express");
  const app = express();
  const fileUpload = require('express-fileupload');

  //Google Apis
  const {google} = require("googleapis");
  const OAuth2 = google.auth.OAuth2;
  const youtube = google.youtube("v3");

  //Native Modules
  const {
    existsSync,
    writeFileSync,
    unlinkSync,
    readFileSync,
    createReadStream,
    mkdirSync
  } = require("fs");
  const {join} = require("path");
  
  //Fetch
  require('es6-promise').polyfill();
  const fetch = require("isomorphic-fetch");
  
  //Env
  const PORT = process.env.PORT || 3000;
  const client_id = "your-client-id";
  const client_secret = "your-client-secret";


Usamos en middleware de express-fileupload.

  app.use(fileUpload());

En nuestras rutas añadimos la "/authSuccess" con la cual generaremos un Access Token y un Refresh Token.

Esta recibirá un query con el código para el OAuth, con el cual generaremos la URL de autenticación.

  app.get("/authSuccess", ({query}, res) => {
    let {code} = query;
    let dataToSend = `code=${code}&
client_id=${client_id}&
client_secret=${client_secret}&
redirect_uri=http%3A%2F%2Flocalhost:3000%2FauthSuccess&
grant_type=authorization_code`;

    ...
  })

Después hacemos una petición a la API OAuth de Google para obtener nuestro Refresh Token.

  app.get("/authSuccess", ({query}, res) => {
    ...

    fetch("https://accounts.google.com/o/oauth2/token", {
      method:"POST",
      body:dataToSend,
      headers:{
        "Content-Type": "application/x-www-form-urlencoded"
      }
    })
    .then(response=>response.json())
    .then(data=>{
      let {refresh_token} = data;
      if (!existsSync("temp")) {
        mkdirSync("temp");
      }
      writeFileSync("temp/refresh-token.txt", refresh_token);
      res.redirect(302, "/upload");
    });
  })

En esta petición enviamos la URL previamente creada para obtener el Refresh Token. Recomiendo guardar el Refresh Token en un archivo temporal o en la base de datos ya que con el se puede obtener un nuevo Access Token sin volver a pedir la autorización a la cuenta.

Ahora vamos a crear la ruta "/upload" con el método POST que va a procesar el vídeo.

Obtenemos los datos del body y el archivo y el tipo con express-fileupload.


  app.post("/upload-video", (req, res) => {
    let {file} = req.files;
    var {title, description} = req.body;

    let mime;
    switch (file.mimetype) {
      case "video/mp4":
        mime = ".mp4";
        break;
      case "video/3gpp":
        mime = ".3gp";
        break;
      case "video/x-msvideo":
        mime = ".avi";
        break;
      default:
        mime = ".mp4";
        break;
    }
    file.mv(join(__dirname, "temp", "video"+mime), ()=>{
      ...
    });
  });

Ejecutamos file.mv y le pasamos como segundo parámetro la función callback que vamos a ejecutar depues de movido el archivo.

En el callback iniciamos una instancia de OAuth2 y pasamos el ID y Secret. Leemos el Refresh Token del archivo de texto y generamos un nuevo Access Token.

  file.mv(join(__dirname, "temp", "video"+mime), ()=>{

    let oauth2Client = new OAuth2(
      client_id,
      client_secret
    );

    let fileBuffer = readFileSync(join(__dirname, "temp", "refresh-token.txt"));
    let refresh_token = Buffer.from(fileBuffer).toString();

    fetch("https://www.googleapis.com/oauth2/v4/token", {
      method:"POST",
      headers:{
        "Content-Type":"application/x-www-form-urlencoded"
      },
      body:`client_id=${client_id}&
client_secret=${client_secret}&
refresh_token=${refresh_token}&
grant_type=refresh_token`
    })
    .then(response=>response.json())
    .then(data=>{
      let {access_token} = data;
      ...
    });

En la respuesta de la petición obtenemos el Access Token, iniciamos credenciales y pasamos en la opción auth el Cliente OAuth2.

  ...
  .then(data=>{
    let {access_token} = data;
    oauth2Client.setCredentials({
      access_token,
      refresh_token
    });
    google.options({auth:oauth2Client});
    ...
  })

Ahora configuramos las opciones de video. part son las opciones que vamos a pasar, en este caso "status" y "snippet".

En resource pasamos snippet y status. En snippet pasamos el titulo y la descripción. y en status pasamos el privacyStatus, que para esta prueba la configuraremos como privada.

Y por ultimo la opción mas importante de la API: media, que contiene el body el cual es un stream de lectura al archivo de vídeo.

  {
    part: 'status,snippet',
    resource: {
      snippet: {
        title,
        description
      },
      status: { 
        privacyStatus: 'private'
      }
    },
    media: {
      body: createReadStream("temp/video."+mime)
    }
  }

Y montamos el vídeo. Y ya podemos decidir que hacer con los datos.

  youtube.videos.insert({
    part: 'status,snippet',
    resource: {
      snippet: {
        title,
        description
      },
      status: { 
        privacyStatus: 'private'
      }
    },
    media: {
      body: createReadStream("temp/video."+mime)
    }
  }, (err, data) => {
    if (err) res.json({status: "error"})
    else {
      let videoData = data.data
      console.log("Title > ", videoData.snippet.title);
      console.log("Description > ", videoData.snippet.description);
      console.log("URL > ", "https://youtube.com/watch?v="+videoData.id);
      unlinkSync("temp/video"+mime);
      res.json({
        status:"success"
      });
    }
  })

Ahora vamos a crear otra parte importante.

Creamos la Interfaz de Usuario (UI).

Para la interfaz vamos a crear 2 paginas una para autenticar la cuenta y otra para subir el vídeo.

En la pagina de autenticación tenemos que añadir el siguiente enlace, el cual es el que nos devolverá el código para obtener nuestro Refresh Token.

  <a href="https://accounts.google.com/o/oauth2/auth?
client_id=&
redirect_uri=http%3A%2F%2Flocalhost:3000%2FauthSuccess&
scope=https://www.googleapis.com/auth/youtube&
response_type=code&access_type=offline"
>Login With Google</a>

Y en la pagina de Subida creamos el formulario para obtener los datos que pasaremos a la API.

  <input type="text" id="title" placeholder="Video Title">
  <textarea id="description"></textarea>
  <input type="file" id="video">
  <button onclick="upload()">Enviar</button>

Ahora a procesar los datos: Primero vamos a obtener el vídeo cuando cambie en el input.

  <script>
    let fileInupt = document.getElementById('video');
    var file;
    fileInupt.addEventListener("change", ({target})=>{
      file = target.files[0];
    }, false);
    ...
  </script>

Vamos a crear la función para enviar los datos al servidor.

  function upload() {
    //Obtenemos titulo y descripcion
    let title = document.getElementById('title').value;
    let description = document.getElementById("description").value;

    //Creamos un FormData con los datos
    let params = new FormData();
    params.append("title", title);
    params.append("description", description);
    params.append("file", file);

    //Mandamos los datos
    fetch("/upload-video", {
        method:"POST",
        body:params
    })
    .then(res=>res.json())
    .then(({status})=>{
      if(status === "success") alert("Video Subido con Exito");
      else alert("Error al Subir");
    })
  }
  </script>

Y ya tenemos configurado todo. Pero puedes mejorar el código para que funcione a tu gusto.

Saber usar la API de YouTube y todas las de Google te ayudaran a darle mayor rendimiento a tu sitio web. Aprende a usarlas y dominarlas para sacarles el mayor provecho.

Vean un ejemplo extendido usando firebase como base de datos para guardar los datos del vídeo en  mi GitHub. Y para mayor información vayan a la sección de desarrolladores de la API de YouTube.

Comentarios

Entradas populares de este blog

ExpressJS - Crea Aplicaciones Web Robustas y de Calidad

Mejora la reputación online de tu marca - Importancia del sitio web

Diseño mas allá de lo visual - ¿Que es diseño?