😣 The problem with current tech
Have you ever wanted to upload a video presentation/teaser of your app online but it looks too plain. Maybe you just wanted to add a gradient or throw in some background music. The only way is to install expensive or resource-heavy overkill video editors, or rely on some sort of online editor that asks you for a premium plan to export without a watermark.
Well, no more!
Introducing Mockoops 📱
Mockoops is an online mockup-tool which allows you to just drag-drop your screen recordings, choose a template, throw in some background music, all previewing everything right in your browser.
Here's an introductory video
Here's how you'll create a video from scratch.
Useful Links ⚙️:
Here's what Mockoops calls home:
🌐 Website: https://mockoops.mohitya.dev
Current Templates 🌈
Mockoops comes with a bunch of templates right out of the box! They are very responsive, customisable and diversified for each of your motion-graphics video need. Some of them are here:
📐 Angled Presentation
This template is idea for long-form content to make it more appealing (and possibly less boring too!). Here's a quick Showdown
⚡️ Quick Teaser
This one is great for quick teasers that start out by build anticipation in the begenning, revealing only certain part of the input video at first, and slowly reveal the entire thing.
Here's me, using it for Pckd's reveal
💻 Laptop Zoom
This one is for the more lo-fi people out there. This template lets you present your video on a moving MacBook screen on a beautiful workstation background. This could be used with non-screen recorded stuff as well!
📚 Text Reveal
This one is for short announcements or reveals. Most suitably when you just have one screen for an app and you want to tease the coming soon status!
Or it could even be used for things like the release of a new version of a product. The possibility with this one are endless
🎭 Rotate Title
This one is well suited for use-cases where you need to present some text before a video, while not having to setup any fancy stuff
With this, the templates end for now. I have a lot in mind as to what to add next. But considering the tight schedule for this hackathon, I'll have to keep that for later.
Mockoops comes packed with awesome features you're gonna love
⚡️ Distributed Rendering Using Serverless (Remotion Lambda)
This portion is explained in later sections
Blazing fast exports
Preview videos right in the browser, then export with a single click
🧩 Responsive Video Templates
Unlike any other video ediors like After Effects, or Jitter, Mockoops has responsive video templates so that you could export videos with any dimension you'd want.
Mockoops even works in offline environments (preview mode).
🍰 Keyboard Shortcuts
Since the app was created with user-friendliness in mind, keyboard shortcuts were on the priority when assigning actions to buttons. Here's how power-users could utilize shortcuts to render video without touching their mouse.
How it works ⚙️
Mockoops uses Remotion for the rendering.
Here's what remotion is
in 100 seconds
tl;dr It's basically a way to create videos programatically with React. It allows developers to create responsive and absolutely positioned
I used my go-to tech stack for this one. Since Linode could run any technology you'd want, you're free to choose. I went with:
- NextJS - Because it's one of the best frontend JS Frameworks
- Remotion - For the video and rendering
- Linode S3 Storage - For quickly storing uploaded video files in storage buckets
- Sass - For making the app look beautiful
- MongoDB (w/ Linode) - For caching renders with the same input params
- React Recoil - For app-wide state management
- React Hot Toast - For the notifications
- React Confetti - For the joyous animations
- React Dropzone - For handling advanced drag-drop animations
The birth of an idea
The app idea The app idea actually came out of the need for creating/building presentable screen-recordings, for announcing my new projects on twitter.
Apps that do the beautifying and presentation part exist for Images (like pika.style), but none for videos. So, it was obvious I had to fill the void.
As every other developer who tries to design, I'm not too good with designing things on my own. I usually browse websites like Dribbble to get inspiration for User Interfaces.
I also usually have the plan in mind on how the app flow would be like. This makes the process much more simpler, and I could concentrate on one part at a time.
(Detailed description... soon)
Care has been heavily focused on in this project. Unlike most hackathon submissions, I plan to use it very frequently, and so, the code was written with maintainability in mind.
(Detailed Description coming soon)
The GitHub commit messages are a joy to read as well, in case you're wondering
Linode played a major role in most aspects of the application. Here's how.
How Mockoops achieved blazing-fast Renders ⚡️
Usually, video processing happens through an API on the same server as the backend. In the traditional way, it would apply to Linode, by having a virtual machine, which runs the NextJS server through an Nginx proxy, with API endpoints to render and get progress.
However, this approach would be highly inefficient and non-scalable in case 50 people render at the same time. Though the server would be able to serve the frontend, the backend would not be able to handle this rendering workload.
This is where serverless comes into play. By leveraging the power of serverless, Mockoops could have a thousand concurrent users, all rendering at the same time while not having to compromise on any part of the application performance.
This is especially useful for maintaining the super-fast response times of Mockoops, while not having to deplete the monthly transfer costs. This also makes Mockoops compatible with the micro-services architecture, where the frontend is one service, the backend another, and the rendering engine to complete the architecture.
🏕 Quick deployment of VM nodes
With Linode, I was able to get Mockoops from development to production within minutes. I even setup an Nginx Proxy Pass and added an SSL certificate. Though it's not as easy as something like vercel, etc. and there's a learning curve, once you get the hang of linux commands, it's much better since you have all the control you could have over deployments.
Domain management using Linode 🚦
Linode also allows for easy domain management for free (until you have at least one VM). Unlike the registrar's nameservers, updates propagated through the DNS instantly as soon as they were edited from the console.
I probably don't need this very often, but with this project, it was crucial. Since the rendering infrastructure was open to anyone, and engineering a protection system to prevent repetetive renders was not possible, the application was vulnerable to DDoS exploits.
I know this is thinking too far, but one of my friends actually got DDoS'ed very recently on a hackathon submission. His project was down for a very long time and his hosting bills probably touched the clouds.
This is where Linode's built-in DDoS protection comes into play. It automatically notifies when repetitive queries are being sent to the same service and if it detects some level of exploitation. Though it's not perfect, I could enjoy peace of mind at no extra cost.
💭 What I learnt during this hackathon
Learning is the main driving factor behind hackathons! Mockoops has been lesser of a web application and more of a teacher to me. To sum it here, here's what I learned:
Optimization: Long-term Caching 😎
Through a limited pre-alpha testing I did with some people for this app, I found out that most just pressed
render on the video templates without changing any parameter. This meant that most of the renders were exactly the same.
This was a huge opportunity to save cloud costs. I just needed a way to identify each render uniquely. This was done through non-cryptographic hashing.
If you don't know already, a hashing function is a function which takes in an input of arbitrary length, and produces a fixed-size output based on the input. Even when the input is slightly changed, the resulatant output string is totally different. Hashing is used mainly for securing password storage, along with salting, etc.
Hashing was particularly useful for my use-case, since the input props to the video could be given as the input to a hashing function (SHA-256 in this case), and it would produce a hash which would act like an ID for the video. If the hash of two video requests is same, it means the same is exact video is being requested. Therefore, it is very efficient to serve the already-rendered video.
Using this method, I was able to decrease the render requests by a large factor, while also making the user interface better. In hindsight, it was well worth the 3 days setting up rendering infrastructure took me.
Serverless Computing 🥂
I was always fascinated by serverless and the JAM stack, but this project took it to another level. Using Remotion Lambda, I was able to deploy pre-built functions across different regions around the globe, and scale on demand.
With serverless functions, serverless sites was another thing I never though of, which came out to be a crucial requirement to access the serverless functions through an API. It taught me about scaling massively, the cold-start problem, caching, cache-invalidation, and a lot more.
Video Rendering 🎬
Setting up the rendering process was a nightmare. Since the videos are rendered on a serverless architecture, the initial setup was much more complicated that normal server renders. Also, Mockoops needed to show a progress bar for each render for a better User Experience.
I first though about client side rendering. However, it was not feasible since browser has to process the video in real time and if there are some interruptions, they are recorded as well, and the final video is not as smooth. It also takes twice the length of video to render, which is not ideal for a good user experience.
Therefore, I had to resort to client side rendering, as the remotion community had too. This meant hosting the infrastructure to render and store videos, which in itself was a challenge, but Linode user-friendliness made the process less painful and more of a joy.
It also taught me about FFMpeg and how it works behind the scenes. Remotion Lambda opens up the video in a Chromium browser controlled using puppeteer. It goes through each frame and dleays the renders until a video/image has loaded. It then takes a screenshot of the window.
This happens for all frames in the video. Finally, they are attached together using FFMpeg, which is an awesome tool I didn't know of before.
I learned how to convert a video from
gif without having to rely on online solutions
🦸 Challenges and how I overcame them
This project was supposed to be an easy build, but oh boy, what an understatement!
Mockoops was no less that a roller-coaster. Though it taught me some valuable lessons.
Software Incompatibility ☹️
It was hard to make remotion compatible with the latest versions of NextJS, since react 18 made significant changes in the browser rendering process and also changed some things from the ground-up. Though remotion had been tested against React 18, I'm afraid not so with NextJS 12.
So, every now and then I was getting ambiguous error messages that I had no idea how to fix, and the solutions online seemed to make no difference. After much struggle and avoiding to downgrade my React and NextJS versions, I had to finally downgrade to React 17 and NextJS 11. It took me 2 days of debugging and finally having enough to make the switch.
Since downgrading, I haven't faced any silly error message and everything worked exactly like I wanted to.
Lesson learnt: Never hesitate to downgrade your tech stack versions if it is hampering too much with progress. The change would probably be very in-significant (unless ofcourse new features aren't a business requirement).
🤗 Run your own version of Mockoops!
Want to tinker with Mockoops? Want to add a template? To setup your own instance of Mockoops, read the docs over on the GitHub repo
🛣 Future Roadmap
Mockoops could be made better by:
- Adding more exciting templates (since I'd probably use this very frequently, I'll add a lot overtime)
- Dynamically uploading serverless functions when a template change is detected: Currently, all templates are uploaded to serverless environments, and different videos are altered based on different input requirements.
- Adding Cypress tests to validate if newly added templates survive edge cases (like rendering fallback if the video is removed)
😎 Summing it up
This is one of the longest blog posts I've written, since I wanted to summarize the entire process.
Mockoops has been a journey of creating a vision to reality. Though there were some bumps and even speed-breakers, I finally managed to get it through the tunne... Well the analogy went too literal. 😅
This was one of my first experiences launching a product (on product hunt as well, soon), and it sure was hell of a fun one!
🤗 Thank you!
If you've reached this far, I'm grateful that you read the article. I'm excited for the results and the prices (since I'm saving up for college). Till then, later!
Did you find this article valuable?
Support Mohit Yadav by becoming a sponsor. Any amount is appreciated!