Skip to content

Nuxtjs video format converter

In an increasingly video-dependent world, the need for ensuring video format compatibility is increasing. In this video, we explore how we can programmatically change the video format.

The final project can be viewed on Codesandbox.

You can find the full source code on my Github repository.

To follow along in this tutorial. Basic knowledge on HTML, JavaScript, and CSS is required. VueJs knowledge will be helpful but it is not a hard requirement.

We are going to use the create-nuxt-app utility. To use it, make sure you have installed yarn, npx (included by default with npm v5.2+), or npm (v6.1+).

Open the terminal in your working directory of choice and run the following command:

yarn create nuxt-app nuxtjs-video-format-converter

The above command will result in a series of setup questions. Here are our recommended defaults:

Project name: nuxtjs-video-format-converter

Programming language: JavaScript

Package manager: Yarn

UI framework: Tailwind CSS

Nuxt.js modules: N/A

Linting tools: N/A

Testing framework: None

Rendering mode: Universal (SSR / SSG)

Deployment target: Server (Node.js hosting)

Development tools: N/A

What is your Github username? Eugene Musebe

Version control system: Git

You may now enter the project and run it:

cd nuxtjs-video-format-converter

yarn dev

Cloudinary is a media management platform geared at allowing developers to unleash their full potential. We are going to set up the recommended @nuxtjs/cloudinary plugin.

Run the following command in the project folder:

yarn add @nuxtjs/cloudinary
# OR
npm install @nuxtjs/cloudinary
Code language: CSS (css)

Add @nuxtjs/cloudinary as a module in the modules section in the nuxt.config.js file:

// nuxt.config.js
export default {
  ...
  modules: [
    '@nuxtjs/cloudinary'
  ]
  ...
}
Code language: JavaScript (javascript)

To configure our Cloudinary instance, add a cloudinary section in the nuxt.config.js file:

// nuxt.config.js
export default {
  cloudinary: {
    cloudName: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,
    secure: true,
    useComponent: true
  }
}
Code language: JavaScript (javascript)

The above piece of code refers to our environmental variables. These are values that are set in the code’s environment as they are dependent on the environment in which the code is deployed. They can also be used to store sensitive values. Let’s create our .env file:

touch .env
Code language: CSS (css)

After creation, we can now set our environmental variable:

NUXT_ENV_CLOUDINARY_CLOUD_NAME=secret-cloud-name

In order to convert the video, we are first going to upload it to Cloudinary. This is because the video format conversion is all done on Cloudinary’s platform.

Let us create the HTML form that will be used for file selection. As visible below, we ensure that only videos are uploaded.

<!-- pages/index.vue -->
<form @submit.prevent="submit">
    ...
    <input type="file" name="video" id="video" accept="video/*" v-on:change="handleFile" required />
    ...
    <div>
        <p v-if="uploading">Uploading...</p>
        <div v-else>
          <button type="reset">Reset</button>
          <button type="submit">Save</button>
        </div>
    </div>
    ...
</form>
Code language: HTML, XML (xml)

Once the video has been selected, we trigger the handleFile method. In this method, we are going to store the selected file in our state.

// pages/index.vue
export default{
    data(){
        return {
            uploadVideo: null,
            cloudinaryVideo: null,
            uploading: false
        }
    },
    methods: {
        async handleFile(e){
            this.uploadVideo = e.target.files[0];
        },
        async readData(f) {
            return new Promise((resolve) => {
                const reader = new FileReader();
                reader.onloadend = () => resolve(reader.result);
                reader.readAsDataURL(f);
            });
        },
        async submit() {
            this.uploading = true;
            const videoData = await this.readData(this.uploadVideo);
            this.cloudinaryVideo = await this.$cloudinary.upload(videoData, {
                upload_preset: "default-preset",
                folder: "nuxtjs-video-format-converter",
            });
            this.uploading = false;
            ...
        },
    }
}
Code language: JavaScript (javascript)

Once the form is submitted, we prevent submission and send then handle the event ourselves. We use the readData method to create a FileReader instance and get the file data. We then send this data to Cloudinary for storage. We specify the folder to be used for storage as well as an upload preset. This is a set of configurations to be followed when processing the file upload.

To create an upload preset, open the Add Upload Preset page. We are then going to use the following settings:

Name: default-preset

Mode: unsigned

Unique filename: true

Delivery type: upload

Access mode: public

Once the upload is complete, we store the video in the `Cloudinary video local state variable.

Since we are using Cloudinary to convert video formats, we first need to understand which video output formats are supported. We can easily understand this by checking the Supported video formats section in the documentation. We are now going to add the video formats to the form above so that our users can select the format they want to download their video in.

<!-- pages/index.vue -->
<select
    id="format"
    name="format"
    v-model="format"
    required
>
    <option 
        v-for="format in formats"
        :key="format.value"
        :value="format.value"
    >
        {{ format.text }}
    </option>
</select>
Code language: HTML, XML (xml)

The formats variable in the state is an array of all the supported output formats:

// pages/index.vue
export default {
    data(){
        return {
            ...
            format: null,
            convertedUrl: null,
            formats: [
                { text: "FLV (Flash Video)", value: "flv" },
                { text: "HLS adaptive streaming", value: "m3u8" },
                { text: "MPEG-2 Transport Stream (ts)", value: "ts" },
                { text: "MPEG-2 Transport Stream (m2ts)", value: "m2ts" },
                { text: "MPEG-2 Transport Stream (mts)", value: "mts" },
                { text: "MOV", value: "mov" },
                { text: "MKV (Matroska Multimedia Container)", value: "mkv" },
                { text: "MP4", value: "mp4" },
                { text: "MPEG-DASH adaptive streaming	", value: "mpd" },
                { text: "OGV (Ogg Video)", value: "ogv" },
                { text: "WebM", value: "webm" },
            ],  
            ...
        };
    }
    ...
}
Code language: JavaScript (javascript)

Once the user selects their format of choice, we generate the converted URL once the upload is complete:

// pages/index.vue
export default {
    ...
    methods:{
        ...
        async submit(){
            ...
            this.uploading = false;
            this.convertedUrl = this.$cloudinary.video.url(
                this.cloudinaryVideo.public_id,
                { format: this.format }
            );
        }
    }
}
Code language: JavaScript (javascript)

We will use the cld-video component to display the convered video as well as use the convertedUrl to enable video download:

<!-- pages/index.vue -->
<div v-if="convertedUrl">
      <h1>Video convertion complete</h1>
      <p>
        Here is a preview of your converted video. Use the button below to
        download
      </p>
      <cld-video
        controls="true"
        :public-id="cloudinaryVideo.public_id"
        :format="format"
      >
      </cld-video>
      <a
        target="_blank"
        :href="convertedUrl"
      >
        Download
      </a>
    </div>
Code language: HTML, XML (xml)

In the above tutorial, we learn how to convert video formats programmatically. This information is very useful for optimizing our video content when building intensive applications. Feel free to review the entire video transformation documentation to learn what else is possible.

Back to top

Featured Post