合并两个mp3 php

发布于 2024-09-28 16:29:00 字数 53 浏览 8 评论 0原文

您知道使用 PHP 合并两个 MP3 文件的类吗?

我在谷歌上什么也没找到。

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

I've found nothing on Google.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

动次打次papapa 2024-10-05 16:29:00

如果您所说的合并是指将一个音频放在另一个音频之上,那么请忽略此答案。

如果您不想重新编码 MP3,您可以直接附加它们。我知道这适用于 MPEG 电影,所以我想它也适用于 MP3。另一种选择是将音频文件添加到不压缩的 Zip 存档中,然后将扩展名重命名为 .mp3。

我做了一个快速测试,

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

效果很好。 ID3 标签将是错误的,但生成的文件包含两个音频文件。 有关其他一些可能的问题,请参阅 Pekka 答案中的链接。

此外,一些快速谷歌搜索导致

和一些讨论

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

度的依靠╰つ 2024-10-05 16:29:00

对于现在有兴趣做同样事情的人,您可以使用我编写的以下库(重构?):
https://github.com/falahati/PHP-MP3

composer require falahati/php-mp3

合并两个 MP3 文件:

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

请注意这是一个 MP3 解析器库,它编码、解码或重新编码 MP3 文件。此解决方案本质上与此处的其他解决方案相同,但始终生成结构正确且标准的 MP3 文件。


-- 回答有关文件无效持续时间的评论:

MP3 文件没有标头,仅由 MPEG 帧组成。该库保留 MPEG 帧头(因为没有这些帧头就无法播放),因此这里描述的问题并不完全正确。

然而,从需要提取MP3文件时长的播放器或工具的角度来看,在没有ID3标签的情况下,应该读取整个文件并逐帧计算时长。这既是计算密集型也是内存密集型,尤其是对于大文件。

因此,许多工具可能会尝试读取第一帧并根据文件的总大小猜测总帧数,并根据该信息和第一帧的属性简单地计算文件的可能持续时间。这本身没问题,并且与实际文件的持续时间应该没有什么差别。

当您尝试将两个截然不同的 MP3 文件合并在一起时,真正的问题就出现了。由于该库不会对文件进行重新编码,因此不会更改帧,而只是简单地将它们彼此相邻添加,信任播放器能够独立于其他帧读取每个帧的 MP3 帧头。某些播放器和工具的情况并非如此,因为它们倾向于通过仅读取第一帧的属性并期望所有其他帧相似来忽略每个帧属性以支持性能。

这就是您的持续时间问题源于而不是源于该库中的错误或功能缺失的地方。您只需向库提供属性(比特率等)类似的文件即可;否则,您将把文件的命运交给播放器的 MP3 解码器实现。

通过此库将截然不同的文件缝合在一起以及糟糕的播放器实现的其他问题包括快慢播放、播放时出错、播放失真等。因此,如果文件的可移植性,请确保您的文件彼此尽可能接近是您关心的东西(也许共享文件以供下载),或者如果不是,请使用兼容的播放器(在我的测试中,Chrome、Firefox 和 Telegram ware 兼容;不知道也不记得其他的)。

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

埋情葬爱 2024-10-05 16:29:00

这是不可能的。 PHP 中没有 MP3 编解码器的实现。您将需要使用外部命令行工具来执行此操作。 (根据您的服务器配置,您可以按照 @ceejayoz 的说法从 PHP 中执行。)

请参阅以下问题以获取解决方案:

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:

無心 2024-10-05 16:29:00

如果 .mp3 文件只是 MPEG-1 或 MPEG-2 Layer III 音频,则可以将这些文件连接起来。整个文件没有真正的标头概念。每个帧都有一个标头,后面跟着数据,文件由一系列帧组成,称为比特流。比特流中的比特率、立体声模式等不一定必须相同,因此您可以连接不同的文件。维基百科文章解释了这一点,但我认为该规范实际上更容易理解。

文件中的 ID3 标签或其他数据(技术上使其成为不兼容的比特流)可能会在解码器端造成混乱。

MPEG-1 和 MPEG-2 音频的规范实际上非常简单。编写解析器将文件分块为帧,然后解释标头并不需要太多工作。上次我这样做只花了一两个小时。

ID3 规范也不是那么复杂,所以我怀疑编写一些代码在连接之前删除标签应该很容易,但我从未这样做过。

getID3() 库 (http://getid3.sourceforge.net/) 也可以提供一些指导。我已经有一段时间没有使用它了,但它可能也支持打开 MP3 并删除 ID3 标签。

华泰

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

聆听风音 2024-10-05 16:29:00

需要记住的重要事项:

  • 比特率必须匹配。确保速率 (Hz) 和立体声/单声道匹配也是一个好主意(我使用 Audacity)。
  • Content-length 标头是两个文件的长度。

这是我的文本转语音项目的示例。我需要在动态生成的 MP3 音频末尾添加 1 秒静音:

$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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文