Merge two mp3 php
Asked Answered
T

5

5

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

I've found nothing on Google.

Turtledove answered 21/10, 2010 at 21:55 Comment(0)
L
16

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

and some discussion

Laundryman answered 21/10, 2010 at 22:6 Comment(10)
This sounds kind of.. uhm.. dirty.Peculiarity
@Gordon: Sorry, i should have been more clear: Concatenating two files is not that dirty. Many formats work like that. I am talking about the ZIP-solution. This seems rather complicated and unnecessary to me.Peculiarity
@elusive using a Zip file has the added benefit of being able to unzip and have the mp3s back again. And also, having two solutions to pick from when the other answer is "impossible" is quite good, dont you think :)Laundryman
@Gordon: Like i said, the concatenating solution is good, but isn't ZIP using a header? An MP3 decoder does not necessarily know how to handle that.Peculiarity
@elusive Maybe. I am no Decoder expert. I just remembered I often did that some years ago and it worked. I just did a quick test from my desktop and it worked now too.Laundryman
@Gordon: Thats right! I did similar things like renaming ZIPs to ISOs a long time ago (which worked, too). This is really weird, but i never tried to burn one of those to CD/DVD. My loop-device was really smart, obviously ;)Peculiarity
I will try that. I absolutely do not care about tags and everything.Turtledove
Thanks @Gordon, this helped me a lot for my project. I have not seen any issues with this approach at all.Moonseed
I tried this with 29 files and it works. The resulting MP3 file shows as 0.01 in length but does play the entire file correctly.Peaslee
this worked for me, adding intro and outro music to amazon polly file, just make sure sample rates, frequency and bitrates match, in my case mp3 mono 22 48kb 22hzAirtight
P
4

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).

Poleaxe answered 18/9, 2017 at 10:30 Comment(1)
For anyone going with this solution, note that it does not alter the output file headers, the result is a mp3 file that has a wrong durationPlainspoken
S
3

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:

Squill answered 21/10, 2010 at 21:58 Comment(1)
You can, however, have PHP execute the external command-line tools.Proprietor
F
2

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

Finery answered 22/10, 2010 at 0:9 Comment(0)
R
1

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;
Reconnoitre answered 19/7, 2015 at 18:7 Comment(3)
Hi, just writing to tell you two things 1) thanks for this as its very insightful 2) is your project available open source or? Very interested in your textToMp3 function!Tewfik
I’m afraid I don’t have the source code for the project anymore. What I can tell you is that the only thing that textToMp3 function did was send the text to a 3rd party API which would respond with a MP3 file. I don’t remember which API that was, but there are plenty out there for you to choose from.Reconnoitre
Thanks Andrew appreciated your reply. Yes infact I did what you said and used a 3rd party API, no need to reinvent the wheel sometimes ey :) Regards!Tewfik

© 2022 - 2024 — McMap. All rights reserved.