How To Extract And Play Part Of An MP3 In PHP

Posted By on Jun 17, 2013 | 4 comments


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.

4 Comments

  1. Great script !

    You solved me a lot of trouble. I just didn’t want to convert files or make extra mp3 files before displaying it to users. So this is my best solution !

    Post a Reply
  2. Back here. Now devlopment has been remade using PSR and class. Work very well. Thnak you for your help 😉

    Post a Reply
  3. This is a great script. I have a file of approximately 1 hr. i want to split it into 15 min intervals. I found how to do the first 15. However, I see on line 19 the start in about 10 seconds. changes every different file size. is there a way to make it more consistant? and also how i start from min 15, etc.

    Post a Reply
    • Thanks for checking out the article. If you want to email me at stephenwalcher @ gmail.com, I’d be happy to help you out if you’re still needing help.

      Post a Reply

Trackbacks/Pingbacks

  1. Automatically trimming an mp3 in PHP - QuestionFocus - […] Check it out at http://www.stephenwalcher.com/2013/06/17/how-to-extract-and-play-part-of-an-mp3-in-php/. […]

Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.