It took me two years of work to create my dream app. It's on the Google Play Store here, for now at least. The vision was clear, as were the motivations. To create an app that allows a userbase to predict the final score of a sports game, on an active "leaderboard" type of "Buddy List." This way, you could interact with friends in a light-hearted way in terms of who really knows what they're talking about before Sunday's Bears-Packers game.
I completed all work by myself, without help from anyone else. The first step was to create an LLC, just incase I were to receive investor interest. Then I weighed options to host the web application.
Over the two years it took to complete the app, I used Bluehost and BuyVM. Bluehost is helpful for a beginner, because they lay out the backend architecture of your site with a friendly GUI and set of menus. BuyVM requires more know-how and I wouldn't have been able to complete the setup without the knowledge I gained over the course of my tenure as a sys admin/ web app dev at a University.
In terms of the actual code writing, the most difficult aspects were the front-end interface and UX, the Leaderboard, the login mechanisms, and the overall design. I went through several iterations of the forward-facing markup before I settled on the W3.css I used for the PWA version of the app.
The backend scripting was all just written freestyle. The Leaderboard was the most challenging aspect and I actually legitimately failed trying to write it once. After a took a couple of months off I returned with a clearer vision for the Leaderboard and was able to complete it.
The app is heavily automated and updates on a single script execution that I do manually. The app would be fully automated if I were to pay for a service to put the final scores into a text file for me, but for now I do it myself. Once the scores are in the text file I just execute a single script and that updates the Leaderboard. As for building the app, it's also just a single script that completes that based off of the NFL Schedule as stored in a CSV.
I guess this puts a nail in the coffin into any conversations about, "I will create an app and become a millionaire." Hardly. I lost money making this. This should also put nails into the coffin on "portability." I wrote this app and ported it everywhere, from Ubuntu to Mac to Windows 10 to CentOS, building on production servers, and local machines regularly.
The two years I spent building this free application wasn't a total waste of my time. Over the course of creating the pages I studied Linear Algebra by myself and came to understand n-dimensionality in a proper fashion. I used a book I'd highly recommend by I.M. Gel'fand called "Lectures on Linear Algebra" and found it was quite useful and relevant to the idea of manipulating a creative idea in hyperspace. Had I not challenged myself, I would be less enriched.
Showing posts with label bash. Show all posts
Showing posts with label bash. Show all posts
Sunday, November 24, 2019
Sunday, July 9, 2017
Blending videos with bash (imagemagick, ffmpeg)
Years ago I was trying to figure out "batch processing." This refers to the concept of applying a single transformation to an entire set of files with one command. Specifically, I wanted to combine two videos, matching frame-by-frame, and blend the two videos together.
The software you'll need to complete this is ffmpeg and imagemagick. Both are CLI softwares you can install via Cygwin, or MacPorts. This is much easier to do via MacPorts, but if you're on Windows, it's not impossible. I was able to install both on an offline Windows 10 box.
To demonstrate what will happen, I'm going to show a single frame as an example:
This is a blended image, the result of two images composed with an imagemagick CLI command into a final result. To achieve this you run:
$ magick composite -gravity center -blend 30x70% strawberry.png banana.png combo.png
Now, the concept for video, is to blend two videos together, matching frame-by-frame, so that if two 60 fps videos are both 2 seconds in length, you'll blend 120 frames from each into 120 final, blended frames. The concept of completing this task with a single command is what's referred to as "batch processing."
For the code snippets, let's consider "Clouds" and "Flowers" instead of Strawberry and banana, for now...
1. First gather some info about our video, we run:
ffmpeg -i Clouds.MOV
Metadata:
major_brand : qt
minor_version : 0
compatible_brands: qt
creation_time : 2019-07-02T21:32:31.000000Z
com.apple.quicktime.make: Apple
com.apple.quicktime.model: iPod touch
com.apple.quicktime.software: 12.0
com.apple.quicktime.creationdate: 2019-07-02T17:32:31-0400
Duration: 00:00:05.67, start: 0.000000, bitrate: 15449 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080, 15369 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
So we have 29.98 fps, let's round up to 30 fps
To get the frames we run:
ffmpeg -i Flowers.MOV -vf fps=30 Flowers_frames/Flowers%03d.jpg -hide_banner
...and the same for the Clouds
Then to compose them into the final frames we just run this:
$ for i in $(seq -f "%03g" 1 170); do magick composite -blend 50x50% "Clouds_frames/Clouds"${i}".jpg" "Flowers_frames/Flowers"${i}".jpg" "Combo_frames/Combos"${i}".jpg"; done
Now that we have the final composed frames, we reanimate these frames into a video with this command:
$ ffmpeg -r 30 -f image2 -s 1920x1080 -i Combo_frames/Combos"%03d".jpg -vcodec libx264 -crf 25 -pix_fmt yuv420p Combo.mov
Note that %05d refers to the length of the largest digit as 5, i.e. 11568 and so all numbers will be padded with the appropriate amount of zeroes to match this length (i.e. 20 becomes 00020), and all filenames will be of the same length. This is so ffmpeg doesn't confuse frame ordering during rendering.
Lastly, you can take the original video's audio and the composed and rendered video and combine those... offsetting the video by .10 seconds (for a better sync)...
ffmpeg -itsoffset 0.1 -i video.mp4 -i original.mp4 -c copy -map 0:v:0 -map 1:a:0 final.mp4
Where video.mp4 is the rendered psychedelic version and original is the original (with audio). The offset component " -isoffset" is applied to the "-i .mp4" that comes directly after it.
That concludes this tutorial. If you have any questions, I'd be glad to answer them. Good luck!
And that's it. I'll post a demonstration once I film the videos properly.
The software you'll need to complete this is ffmpeg and imagemagick. Both are CLI softwares you can install via Cygwin, or MacPorts. This is much easier to do via MacPorts, but if you're on Windows, it's not impossible. I was able to install both on an offline Windows 10 box.
To demonstrate what will happen, I'm going to show a single frame as an example:
This is a blended image, the result of two images composed with an imagemagick CLI command into a final result. To achieve this you run:
$ magick composite -gravity center -blend 30x70% strawberry.png banana.png combo.png
Now, the concept for video, is to blend two videos together, matching frame-by-frame, so that if two 60 fps videos are both 2 seconds in length, you'll blend 120 frames from each into 120 final, blended frames. The concept of completing this task with a single command is what's referred to as "batch processing."
For the code snippets, let's consider "Clouds" and "Flowers" instead of Strawberry and banana, for now...
1. First gather some info about our video, we run:
ffmpeg -i Clouds.MOV
Metadata:
major_brand : qt
minor_version : 0
compatible_brands: qt
creation_time : 2019-07-02T21:32:31.000000Z
com.apple.quicktime.make: Apple
com.apple.quicktime.model: iPod touch
com.apple.quicktime.software: 12.0
com.apple.quicktime.creationdate: 2019-07-02T17:32:31-0400
Duration: 00:00:05.67, start: 0.000000, bitrate: 15449 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080, 15369 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
So we have 29.98 fps, let's round up to 30 fps
To get the frames we run:
ffmpeg -i Flowers.MOV -vf fps=30 Flowers_frames/Flowers%03d.jpg -hide_banner
...and the same for the Clouds
Then to compose them into the final frames we just run this:
$ for i in $(seq -f "%03g" 1 170); do magick composite -blend 50x50% "Clouds_frames/Clouds"${i}".jpg" "Flowers_frames/Flowers"${i}".jpg" "Combo_frames/Combos"${i}".jpg"; done
Now that we have the final composed frames, we reanimate these frames into a video with this command:
$ ffmpeg -r 30 -f image2 -s 1920x1080 -i Combo_frames/Combos"%03d".jpg -vcodec libx264 -crf 25 -pix_fmt yuv420p Combo.mov
Note that %05d refers to the length of the largest digit as 5, i.e. 11568 and so all numbers will be padded with the appropriate amount of zeroes to match this length (i.e. 20 becomes 00020), and all filenames will be of the same length. This is so ffmpeg doesn't confuse frame ordering during rendering.
Lastly, you can take the original video's audio and the composed and rendered video and combine those... offsetting the video by .10 seconds (for a better sync)...
ffmpeg -itsoffset 0.1 -i video.mp4 -i original.mp4 -c copy -map 0:v:0 -map 1:a:0 final.mp4
Where video.mp4 is the rendered psychedelic version and original is the original (with audio). The offset component " -isoffset" is applied to the "-i .mp4" that comes directly after it.
That concludes this tutorial. If you have any questions, I'd be glad to answer them. Good luck!
And that's it. I'll post a demonstration once I film the videos properly.
Subscribe to:
Posts (Atom)
How I wrote/recorded my album "Disposable" (2025)
Click to listen on YouTube, out now!! This blog post will attempt to fully encapsulate as much of the writing/recording/mixing process of th...
-
Recently I was in conversation with someone about music royalties. I mentioned I wrote some music I'm excited about, because I believe i...
-
I used this phone for about two years, and it solved a major issue for me. It was simple. I used to like to drink on the weekends, and this ...
-
The venue was too cramped for a sold out show. Floor was sloped downwards-- seemed like a safety hazard. Stairs to theatre seating were too ...


