To mark the end of 2016 we launched a new website project, which we've been working for a few months. This is not a conventional website, but an online video generator. This post is about the tech recipes, and how we engineered the systems.
Requirement in a nutshell:
Our client organise events on different locations (Busan, Tokyo, Hawaii) where the event participants would take photographs and compile them in to a video to share with others. The system has templates which are used to compile videos, and has placeholder where a user can upload photos or write text in to for a video. The videos once compiled get uploaded to Youtube, and the users gets an email notification with the video link.
We used a few technologies to come up with a solution. The stack we used is the following.
- SilverStripe CMS / Framework 3.5.1
- Adobe After Effects
- Adobe After Effects XML (AEPX)
- Amazon S3
- SilverStripe Fluent Module
We made extensive use of the AEPX files. These are XML versions of the adobe after effects files. Being XML we could open these files in a text editor. However there were super complicated hash codes, elements etc. We wrote a parser in PHP to read through an AEPX file and fine patterns of strings which denotes codes for placeholder texts and images. (a text placeholder would be PH_TEXT_001, and an image placeholder would be PH_IMAGE_001). Once these XML elements are read out of the the system saves them in a sequence, and in to data objects (records) in SilverStripe.
We made objects with respect to these objects to save the user submitted data. We had a Video Compilation class, Image Upload class, and Text Upload class. These keeps a submissions on a session and collects data from users. The JourneyStep object was used to make a user journey, and a step by step form. So when a user starts making a video it gives them fields to upload images, texts in combination, and to provide them with a multi-step form. On the last step the submission is saved in to a state called, Completed which a cron job is picking up, and using the AEPX file and the actual submitted data the cron job renders the video.
Selecting servers was a tricky one for us. We had several requirements which we needed to meet, also because of After Effects a few compromises had to be made.
- We wanted to use an CentOS NGINX / PHP-FPM recipe for the web servers
- After Effects only works on Windows servers
- Various cron jobs were there for uploading videos to youtube, messaging users etc.
After a lot of discussions, brainstorm sessions, we came up with a server set up like the following.
The trick was to use one single RDS and have different servers contacting that RDS for data. Each cron instance would read data from the RDS and perform cron actions. Like compiling videos, uploading videos to Youtube, sending out emails to users. We had to face a several issues with
- How do we manage the data, (a compiled video was going to be up to 12 GBs)
- Handing high resolution images
- Editing and cropping images on the client side including mobile devices
- Handling EXIF data for images, and rotate them as needed.
The combination of the servers ran without issues with properly synced cron jobs which ran periodically. The final system generated videos for a user and uploads the videos between 22 - 30 minutes, and email the users. Which was fairly a good response time when we consider the time it takes to compile a video.
CMS & Final Product:
Here are some screenshots of the final CMS product.
This is an example video generated by the system.