Skip to content

RESOURCES / BLOG

Video trimming using Nuxt.Js

Video trimming is a common task nowadays as it is now the preferred media for content sharing. Short videos have taken the world by storm. Let us learn how to trim short videos from long videos programmatically as this is a requirement for interactive platforms.

The final project can be viewed on Codesandbox.

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

Knowledge of HTML, CSS, and JavaScript is required to follow along with this article. Knowledge of Vue.Js is recommended but not required.

[Nuxt.Js](http://nuxtjs.org is an intuitive Vue.Js framework that boasts being easy to learn and master. We will use it to improve our productivity and developer experience.

We will use the create-nuxt-app utility. Ensure you have yarn installed or npm v5.2+ v6.1+.

Open your terminal in your preferred working directory:


yarn create nuxt-app nuxjs-video-trimmer

# OR

npx create-nuxt-app nuxjs-video-trimmer

# OR

npm init nuxt-app nuxjs-video-trimmer

Code language: PHP (php)

This will trigger a set of questions required to customize your installation. Here are our recommended defaults:

Project name: nuxtjs-video-trimmer

Programming language: JavaScript

Package manager: Yarn

UI Framework: TailwindCSS

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: <your-github-username>

Version control system: Git

Once the setup is complete, feel free to enter and run the project:


cd nuxtjs-video-trimmer

  

yarn dev

# OR

npm run dev

Code language: PHP (php)

Your application will now be running on http://localhost:3000

Cloudinary is a media management platform that enables us to make the most out of our content via their comprehensive and powerful APIs and SDKs.

To install the recommended Nuxt.Js plugin, @nuxtjs/cloudinary open the terminal in your project folder. Run the following command:


yarn add @nuxtjs/cloudinary

# OR

npm install @nuxtjs/cloudinary

Code language: CSS (css)

Add it to the modules section of nuxt.config.js:


// nuxt.config.js

export  default  {

...

modules: [

'@nuxtjs/cloudinary'

]

...

}

Code language: JavaScript (javascript)

Add cloudinary section in nuxt.config.js to configure our instance:


// nuxt.config.js

export  default  {

...

cloudinary: {

cloudName:  process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,

useComponent:  true

}

}

Code language: JavaScript (javascript)

In the above configuration, we refer to the NUXT_ENV_CLOUDINARY_CLOUD_NAME environmental variable. Environmental variables are variables we configure in our development environment instead of in our codebase. This is because they are dependent on the environment our code is deployed in or even are too sensitive to be in our code repositories.

To obtain our Cloudinary cloud name, open your dashboard. If you don’t have an account you can register here. It should be visible in the Account Details section.

We will store our environmental variables in the env file. Let’s create one:


touch .env

Code language: CSS (css)

Add your cloud name:


<!-- .env -->

NUXT_ENV_CLOUDINARY_CLOUD_NAME=<secret-cloud-name>

Code language: HTML, XML (xml)

Before we trim the video, we will upload it to the Cloudinary platform. Let us create an upload component.


touch components/Upload.vue

Let us create an HTML form to upload the video:


<!-- components/Upload.vue -->

<template>

<div class="mt-12">

<form

action="#"

method="POST"

@submit.prevent="submit"

>

<div>

<label for="file">File</label>

<div>

<input

accept="video/*"

@change="handleFile"

type="file"

name="file"

id="file"

/>

</div>

</div>

<div>

<p v-if="uploading"  >

Uploading...

</p>

<button v-else  type="submit">

Upload

</button>

</div>

</form>

</div>

</template>

Code language: HTML, XML (xml)

When a file is selected, we trigger the handleFile method. This method saves the selected file in the component state


// components/Upload.vue

<script>

export default {

data()  {

return {

...

uploadVideo: null,

};

},

methods: {

async  handleFile(e)  {

this.uploadVideo  =  e.target.files[0];

},

...

},

};

</script>

Code language: HTML, XML (xml)

This prepares the file for upload. When the file is submitted, we trigger the submit method. This uploads the file to Cloudinary and emits the uploaded method:


<script>

export default {

data()  {

return {

uploading:  false,

...

};

},

methods: {

...

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-trimmer",

});

this.$emit("uploaded", this.cloudinaryVideo);

this.uploading  =  false;

},

},

};

</script>

Code language: HTML, XML (xml)

Once the event is emitted, it is received in the index file.


<!-- pages/index.vue -->

<template>

...

<upload  v-else  @uploaded="storeVideo" />

...

</template>

Code language: HTML, XML (xml)

The uploaded event is handled by the storeVideo method:


// pages/index.vue

<script>

import Upload from "../components/Upload.vue";

...

export default {

components: {

Upload,

...

},

data()  {

return {

uploadVideo:  null,

};

},

methods: {

storeVideo(video)  {

this.uploadVideo  =  video;

},

},

};

</script>

Code language: HTML, XML (xml)

We will create a Trimmer component to handle our trimming logic:


touch components/Trimmer.vue

Once created, let’s inject the Cloudinary video instance into the component:


<!-- pages/index.vue -->

<template>

...

<trimmer

v-if="uploadVideo"

:video="uploadVideo"

/>

<upload

v-else

@uploaded="storeVideo"

/>

...

</template>

Code language: HTML, XML (xml)

// pages/index.vue

<script>

...

import Trimmer from "../components/Trimmer.vue";

export default {

components: {

...

Trimmer,

},

};

</script>

Code language: HTML, XML (xml)

Let us display basic information about the video:


<!-- components/Trimmer.vue -->

<template>

...

<cld-video

:public-id="video.public_id"

/>

...

<ul>

<li>Video format: {{ video.format }}</li>

<li>Duration: {{ video.duration }} Seconds</li>

</ul>

...

</template>

Code language: HTML, XML (xml)

To obtain the start and stop timestamps for the trimmed video, let’s create an HTML form:


<!-- components/Trimmer.vue -->

<template>

...

<form @submit.prevent="trimmed = true">

...

<input

min="0"

step="0.01"

:max="stop"

placeholder="Start"

type="number"

name="start"

v-model="start"

id="start"

/>

...

<input

type="number"

:min="start"

step="0.01"

:max="video.duration + 0.1"

placeholder="End"

v-model="stop"

name="end"

id="end"

/>

...

<button type="submit">Trim</button>

...

</form>

</template>

Code language: HTML, XML (xml)

When the form is submitted, trimmed is set to true. This will render the trimmed video and a download button. Let us see the code that enables it:


// components/Trimmer.vue

<script>

export default {

props: {

video:  {

required:  true,

type:  Object,

},

},

data()  {

return {

start:  0,

stop:  this.video.duration,

trimmed:  false,

};

},

computed: {

trimmedUrl()  {

return this.$cloudinary.video.url(

this.video.public_id, {

start_offset:  this.start,

end_offset:  this.stop,

format:  "mp4",

});

},

},

};

</script>

Code language: HTML, XML (xml)

We can now render the trimmed video and download button:


<cld-video

autoplay="true"

v-if="trimmed"

:public-id="video.public_id"

controls="true"

>

<cld-transformation

:end-offset="stop"

:start-offset="start"

/>

</cld-video>

<div v-if="trimmed">

<a target="_blank"  :href="trimmedUrl"  >Download</a>

</div>

Code language: HTML, XML (xml)

We are now able to trim our videos seamlessly without the need for a complex setup. To see what more we can do with our media, feel free to check out the Cloudinary documentation.

Start Using Cloudinary

Sign up for our free plan and start creating stunning visual experiences in minutes.

Sign Up for Free