Mobile app demo walkthrough generator

Eugene Musebe

Introduction

For any product manager or app developer, it is very easy to record the screen of your latest release. It is also very easy to record yourself as you walk through the application. It is however not easy to combine these two videos together let alone in a presentable manner.

In this tutorial, we demonstrate how to create a demo walkthrough generator for easy updates of your product walkthroughs.

Codesandbox

The completed project is available on Codesandbox.

Github

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

Prerequisites

To be able to follow through with this tutorial, entry-level knowledge of HTML, CSS, and JavaScript is required. Knowledge of VueJs is recommended but not required.

Setup

NuxtJs Installation

NuxtJs is a VueJS framework that provides us with a modular, performant, and enjoyable experience.

To set up our project, run the following command in your preferred working directory:

1yarn create nuxt-app nuxtjs-mobile-demo-walkthrough-generator
2
3# OR
4
5npx create-nuxt-app nuxtjs-mobile-demo-walkthrough-generator
6
7# OR
8
9npm init nuxt-app nuxtjs-mobile-demo-walkthrough-generator

The commands above will trigger a set of questions required to help the utility set up the project. Here are our recommended defaults:

Project name: nuxtjs-mobile-demo-walkthrough-generator

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)

Deployment tools: N/A

What is your Github <your-github-username>

Version control system: Git

You may now navigate to the project and launch it

1cd nuxtjs-mobile-demo-walkthrough-generator
2
3
4yarn dev
5
6# OR
7
8npm run dev

@nuxtjs/cloudinary installation

@nuxtjs/cloudinary is the recommended Cloudinary plugin for NuxtJs. Cloudinary is a media management platform that allows us to unleash the potential of our media assets by providing a powerful API service.

We first need to add @nuxtjs/cloudinary as a dependency in our project

1yarn add @nuxtjs/cloudinary
2
3# OR
4
5npm install @nuxtjs/cloudinary

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

1// nuxt.config.js
2
3export default {
4
5...
6
7modules: [
8
9'@nuxtjs/cloudinary'
10
11]
12
13...
14
15}

We will finally add a cloudinary section in the nuxt.config.js to set configurations for the module:

1// nuxt.config.js
2
3export default {
4
5...
6
7cloudinary: {
8
9cloudName: process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,
10
11secure: true,
12
13useComponent: true
14
15}
16
17...
18
19}

As visible in the codebase above, we are making use of environmental variables. These are sensitive details that we do not want in our codebase. To set up environmental variables locally, we will create a .env file

1touch .env

We will add the Cloudinary cloud name here. If you do not have one, create an account on https://cloudinary.com/. The cloud name will be visible in the console section.

1<!-- .env -->
2
3NUXT_ENV_CLOUDINARY_CLOUD_NAME=<secret-cloudinary-cloud-name>

Template file placement

To generate the final complete file, we are going to make use of a video template. This is a 30-minute video that has no audio and has the background and phone template we require. This will limit our application to generate videos of max 30 minutes. Grab this video here. We recommend creating a folder called nuxtjs-mobile-demo-walkthrough-generator and saving this video with the name iphone_se_template.mp4. This will lead to the video having the public_id nuxtjs-mobile-demo-walkthrough-generator/iphone_se_template.mp4.

Uploading video files

We are first going to create a simple form for selecting the two video files. One is the mobile app video, the other is an instructional video. We are going to place this form in a Form.vue component file.

1<!-- components/Form.vue -->
2
3<form action="#" method="POST">
4
5<div>
6
7<div>
8
9<div>
10
11<div>
12
13<label for="mobile_app_video">
14
15Mobile app video
16
17</label>
18
19<div>
20
21<input id="mobile_app_video" name="mobile_app_video" required="" type="file" />
22
23</div>
24
25</div>
26
27</div>
28
29<div>
30
31<div>
32
33<label for="instructor_video">
34
35Instructor video
36
37</label>
38
39<div>
40
41<input id="instructor_video" name="instructor_video" required="" type="file" />
42
43</div>
44
45</div>
46
47</div>
48
49</div>
50
51<div>
52
53<button type="submit">
54
55Save
56
57</button>
58
59<p v-if="uploadingMobileAppVideo || uploadingInstructorVideo">
60
61Upload in progress
62
63</p>
64
65</div>
66
67</div>
68
69</form>

As indicated in the above code, the submission of the form will be handled by the submit method. Let's see what this method contains:

1<script>
2
3// components/Form.vue
4
5export default {
6
7data() {
8
9return {
10
11uploadingMobileAppVideo: false,
12
13uploadingInstructorVideo: false,
14
15};
16
17},
18
19methods: {
20
21submit(e) {
22
23this.uploadMobileAppVideo(e);
24
25this.uploadInstructorVideo(e);
26
27},
28
29
30
31async uploadMobileAppVideo(e) {
32
33this.uploadingMobileAppVideo = true;
34
35
36
37// Mobile app video file
38
39let file = e.target.mobile_app_video.files[0];
40
41
42
43/* Read data */
44
45const data = await this.readData(file);
46
47
48
49/* upload the converted data */
50
51const resp = await this.$cloudinary.upload(data, {
52
53upload_preset: "default-preset",
54
55folder: `nuxtjs-mobile-demo-walkthrough-generator`,
56
57});
58
59
60
61this.$emit("MobileAppVideoUploaded", resp.public_id);
62
63
64
65this.uploadingMobileAppVideo = false;
66
67},
68
69
70
71async uploadInstructorVideo(e) {
72
73this.uploadingInstructorVideo = true;
74
75
76
77// Instructor video file
78
79let file = e.target.instructor_video.files[0];
80
81
82
83/* Read data */
84
85const data = await this.readData(file);
86
87
88
89/* upload the converted data */
90
91const resp = await this.$cloudinary.upload(data, {
92
93upload_preset: "default-preset",
94
95folder: `nuxtjs-mobile-demo-walkthrough-generator`,
96
97});
98
99
100
101this.$emit("InstructorVideoUploaded", resp.public_id);
102
103
104
105this.uploadingInstructorVideo = false;
106
107},
108
109readData(f) {
110
111return new Promise((resolve) => {
112
113const reader = new FileReader();
114
115reader.onloadend = () => resolve(reader.result);
116
117reader.readAsDataURL(f);
118
119});
120
121},
122
123},
124
125};
126
127</script>

In the above code, we read the files submitted and upload them to the nuxtjs-mobile-demo-walkthrough-generator folder. We also specify an upload preset. These are a set of rules to be used for all uploads. To create an upload reset, proceed to the settings section in your Cloudinary account. Proceed to the upload section. We recommend the following settings:

Unique filename: true

Delivery type: upload

Access mode: public

The above code will upload the files and emit two events. MobileAppVideoUploaded and InstructorVideoUploaded. In the next section, we receive these two events and generate the final video.

Video generation

We will now inject the Form.vue component in the pages/index.vue file and listen for the events:

1<!-- pages/index.vue -->
2
3<template>
4
5...
6
7<Form
8
9@InstructorVideoUploaded="instructorVideoUploaded"
10
11@MobileAppVideoUploaded="mobileAppVideoUploaded"
12
13/>
14
15...
16
17</template>

We will receive the public_id and assign it to local variables. When overlaying videos in subfolders, you need to replace all \ with : as indicated here.

1// pages/index.vue
2
3<script>
4
5export default {
6
7data() {
8
9return {
10
11instructorVideo: null,
12
13mobileAppVideo: null,
14
15};
16
17},
18
19methods: {
20
21instructorVideoUploaded(public_id) {
22
23this.instructorVideo = public_id.replace("/", ":");
24
25},
26
27mobileAppVideoUploaded(public_id) {
28
29this.mobileAppVideo = public_id.replace("/", ":");
30
31},
32
33},
34
35};
36
37</script>

Once the public_ids have been stored in the page state, we will proceed to overlay the two videos on top of the initial video template. To remove the sound from the mobile app video, we add the audioCodec="none" setting.

1<template>
2
3...
4
5<cld-video
6
7public-id="nuxtjs-mobile-demo-walkthrough-generator/iphone_se_template"
8
9width="1000"
10
11crop="scale"
12
13quality="auto"
14
15controls="true"
16
17autoplay="true"
18
19class="m-auto"
20
21v-if="mobileAppVideo && instructorVideo"
22
23>
24
25<cld-transformation
26
27:overlay="`video:${mobileAppVideo}`"
28
29width="405"
30
31height="750"
32
33gravity="center"
34
35x="-385"
36
37y="0"
38
39audioCodec="none"
40
41/>
42
43<cld-transformation
44
45:overlay="`video:${instructorVideo}`"
46
47width="300"
48
49height="300"
50
51gravity="south_east"
52
53radius="150"
54
55x="100"
56
57y="100"
58
59crop="fill"
60
61/>
62
63</cld-video>
64
65...
66
67</template>

Conclusion

With the above code, we have successfully created a mobile demo walkthrough generator. When the product changes, we simply upload the new videos and retrieve the newly compiled video. This just shows the potential of what is possible.

Eugene Musebe

Software Developer

I’m a full-stack software developer, content creator, and tech community builder based in Nairobi, Kenya. I am addicted to learning new technologies and loves working with like-minded people.