How to Extract and Play Part of an MP3 in PHP

One of the sites I manage, Late Night Record Pool, has been having bandwidth issues as of late. They enjoy roughly 8,000 unique visits a month, and with the ability to preview any song or video in their extensive library, the bandwidth adds up fast. We didn’t want to give up this awesome feature to the site, but we had to do something. So, I decided to try and come up with a way to just preview the songs, sending out only a fraction of the bandwidth every time.

There are tons of classes and programs that offer up the ability to extract a section from an MP3, but they all require you to save the file before using it. That’s a good method, but with a library of music approaching two terabytes, suddenly adding a preview-version of every song would not be feasible. I had to come up with a way on my own to do it on the fly.

$getID3 = new getID3();

$id3_info = $getID3->analyze($filename);

list($t_min, $t_sec) = explode(':', $id3_info['length']);
$time = ($t_min * 60) + $t_sec;

$preview = $time / 30; // Preview time of 30 seconds

$handle = fopen($filename, 'r');
$content = fread($handle, filesize($filename));

$length = strlen($content);

if (!$session->IsLoggedIn()) {
	$length = round(strlen($content) / $preview);
	$content = substr($content, $length * .66 /* Start extraction ~20 seconds in */, $length);
}

header("Content-Type: {$id3_info['mime_type']}");
header("Content-Length: {$length}");
print $content;

Note: the site from which I’m pulling this example also uses the getID3 PHP library to get information like Artist, Title, Mime-Type, etc.

Now that you’ve read over the code, let’s go back and look at the important lines. Lines 5 and 6 break down the runtime of the entire song (in minutes:seconds) to give us the total number of seconds. From there, a little math on line 8 to get us the exact proportion 30 seconds would be on this song.

Next, we bring the MP3 file into the code; Lines 10 and 11 use the fread method to read the file into the variable $content. We now have a (very large) string representing the MP3. After we pull the file in, and if the user is a logged-in user, we simply output our headers and print this string out. Because of the headers and string we send, the browser will interpret the script as an actual MP3 file and start playing/downloading.

The IF block starting at line 15 handles the preview functionality for users who are not logged in. Using the proportion value we found at line 8, we then calculate out how many bytes will equal 30 seconds for this particular song, and we substr it out. From there, the script is the same as if the user were logged in: output the header, print the string, and the browser will treat it like a new (and shorter) MP3.

Now that I’ve covered how this works, I’d like to explain quickly why it works. An MP3 file is set up so that all meta information (artist, title, length, etc.) are stored at the beginning of the file. This is what’s know as an ID3 tag. The reason the file is structured this way is so that music players can stream and play MP3 files while downloading, rather than having to download the entire song first before playing. With this method of extraction, I can send over all the headers manually to treat it like an MP3, but only send a fraction of the file itself and the browser still plays the song. (Note: line 21 represents the ‘size’ of the file and has to be sent or this will not work)

Obviously, this quick-and-dirty method of extraction does not take into account the ID3 tag. Since I already get this information from my getID3 library, I decided to start the extraction roughly 20 seconds in, bypassing any ID3 code. It also allowed me to start the preview further in the file, making it more likely the user gets to hear the chorus (or hook) of a song in this preview. You can always dial these setting to taste, and the lines to do that (lines 8 and 17) are denoted with comments.

The next step is to work out how to pull the ID3 out first, make the extraction, then add ID3 back on. So, check back for that article in the near future.

Posted in PHP, Web Design | Tagged | Leave a comment

Backwards-Compatible @font-face For All Browsers

Definitely one of the higher-obtainables in my field, the loftiest of lofty goals, is the ability to embed fonts on a website. As it stands now, there are only about 15 different fonts (and their respective variations) available to every user on every computer. Even a first-year designer can tell you that will get pretty boring pretty fast.

Enter @font-face. A CSS specification that came about in 1998 (with the rest of CSS2), this specific declaration allows you to specify any font you can name to be used in your website. Unfortunately, this isn’t a perfect world, and just simply saying you want to use a font, doesn’t at all mean that the font will actually show up when the user visits your site. Any time a font is called in a website, the browser will check for it in the user’s computer and, if they do not have it, the browser will change your fonts to something the computer does have. Whatever it changes to, you can pretty much guarantee that you won’t like it. So, how do we get our fonts down to their computers?

Very simple: we embed them. An embedded font is a file (or files) placed on the websever with the site. When the CSS code calls for a font, the browser runs like normal, checking the user’s computer for the font. But, when it doesn’t find it, instead of defaulting to some lesser font, the browser now has another place to look: your embedded file. The browser proceeds to download and cache the font file, and you now have beautiful, custom fonts attached to any element on the site you want. Of course, no browser really is alike in how they handle these embedded files, so you have to make multiple different types of embedded fonts to cover the different possibilities.

There are at least 18 different types of embedded fonts. They include .woff (Mozilla), .dfont (Mac OSX), .suit (Mac Classic), .eot (IE), .otf (also IE), .svg (iOS, new HTML5 standard), and .ttf (Windows). Most people will not have anything besides a TrueType (.ttf) or an OpenType (.otf) font file, so you will have to convert what you have into what you need. There are many different methods, online and off, to do this. After many trials and some errors, I’ve found the best to be the online convertor at the aptly-titled http://onlinefontconverter.com/.

I’d like to credit the post at Paul Irish’s blog and the great guys over at Six Revisions for helping me learn about this subject.

@font-face {
    font-family: 'Sketchy';
    src: 	url('fonts/sketchy-webfont.eot');
    src: 	local('☺'), url('fonts/sketchy-webfont.woff') format('woff'),
			url('fonts/sketchy-webfont.ttf') format('truetype'),
			url('fonts/sketchy-webfont.svg#Sketchy') format('svg');
    font-weight: normal;
    font-style: normal;
}

h1 {
    font-face: 'Sketchy', 'Arial Black', Arial;
}

This code verifies with IE6+, Firefox 5+, Chrome 14+, and Safari 5+. Windows and Mac, both.

One specific tip that took me some time to figure out: SVG font files require you to denote the name of the font in the filename (notice the “sketchy-webfont.svg#Sketchy” in some declarations).

Pay close attention to the special ‘☺’ character. While it may just look pretty, this character has a very specific purpose. Most of the time, the font you choose will not be on the user’s computer or they will have it already with no need for download/embedding. Very seldom will you encounter a user who has a different font by the same name, and if this happens, you could skew the entire website. In order to fix this, we send the ‘☺’. This character is what’s called a two-byte unicode character, which is an unacceptable format in font names. Most (if not all) font files only take one-byte characters. This extra “broken” character will force the user’s computer to download and use your font, just in case they have something else.

Posted in Web Design | Tagged , , , | Leave a comment

Past is Prologue

Today is officially six months since I left my job at Global Designs. The time has been marred with ups and downs, from all over the spectrum. Mostly, my time there was a learning experience. Not only did I get real-world experience, but I grew into the man I am now and really became an adult during my time there.

Not many people would freely admit this, but I quit my job. Up and left. Came in one day and told them I wasn’t coming back. But, I personally don’t find this to be a problem, because it was either them or me.

Let’s start at the beginning… Five years ago this May, I graduated from college. That’s not nearly as big a deal for me as it was for people of my parents’ generation, but it was still the biggest accomplishment of my life up to that point. My eyes were wide with hope and excitement. I got to step out (somewhat sure-footed) into the world and make my way. I found a nice job in my field before I left college so, I got to put time in while going to school. And when I graduated, the sky was the limit.

Eventually, I rose to the position of Project Manager. Pretty-much second in line at this company, I thought I had it made. I could work directly with my boss (the owner) to make the company run smoother and more efficient and, with my newly found spare time, I could brainstorm the ideas that would take the company to the next level.

Then, the event that ruined the collective hopes and dreams of America–the Great Recession–hit. Like many people in my line of work, I counted myself lucky to still have a job, and was willing to sacrifice a lot to keep it. So, when the first of our 3 designers was fired, I kept it cool. I thought, “this will blow over soon and I’ll only have to do the extra work of this missing person for a little while.” That little while expanded into six months, and when the only other designer (besides me) quit, I became worried. I later learned the stress drove them to the breaking point. It wasn’t until two weeks after, when it was apparent that the company wasn’t hiring a new designer, that I knew for sure that I was in trouble.

So many people lost their jobs, that news of their losses outweighed the other story: the story of the people left behind. “The New Normal,” as I called it. So many people had been fired or laid off in the last year, but those who were still lucky enough to be collecting a steady paycheck found their workload doubled, tripled, or worse just to accommodate the loss of employees. “You’ve still got a job. Suck it up and keep quiet.” Lines like that were basically my mantra. I kept my head down, didn’t make waves, and hoped this would all pass like a bad dream.

It wasn’t until I noticed that my boss noticed this shift in workload too, did it become a problem. If this guy can handle the work of three people and I don’t have to pay him any more, then why hire anybody else. This appeared to be the new motto for our company, as I went almost an entire year doing the work of three people. As bad as it was, I was making decent money for Springfield, and it was salary. Add to that the fact that the entire country overall was still losing ~750K jobs a month, I would have to have been stupid to give my job up.

I held to my mantra, and eventually things got better. The company finally hired another programmer, and then another. Suddenly, I was back in my project manager role. I could finially take a moment of rest every now and then; I could come into the office at the beginning of the day know I would leave on time; I could finally breathe.

Now I believe, like the rest of the country, that we’re on the other side of this. The US Government avoided financial collapse and, though it was gradual, we started seeing improvements in the economy. People were getting jobs again, and businesses were spending money. The only problem: no businesses were spending money on us. Businesses weren’t in free-fall anymore, but they sure weren’t expanding, either. And there’s only so many times you can hit up your old clients for updates…

You’ve heard the saying, “If it isn’t broke, don’t fix it.” My boss saw this current state of the economy as the company being “broken” and started making changes to try and “fix” it. New managers were hired, a new hierarchy was put in place, and I ended up being put in a room, by myself. Essentially, a monkey chained to a typewriter. I didn’t know it at the time, but it was decided around then that an expensive Project Manager wasn’t needed anymore in this company.

Around this same time, the lease on our building expired, and the company opted to buy their own building. I will repeat that so it sinks in: in a down economy, with their employees depending on them, this company gave up a steady lease relationship to buy their own building. Whether it be hubris, thinking they deserved a whole building, or just wanting a change of scenery, it was one of the biggest mistakes a company could make at the time. And after the company eventually crashes, when they look at the wreckage, this decision will probably be declared the start of the decline.

Now things were getting tense, barely any new clients were coming in, and we had already hit up our previous clients for help. The company was in trouble, and they had to do something. That something: double down on labor. Not in the way you think, them hiring more people. They decided to focus on getting even more production out of the designers. In our old building, we had one giant room (at least 20′ x 30′) where all the designers/developers could discuss technical issues, provide critiques/suggestions, and just generally feel comfortable and productive. In the new building, each designer was segregated to their own room. The boss called it an “office” (most likely to try and make us feel better), but we were essentially being put in our own little closet compared to our old home.

The long, cold winter of our nation’s “Recovery” kept the company in limbo. No longer able to pull in the large enterprise-level projects, we started focusing on design packages for low-income businesses, trying to shift the focus from quality to quantity. It was the new stated goal for the company that every designer would put out an entire website within a week. And again, I found a new normal. Instead of planning large-scale projects, and participating in project meetings, I basically had become a well-paid, human version of GeoCities.

Again, I kept to my mantra: I would be stupid to quit a job in this economy. But this commitment wasn’t nearly as steadfast as it used to be. Before, if times were tough, I could imagine the light at the end of all this. I imagined the second, and third branches of the company opening up across the region; I saw myself the head of an entire design department; I saw myself happy here. Now, all I could see were the four walls of my new office, shut away from the rest of the employees, and shut away from the world.

The bottom line for all of this, is that we grew apart. It became apparent to me that the company no longer wanted to see itself on the national stage. They became more interested in local business, most likely because it was safe. This didn’t sit well with me, I still had lofty goals in my life that they weren’t interested in helping me reach anymore.

After about a year of this, with no end in sight, I finally reached my breaking point. I decided that in this down economy, I didn’t care if I kept a steady job, if the job was what I was living now. Over the 5 years I had worked for Global Designs, the working conditions deteriorated so badly that I decided I would be better off somewhere else.

Luckily, that “something” was a good friend of mine. For a few months, we had been talking about how great it would be to start our own company. How great would it be, I thought, to have the office I wanted: wide open spaces, collaborative relationships, and (most important) a positive environment in which to thrive.

My friend played on a higher level than Global could ever hope. He had important clients all over the country, and even a few who spanned the globe. And when one of them offered a windfall to work on a project, it was as if the fates themselves were conspiring a cosmic balance for me. After over a year of feeling like I hated myself just because of my working conditions, I finally had a chance to get out. And I took it, dropping that black cloud of a job like a bad habit.

The bottom line of it all is that Global and I grew apart. They had evolved a different set of priorities from when I joined on, and I wasn’t going to evolve with them. The time since then has been… different. Working for yourself is a whole different kind of experience (which I’m sure I’ll write about eventually). I’ve barely had any money to my name, and I barely sleep now, but I wouldn’t change a single thing. Even if I made only a fraction of the money I used to make at Global, I have one thing now they couldn’t give me anymore. I’m happy.

I’ve been off the grid for legal reasons (finishing out the remainder of my non-compete agreement with Global), but now I’m officially back on the market. Ready to make incredible websites. Ready to brainstorm the next big idea. Finally ready to change the world.

Posted in Personal | 2 Comments