Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge two mp3 php

Tags:

merge

http

php

mp3

ogg

Do you know a class to merge two MP3 files using PHP?

I've found nothing on Google.

like image 297
poiuytrez Avatar asked Oct 21 '10 21:10

poiuytrez


5 Answers

If by merging, you mean placing one audio over the other, then please disregard this answer.

If you dont want to re-encode the MP3s, you can probably just append them. I know this worked for MPEG movies, so I guess it could work for MP3s too. Another option would be to add the audo files to a Zip Archive with no compression and then rename the extension to .mp3.

I did a quick test and this

file_put_contents('combined.mp3',
    file_get_contents('file1.mp3') .
    file_get_contents('file2.mp3'));

worked fine. The ID3 tags will be wrong, but the resulting file contains both audio files. For some other possible gotchas, see the link in Pekka's answer.

Also, some quick googling resulted in

  • http://www.sourcerally.net/Scripts/20-PHP-MP3-Class
  • http://codingforums.com/showthread.php?t=169069

and some discussion

  • http://ask.metafilter.com/21381/Merge-mp3s-with-PHP
like image 67
Gordon Avatar answered Nov 09 '22 08:11

Gordon


For anyone interested in doing the same thing now, you can use the following library that I wrote (refactored?): https://github.com/falahati/PHP-MP3

composer require falahati/php-mp3

Merge two MP3 file:

$audio1 = \falahati\PHPMP3\MpegAudio::fromFile("1.mp3")->stripTags();
$audio2 = \falahati\PHPMP3\MpegAudio::fromFile("2.mp3")->stripTags();
$audio1->append($audio2)->saveFile("3.mp3");

Please note that this is an MP3 parser library and it does not encode, decode or re-encode MP3 files. This solution is essentially the same as others here but always results in a structurally correct and standard MP3 file.


-- In answer to the comment about the invalid duration of the file:

MP3 files have no header and only consists of MPEG frames. This library keeps the MPEG frame headers (since it won't be playable without those) and therefore the problem described here is not entirely true.

However, from the point of view of a player or a tool that needs to extract the duration of an MP3 file, in the absence of an ID3 tag, the whole file should be read and calculate the duration frame by frame. This is both calculation-intensive and memory-intensive, especially for big files.

Therefore many tools might try to read the first frame and guess the number of total frames based on the total size of the file and simply calculate the possible duration of the file from this information and based on the properties of the first frame. This is alright by it-self and should work with no to little difference to the real file's duration.

The real problem arises when you try to merge two hugely different MP3 files together. Since this library does no re-encode the files it won't change the frames and just simply adds them next to each other trusting the player to read the MP3 frame header for each frame independently of other frames. This is not the case with some players and tools since they tend to ignore each frame property in favor of performance by only reading the properties of the first frame and expecting all other frames to be similar.

This is where your problem with duration arises from and not from a bug or lack of feature in this library. You simply need to provide the library with similar files in terms of properties (bitrate, etc); otherwise, you are leaving the fate of your file in the hand of player's MP3 decoder implementation.

Other issues with hugely different files sewed together via this library and bad player implementations contain, fast or slow-paced playback, error while playing, distorted playback, etc. So make sure your files are as close to each other as possible if the file's portability is something you care about (sharing the file for download maybe) or use a compatible player if it is not (in my tests, Chrome, Firefox and Telegram ware compatible; don't know and don't remember about the others).

like image 31
Soroush Falahati Avatar answered Nov 09 '22 09:11

Soroush Falahati


This is not possible. There is no implementation of the MP3 codec in PHP. You will need to use an external command-line tool to do this. (Which, depending on your server configuration, you can execute from within PHP as @ceejayoz says.)

See these questions for solutions:

  • Merging MP3 files in Linux Debian using PHP

  • What is the best way to merge mp3 files?

like image 45
Pekka Avatar answered Nov 09 '22 07:11

Pekka


If the .mp3 files are just MPEG-1 or MPEG-2 Layer III audio, then the files can just be concatenated. There is no real concept of a header for the whole file. Each frame has a header followed by data, and the file is just comprised of a sequence of frames, which is called the bitstream. The bitrate, stereo mode, etc, do not necessarily have to be the same within a bitstream, so you can concatenate dissimilar files. The Wikipedia article explains this, but I think the spec actually is easier to understand.

ID3 tags, or an other data, within the file (which technically renders it a non-compliant bitstream) may muck things up on the decoder end.

The spec for MPEG-1 and MPEG-2 audio is actually pretty simple. Writing a parser to chunk a file into frames, and then interpreting the headers is not that much work. The last time I did this, it only took an hour or two.

The ID3 spec isn't that complicated either, so I suspect writing some code to strip out the tags before concatenation should be easy, but I have never done this.

The getID3() library (http://getid3.sourceforge.net/) may provide some guidance, too. It has been a while since I have used it, but it may also support opening MP3s and stripping out the ID3 tags already.

HTH

like image 2
mpdonadio Avatar answered Nov 09 '22 08:11

mpdonadio


Important things to remember:

  • The bit rates must match. It's also a good idea to ensure the rate (Hz) and stereo/mono are matched (I used Audacity).
  • The Content-length header be the length of both files.

Here's a sample from my text-to-speech project. I needed to add a 1 second silence at the end of MP3 audio that was generated dynamically:

$output_audio = textToMP3("Hello World");               // Original audio
$silent_audio = file_get_contents("silence.mp3");       // 1 second silence
$content_length = strlen($output_audio) + strlen($silent_audio);

// Output the audio stream
header('Content-type: audio/mpeg');
header('Content-length: ' . $content_length);
header('Cache-Control: no-cache');
header("Pragma: no-cache");
header("Expires: 0");
echo $audio . $silent_audio;
like image 1
Andrew Bucklin Avatar answered Nov 09 '22 08:11

Andrew Bucklin