【发布时间】:2011-04-28 21:13:14
【问题描述】:
你知道使用 PHP 合并两个 MP3 文件的类吗?
我在 Google 上一无所获。
【问题讨论】:
你知道使用 PHP 合并两个 MP3 文件的类吗?
我在 Google 上一无所获。
【问题讨论】:
对于现在有兴趣做同样事情的任何人,您可以使用我编写的以下库(重构?): 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 软件兼容;不知道也不记得其他的) )。
【讨论】:
要记住的重要事项:
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;
【讨论】:
如果 .mp3 文件只是 MPEG-1 或 MPEG-2 Layer III 音频,则可以将这些文件串联起来。整个文件的标题没有真正的概念。每个帧都有一个标题,后面跟着数据,而文件只是由一系列帧组成,称为比特流。比特率、立体声模式等在比特流中不一定必须相同,因此您可以连接不同的文件。维基百科文章解释了这一点,但我认为规范实际上更容易理解。
文件中的 ID3 标签或其他数据(从技术上讲会使其成为不合规的比特流)可能会在解码器端造成混乱。
MPEG-1 和 MPEG-2 音频的规范实际上非常简单。编写一个解析器将文件分块成帧,然后解释标题并没有那么多工作。我上次这样做时,只花了一两个小时。
ID3 规范也没有那么复杂,所以我怀疑在连接之前编写一些代码来去除标签应该很容易,但我从来没有这样做过。
getID3() 库 (http://getid3.sourceforge.net/) 也可以提供一些指导。好久没用了,不过它可能也已经支持打开MP3和去掉ID3标签了。
HTH
【讨论】:
如果合并是指将一个音频放在另一个音频之上,那么请忽略此答案。
如果您不想重新编码 MP3,您可以只附加它们。我知道这适用于 MPEG 电影,所以我想它也适用于 MP3。另一种选择是将 audo 文件添加到没有压缩的 Zip 存档中,然后将扩展名重命名为 .mp3。
我做了一个快速测试,这个
file_put_contents('combined.mp3',
file_get_contents('file1.mp3') .
file_get_contents('file2.mp3'));
工作正常。 ID3 标签将是错误的,但生成的文件包含两个音频文件。 For some other possible gotchas, see the link in Pekka's answer.
另外,一些快速的谷歌搜索导致
还有一些讨论
【讨论】:
这是不可能的。 PHP 中没有 MP3 编解码器的实现。您将需要使用外部命令行工具来执行此操作。 (根据您的服务器配置,您可以像@ceejayoz 所说的那样在 PHP 中执行。)
请参阅以下问题以获得解决方案:
【讨论】: