我需要将几个mp3文件合并为一个。
我目前正在这样做:
$combinedFiles = "";
$dir = $_POST['dir'];
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
$combinedFiles .= file_get_contents(urldecode($dir."/".$entry));
}
}
closedir($handle);
}
file_put_contents("mp3/".$dir.".mp3", ($combinedFiles));
如果我这样做:
ini_set('memory_limit', -1);
它有效。我尝试将此限制设置为 4MB,它不会引发内存错误,但不会创建文件。如果不设置任何限制并保留默认值,我会收到分配内存错误。我不想把它留在-1
因为我已经读过这是一种不好的做法,可能会导致问题。
谢谢(错误不是来自代码中的其他任何地方,我只运行它)。
编辑:即使设置为8GB,这是我的计算机内存,它也不起作用。
这种方法呢?
<?php
$dir = $_POST['dir'];
if ($handle = opendir($dir))
{
$outFd = fopen(sprintf("mp3/%s.mp3", $dir), 'wb');
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != "..")
{
$path = urldecode(sprintf("%s/%s", $dir, $entry));
$inFd = fopen($path, 'rb');
stream_copy_to_stream($inFd, $outFd);
fclose($inFd);
}
}
fclose($outFd);
closedir($handle);
}
现在,我们对未正确验证输入有一些安全问题,如果这是一个公共工具,您应该修复它们。但现在我只讨论手头的问题。
与其一次将所有这些文件的数据存储在内存中,为什么我们不先打开输出文件,然后将每个输入文件复制到输出文件的末尾?我们可以做到这一点 stream_copy_to_stream()
.
我们也可以通过 stream_set_chunk_size()
为操作使用较小的块大小,但听起来,对于您的应用程序,可以将一个 MP3 临时存储在内存中(4-5Mb 顶部)。您也可以一次手动读取/写入一个块,而不是使用stream_copy_to_stream()
,但总体思路是相同的。
这应该会导致一次实际存储在内存中的文件少于一个。
你可以使用sox,它对我有用几次
在您的示例中,您将所有文件复制到内存,并在作业完成后将它们写回磁盘。
我的建议:
- 将第一个文件复制到新位置
- 从第二个文件中获取内容并将其追加到复制的文件 (file_put_contens FILE_APPEND)
- 取消设置包含内容的变量
- 继续执行步骤 2,直到完成