How to merge / concatenate mp3s with PHP
First published on August 12, 2007
One of the new features of my anti-spam plugin is the ability to create auto-generated mp3 files. The plugin concatenates individual mp3 files representing the sound of each letter in the alphabet, in order to build a word.
Of course, I have no idea how to code something that merges mp3 files, so I had to do some searching and eventually found this site with some working code: http://www.sourcerally.net/Scripts/20-PHP-MP3-Class.
Here is my modified version, with some simplified functionality (I removed the code that added ID3 tags) and an added feature that I modified from FPDF (a script that creates PDFs in PHP) in order to output (to the browser) the merged mp3 file, prompting users to open or save it. This code is compatible with both PHP 4 and PHP 5.
<?php // This is the class to generate mp3 files based on the anti-spam words // Based on the PHP mp3 class at http://www.sourcerally.net/Scripts/20-PHP-MP3-Class // Output code based on the FPDF class at http://www.fpdf.org class mp3 { var $str; var $time; var $frames; // Create a new mp3 function mp3($path="") { if($path!="") { $this->str = file_get_contents($path); } } // Put an mp3 behind the first mp3 function mergeBehind($mp3) { $this->str .= $mp3->str; } // Calculate where's the end of the sound file function getIdvEnd() { $strlen = strlen($this->str); $str = substr($this->str,($strlen-128)); $str1 = substr($str,0,3); if(strtolower($str1) == strtolower('TAG')) { return $str; } else { return false; } } // Calculate where's the beginning of the sound file function getStart() { $strlen = strlen($this->str); for($i=0;$i<$strlen;$i++) { $v = substr($this->str,$i,1); $value = ord($v); if($value == 255) { return $i; } } } // Remove the ID3 tags function striptags() { //Remove start stuff... $newStr = ''; $s = $start = $this->getStart(); if($s===false) { return false; } else { $this->str = substr($this->str,$start); } //Remove end tag stuff $end = $this->getIdvEnd(); if($end!==false) { $this->str = substr($this->str,0,(strlen($this->str)-129)); } } // Display an error function error($msg) { //Fatal error die('<strong>audio file error: </strong>'.$msg); } // Send the new mp3 to the browser function output($path) { //Output mp3 //Send to standard output if(ob_get_contents()) $this->error('Some data has already been output, can\'t send mp3 file'); if(php_sapi_name()!='cli') { //We send to a browser header('Content-Type: audio/mpeg3'); if(headers_sent()) $this->error('Some data has already been output to browser, can\'t send mp3 file'); header('Content-Length: '.strlen($this->str)); header('Content-Disposition: attachment; filename="'.$path.'"'); } echo $this->str; return ''; } } ?>
Here’s how I used the class to generate an mp3 file from individual files (in a “sounds” folder) representing each letter. You can, of course, use the above code to concatenate mp3 files for any purpose.
// Specify the word $petersword = "testword"; $word_count = strlen($petersword); // Set up the first file if ($word_count > 0) { $mp3 = new mp3($cas_fontpath . 'sounds/' . substr($petersword, 0, 1) . '.mp3'); $mp3->striptags(); } // Generate the mp3 file from each letter in the word for ($i = 1; $i < $word_count; ++$i) { $cas_character = $cas_fontpath . 'sounds/' . substr($petersword, $i, 1); $cas_mp3equivalent = new mp3($cas_character . '.mp3'); $mp3->mergeBehind($cas_mp3equivalent); $mp3->striptags(); } // Spit out the audio file! $mp3->output('word.mp3');
Note: if you need some support using any of the code, I suggest that you visit the original source of the mp3 concatenation code.
January 15th, 2008 at 11:42 am
Priyankoo Sarmah says:
Thanks a lot!! So useful!!
March 1st, 2008 at 12:10 pm
Alx says:
do it is possible to insert a pause into file merged?
March 1st, 2008 at 1:19 pm
Peter says:
Yes, you can insert a pause — to do so you simply have to record a blank sound file as the pause.
March 2nd, 2008 at 8:19 am
Alx says:
This is my implementation:
http://interno.netsons.org/modules.php?name=Dtmf
http://interno.netsons.org/modules.php?name=Banche
http://interno.netsons.org/modules.php?name=CodFis
Ty
June 30th, 2008 at 7:59 pm
Dada says:
I was looking for that sort of script since severals months, you’re my hero, thanks alot.
July 1st, 2009 at 11:30 am
Thierry says:
Thanks for sharing. It worked on the first try … what I though would take hours, take me 30mn …
July 8th, 2009 at 8:57 pm
Vaz says:
Excellent…I thought we need some extra things to work mp3 with php…great tutorial
June 1st, 2010 at 1:19 pm
Mukoo says:
Thanks! it works perfectly. But how about layering/mixdown 2 mp3’s, not simply appending one after the other. What if I want them to blend together? Do you think it can be done?
Reply from Peter: It can certainly be done with desktop programs, but I’ve never looked into a command-line solution. If you find something, please post your findings.
August 3rd, 2010 at 1:59 am
Natali says:
Very helpfull!!! Many thanks!!!
October 5th, 2010 at 2:19 am
Sarunas says:
When merging mp3s with different bitrates the higher bitrate mp3 plays in slow motion. Any solutions to this?
Reply from Peter: Not sure, but I welcome other people’s solutions.
December 19th, 2010 at 8:48 am
Michel says:
This script is exactly what I was looking for but… is there a way to have the sound played by a flash script like hbs_mp3_player.swf directly in the web page?
When I use your script I’m asked to download the merged mp3 file or play it with VLC or WMP.
Reply from Peter: I’m pretty sure you could feed the generated file to a player, since it shouldn’t be any different than any other mp3 player. If it’s a file being generated on the fly, you probably have to save it to the server and stream it from there.
November 9th, 2011 at 10:37 am
John C says:
Dear all,
I am a beginner with php. I would like to adapt this script to merge 2 mp3 files (file1.mp3 and file2.mp3 into file-merged.mp3).
It should be very simple compared to this script.
Thank you very much for your kind replies.
JC
June 28th, 2012 at 12:29 am
nischal dhakal says:
Dear all,
When i am trying to merge two mp3 files which have more than 2:00 minutes lengths of file, It create a merge file but can’t be opened on window media player. Anyone have any answer with this.
thank you….
November 16th, 2012 at 4:29 am
Teryaki says:
Hey
Thank you very much for your script. it works fine.
What changes do i need to make, if i want to merge ogg files?
Reply from Peter: I haven’t looked into ogg files, but please share any findings!
August 31st, 2015 at 7:03 am
Matt says:
Hey Peter,
You said you removed the section which added ID3 Tags, but can you help me with putting in new ID3 tags into the downloaded file?
Reply from Peter: Unfortunately, I don’t have the original code and it looks like the original link is broken. Looks like you’ll have to search elsewhere. Good luck!
September 7th, 2015 at 9:37 am
Nour says:
Is there any documentation about this mp3 class, the given link is broken.
January 22nd, 2019 at 4:27 am
Kalpesh says:
Hello Sir,
I want joint two or more mp4 audio file in one audio file using code igniter framework .
How to implement this code in my project.
Please Help…….
September 11th, 2019 at 10:59 am
Stanislas says:
Hello Sir,
I am a beginer in php and I just want to merge two files:
$file_total = $file_1 + $file_2
I tried to understand your code during a long time, but I can’t understand where is the code for just adding 2 files.
Each time they put me a warning which says : "Catchable fatal error: Object of class mp3 could not be converted to string"
what should I do ?
Thanks for your answer
Reply from Peter: Are you merging mp3 content, text, or non-mp3 binary files? Most of the code is for handling mp3s, so you should look for some other code specific to your purpose.
November 15th, 2023 at 6:48 am
Peter says:
This is amazing! Thanks a lot for sharing this code and also the audio files! I’ll use this for my own custom CAPTCHA implementation.
One change which is required to make it work with "new" PHP versions: The constructor must now be called "__construct" instead of "mp3". Otherwise it won’t be invoked.
Another little improvement I made is adding playback via JavaScript. This is much more convenient than having to download the file.
As a fallback / non-JS solution you can also just remove the "Content-Disposition"-header. Modern browsers won’t make you save the file then but instead it will be opened directly in the browser and you can play it easily (you should open it in a new tab so users don’t lose their input). It’s probably smart to still offer a download link for best compatibility.
btw: In case anyone still needs the tag stuff: I also found this newer PHP mp3 merge code which seems to do these things (didn’t try it): https://github.com/thegallagher/PHP-MP3/tree/master