The first step is to create a script that will be executed by PhantomJS. This script will do the following:
Next, we want to create a PHP function that actually executes the above script and converts the html to a SimpleXmlElement object.
Finally, running the function from step 3 should result in something like this.
Over the few weeks I’ve been working on a Canvas based side project (more on that soon) that involved cutting a mask out of a source image and placing it on a Canvas. In Photoshop parlance, this would be similar to creating a clipping mask and then using it to extract a path from the image into a new layer. So visually, we’re looking to achieve something similar to:
At face value, it looks like doing this with Canvas is pretty straightforward using the getImageData function. Unfortunately, if you look at the parameters that function accepts it’ll only support slicing out rectangular areas which isn’t what we’re looking to do. Luckily, if you look a bit further in the docs it turns out Canvas supports setting globalCompositeOperation which allows you to control how image data is drawn onto the canvas. The idea is to draw the mask on a canvas, turn on the “source-in” setting, and then draw on the image that you want to generate the slice off. The big thing to note here is that putImageData isn’t effected by the globalCompositeOperation setting so you have to use drawImage to draw the mask and image data.
So concretely how do you do this? Well check it out:
The code is running over at http://symf.setfive.com/canvas_puzzle/grass.html if you want to see it in action.
Anyway, happy canvasing!
Recently I was working on a project where part of it was doing data exports. Exports on the surface are quick and easy – query the database, put it into the export format, send it over to the user. However, as a data set grows, exports become more complicated. Now processing it in real time no longer works as it takes too long or too much memory to export. This is why I’ll almost always use a background process (notified via Gearman) to process the data and notify the user when the export is ready for download. On separate background threads you can have different memory limits and not worry about a request timeout. I suggest trying to not use Doctrine’s objects for the export, but get the query back in array format (via getArrayResult). Doctrine objects are great to work with, but expensive in terms of time to populate and memory usage; if you don’t need the object graph results in array format are much quicker and smaller memory wise.
On this specific export I was exporting an entity which had a foreign key to another table that needed to be in the export. I didn’t want to create a join over the entire data set as it was unnecessary. For example, a project which has a created by user as a relation. If I simply did the following:
I’d end up with an array which had all the project columns except any that are defined as a foreign key. This means in my export I couldn’t output the “Created by user id” as it wasn’t included in the array. It turns out that Doctrine already has this exact situation accounted for. To include the FK columns you need to set a hint on the query to include meta columns to true. The updated query code would look similar to:
Now you can include the foreign key columns without doing an joins on a query that returns an array result set.
Because sometimes it’s just fun to make something absurd: http://taken.setfive.com/.
If you aren’t familiar, the Taken movie series (http://www.imdb.com/title/tt0936501/) is a set of ridiculous action dramas that have acquired a strong cult following over the years (deservedly or not). All of the movies basically involve someone close to a retired CIA agent, played by Liam Neeson, being “Taken” and Neeson subsequently raining hell over anyone involved in wronging him. As a result of the movie series, Liam Neeson has made a formidable run at Kiefer Sutherland’s title of today’s Chuck Norris. Neeson, who plays the main character in the movie employs his signature throat punch in place of Norris’ roundhouse kick.
Our team seems to share a fondness for laughable action movies and actually took the afternoon off to watch the latest Taken 3 film when it debuted a couple weeks ago. With a little bit of vacation downtime prior to the debut and the urge to develop a web application as preposterous as the film series, we came up with the idea of creating Taken Audio MadLibs (http://taken.setfive.com/). For those of you not familiar MadLibs (http://en.wikipedia.org/wiki/Mad_Libs) is a phrasal template word game where one player prompts others for a list of words to substitute for blanks in a story, before reading the – often comical or nonsensical – story aloud.
So our take on the MadLibs program works something like this:
-There are four different “story lines” which all involve dialog between Liam Neesons character and a second character
-Neesons lines are actual lines from the Taken movies
-The other character’s lines are transformed into audio clips by Google’s unofficial Text To Speech (TTS) API and are based on the words you enter into a simple webform
-The lines are combined together into a hilarious back and forth dialog between Neeson and your character
Technically, there really isn’t too much “magic” going on with the program. It’s built on the Symfony2 framework and employs a simple one page parallax scrolling design for the web forms. Once the user submits the web form for their story we send it off to the controller where the user entered words are inserted into a set of templated lines. These text lines are then sent off to the Google TTS API which returns an .mp3 audio file with the audio representation of the text. We then splice together the Google TTS mp3 lines with the Taken audio files that we have stored on the server and combine into one audio file. The audio file is returned to the UI in the form of a HTML5 audio tag where the user can play or download the file. We also provide the user with the option of emailing the audio file to a friend if they would like to.
There were two problems that we ran into worth mentioning for those of you playing around with Google’s TTS api or combining multiple audio files of different formats.
1. Google’s TTS API only accepts 100 characters per call so you’ll have to split a given line or sentence into 100 character chunks and then combine the multiple mp3s back into one. This isn’t too difficult to do but worth mentioning if you ever plan to play around with this API.
2. We did run into a bit of trouble trying to combine the .mp3 files that Google returned with the Taken audio .mp3 files we got from (http://www.soundboard.com/sb/Taken_sound_clips). The problem is that the frame rate of the Google .mp3 files is different than the Taken files so when we tried to combine them into one some audio players would not render the resulting file. To get around these issues we took the following steps the combine and massage the audio files via a couple different server-side Linux-based Audio programs (avconv and oggCat):
Anyways, if you haven’t checked out the final program yet it can be seen here http://taken.setfive.com/ and if you have any questions, comments, or feedback feel free to leave them below.
Posted In: Tips n' Tricks
Last week we officially did a very quiet launch of HotelSaver.io. The concept is fairly simple: You submit your existing hotel reservation, we constantly monitor for price drops, if we find one we notify you immediately and you save money. I had the idea for this site a few months ago when I had made reservations in New Orleans for a bachelor party, then noticed the next day the prices dropped and I managed to save over 40% of the reservation by getting it price matched and discounted. At this point I thought “wow, that was incredibly easy, took little time and saved a ton of money”. Shortly thereafter and shooting it around with everyone here, it was decide we’re going to launch a MVP product and see what the reception is.
With this concept it is really easy to quickly blow it up into a massive product with complex algorithms, payment types, etc. however trying to follow our own advice to our clients we launched with the minimal features to make it useful to the end user: simple reservation monitoring and payment processing to get us paid. We knew the first version of the product would be far from finished in terms of design and feature complete, but we wanted to see if others thought the idea had legs. Here are a few things we did to cut down on the time to launch even more:
We also wanted to get feedback from a small group of users. We posted it on HackerNews and immediately started getting great feedback. We knew posting this on the day we were traveling for the Holidays wasn’t optimal as we couldn’t respond to feedback immediately, we wanted to get this launched. We managed to make it to the front page of HackerNews for a while and instantly had 2,500 unique visitors that day, up from zero the day before! The feedback was great the main points were:
Today we revamped our pricing strategy after the feedback. We knew the upfront cost was most likely a turn away for many users but didn’t know what percentage would hate it. After reading the feedback on the post and numerous emails, we’ve switched to a 20% of the amount saved. This makes it 100% risk free to the user. We won’t make money unless you save money. If we save you $100 dollars, you get $80 of it. We’ll be next week working on promoting the revised pricing strategy to see what additional feedback we can get as well as addressing the other parts of the feedback.
We’ll be trying to keep everyone updated on our adventures of launching our own product in house. We’re excited to try some techniques we’ve seen over the years and testing them out ourselves as well as trying some new ideas. If you have any feedback let us know!