是否有比file_get_contents更少的内存扩展或更有效的合并 MP3 的方法


Is there a less memory extensive or more efficient way of merging MP3 than file_get_contents?

我需要将几个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,它对我有用几次

在您的示例中,您将所有文件复制到内存,并在作业完成后将它们写回磁盘。

我的建议:

  1. 将第一个文件复制到新位置
  2. 从第二个文件中获取内容并将其追加到复制的文件 (file_put_contens FILE_APPEND)
  3. 取消设置包含内容的变量
  4. 继续执行步骤 2,直到完成