One Tuesday evening I was out by the beach trying to get some nice looking drone footage. I got a clip that looked pretty good (given the lighting conditions) and tried to upload it to my Instagram story. However, I wanted to apply an effect to it, which turned out to be impossible. Thus begins my quest to make my own effects.
Around two weeks later, I got bored and decided to actually make my own effects. The real way to create Instagram-supported effects is through Spark AR, a piece of software used for AR and other effects. Here’s an example of what it looks like, using my drone photo as the sample image.
Not bad, right? I thought the problem would be solved there. However, once I tested it out in the app, I found that I still couldn’t use existing media, even though I checked the box that says “allow existing media.” So, there’s no way to allow existing media through the effects, and I had to figure out another way. Lucky for me, Python exists.
At around 2 AM, having just finished a few games of Valorant (priorities), I did some research on how to:
- Import an image
- Get the date and time metadata from the image
- Add the text with date and time to the image
- Export the image
Since this uses images (big surprise), I started by using Pillow (Python Imaging Library). This allowed me to open an image, extract the metadata, add text, and export the image. So that’s it! One simple Python module and all my problems are gone! It took less than two hours, and I have a working effects creator!
Here are four examples of the effect:
Except… it only works on my computer. What if I want to use it on my phone?
Time to make a website!
I looked up “deploy python script as web app” and clicked the first result. Okay, guess I’m going to be using Flask! This is where the problems started. I used this guide from Real Python to get started, and I got a website up and running pretty quickly. Next, I had to figure out how to have users import their own images. I found this nice post about handling file uploads from Miguel Grinberg which may have saved my life. It does some pretty cool stuff with the file stream to check file extensions, file size, and more. I also had to import more stuff such as Flask (obviously) and Werkzeug (for file handling). After this, the site was working! Around this time I added a feature to delete all uploads and exports upon refresh, so the folders where the images were wouldn’t get clogged. Next up, deploying the site!
Deploying the site
The same guide from Real Python deployed their example site using Google Cloud, so that’s what I went with. I went through the entire setup and got the website online! However, due to how I handled my files, I would get an error every time I uploaded a file to the site. The process for my website is this: put uploaded images in the “uploads” folder, access image from that folder, and write new images to the “exports” folder. Due to security reasons, Google Cloud does not have write access to my files. (This is super reasonable, and it’s generally good practice to use a database or something else instead.) So, I created a database.
I started by using MySQL to store image file names and image data, but one thing led to another and I had to activate a bunch of cloud software and other things I won’t go into. I decided to ditch that effort (for the time being) and figure out another way to deploy it. This is fine to be for a few reasons:
- I’m probably going to be the only person using it anyways; there’s no point in having a 10GB database for one person’s photos (that will be deleted after download anyways)
- Because I’m probably going to be the only person using it, writing straight to the files won’t be a security threat
I researched a few other ways to host a site, and suddenly remembered what I used to host my Discord bot: repl.it!
I created another environment for the script in a new repl.it and added the necessary files. One new issue I ran into was the date and time would be in UTC and not my local timezone. This was fixed by importing datetime and subtracting the time offset manually (I tried a solution with location-aware timezones with pytz, but that led to different problems). Sometimes stuff would randomly break and then fix itself, but that was mostly because of packages in repl.it not loading properly. I managed to get this website to stay on all (most of) the time because of a free Hacker plan (thanks for the .edu email, UCLA). It should be up at effects.willhsieh.com unless something has gone wrong or I decide to take it down. You can find the GitHub repo here.
What I learned
Oh boy, the last two(? three?) days have been quite interesting. First thing: Python is very cool (especially for quick projects like this). It’s amazing to spontaneously decide “I’m gonna make something” and have it be done two hours later. Second thing: web deployment/cloud services are complicated. Even though it didn’t end up working the way I wanted it to, getting some hands-on experience with Flask, Google Cloud, and MySQL is completely worth the learning experience. Third thing: alternatives have its trade-offs. The ideal solution would have been to deploy the site with a database, but due to time constraints repl.it was what I went with. In the long term, the scalability isn’t that good, and repl.it has its own problems. (Actually, the ideal solution would’ve been to just have Spark AR work properly. Still sad about how existing media can’t be used.)
And as always,
thanks for watching relevant xkcd.