【问题标题】:look for a specific filetype in a directory in php and send it to a different directory after conversion在php中的目录中查找特定的文件类型,并在转换后将其发送到不同的目录
【发布时间】:2019-09-29 09:20:26
【问题描述】:

我有一个目录,其中有一个 mp4 文件(也包括其他文件),我想将其转换为 mp3,然后将其发送到不同的目录。我已使用以下 命令行命令 转换为 mp3 并且它工作得非常好。

ffmpeg -i 36031P.mp4 -map 0:2 -ac 1 floor_english.mp3 

mp4 文件 位于 in_folder 中。使用 ffmpeg,我想将 mp4 文件转换为 mp3 并将其发送到 out_folder

<?php
$dir    = 'in_folder';
$files1 = scandir($dir);
print_r($files1);    /* It lists all the files in a directory including mp4 file*/
?>

print_r($files1)列出一个目录下的所有文件,包括mp4file。

问题陈述:

我想知道我需要编写什么 php 代码,以便它只查找目录中的 mp4 文件,然后将其发送到 不同的目录(比如说 out_folder)转换成mp3。

我想要的图示

【问题讨论】:

  • 我可以知道它被否决的原因
  • 在循环中使用opendirreaddir。在循环中,检查文件类型并仅复制这些文件。
  • 为什么不直接在最终文件夹或子目录中转换 mp3 ;) 或使用 pathinfoscandir 上循环检查文件扩展名
  • 赏金快闪怎么样?

标签: php ffmpeg mp3 mp4 scandir


【解决方案1】:

认为这是你想要的:

<?php
$dir    = 'in_folder';
$files1 = scandir($dir);
print_r($files1);    /* It lists all the files in a directory including mp4 file*/

$destination = 'your new destination';

foreach($files1 as $f)
{
  $parts = pathinfo($f);
  if ($parts['extension'] = 'mp3';
  {
    // copy($f, $destination. DS . $parts['filename']. '.' . $parts['extension']);
    rename($f, $destination. DS . $parts['filename']. '.mp3');
  }
}
?>

文档pathinfo

使用转换编辑:

我觉得你可以像这样直接导出你的mp3

foreach($files1 as $f)
{
  $parts = pathinfo($f);
  if ($parts['extension'] = 'mp4';
  {
    // $result : the last line of the command output on success, and FALSE on failure. Optional.
    system('ffmpeg -i '.$f.' -map 0:2 -ac 1 '.$destination.DS. $parts['filename'].'.mp3', $result);
  }

  // See: https://www.php.net/manual/en/function.system.php
  if ($result === false) {
    // Do something if failed
    // log for example
  } else {
    // command completed with code : $result
    // 0 by convention for exit with success EXIT_SUCCESS
    // 1 by convention for exit with error EXIT_ERROR
    // https://stackoverflow.com/questions/12199216/how-to-tell-if-ffmpeg-errored-or-not
  }
}

文档system

或者做第一个循环也转换 mp4,第二个循环复制 mp3

一键编辑:

foreach($files1 as $f)
{
  $parts = pathinfo($f);

  switch(strtolower($parts['extension']))
  {
    case 'mp4' :
      // $result : the last line of the command output on success, and FALSE on failure. Optional.
      system('ffmpeg -i '.$f.' -map 0:2 -ac 1 '.$destination.DS. $parts['filename'].'.mp3', $result);

      // See: https://www.php.net/manual/en/function.system.php
      if ($result === false) {
        // Do something if failed
        // log for example
      } else {
        // command completed with code : $result
        // 0 by convention for exit with success EXIT_SUCCESS
        // 1 by convention for exit with error EXIT_ERROR
        // https://stackoverflow.com/questions/12199216/how-to-tell-if-ffmpeg-errored-or-not
      }
      break;

    case 'mp3' :
      // copy($f, $destination. DS . $parts['filename']. '.' . $parts['extension']);
      rename($f, $destination.DS.$parts['filename'].'.mp3');
      break;  
  }
}

编辑 1 : 更正strtolower($parts['extension'])检查文件扩展名不区分大小写。

或者像这样:

strtolower(pathinfo("/path/file.mP4", PATHINFO_EXTENSION)) == ".mp4"

没有必要使用preg_matchregexp,因为pathinfo 是完成这项工作的预制函数,除非您使用像.tar.gz 这样的双命名扩展名,否则它可以正常工作。

regular-expression-to-detect-a-file-extension

编辑 2 :使用 rename 而不是 copy 移动 mp3。

【讨论】:

  • 感谢您的回答。它看起来真的很棒。我还想在代码中包含转换过程。我想知道我应该在哪里集成 ffmpeg 进程。它的工作方式应该是扫描目录以查找 mp4 文件,然后在将其转换为 mp3 后将其发送到不同的目录。
  • php 代码应该扫描一个目录(文件夹 A 中的 mp4 文件) 以查找一个 mp4 文件,然后将其发送到不同的目录 (文件夹 B 中的 mp3 文件) 转换成 mp3 后。
  • 所有逻辑看起来都正常。我在我的代码库中复制了您的代码。有什么我想念的吗?因为它似乎没有将 mp4 转换为 mp3 并将其发送到不同的文件夹。
  • 可能我们很接近了。缺了点什么。我将发布另一个问题以提供答案。
  • 我有一个类似的question 与 ffmpeg 相关。我想知道你是否可以看看。
【解决方案2】:

我觉得这一切都可以更健壮和更短。

<?php

// the folder to get MP4's from, recursively
$src_dir = 'folder/a';
// the destination to put MP3's in.
$dst_dir = 'folder/b';

// An iterator ('reader') that takes all files in src
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($src_dir)
);

// A filter, that only leaves entries ending with .mp4, case-insensitive.
$videos = new RegexIterator($files, '/^.+\.mp4$/i', RecursiveRegexIterator::MATCH));

// Then, for each element in videos, convert to MP3
foreach ($videos as $video) {
    $src = $video->getPathname();
    // The destination is the basename without 'mp4', with 'mp3' appended.
    $dst = $dst_dir.'/'.$video->getBaseName($video->getExtension()).'mp3';

    system("ffmpeg -i $src -map 0:2 -ac 1 $dst");
}

您应该注意不允许使用“用户指定”的文件名,而是使用您自己的(随机)文件名。不惜一切代价避免执行未经验证的用户输入!

【讨论】:

  • 我试过你的代码。它一直运行到// A filter, that only leaves entries ending with .mp4, case-insensitive. 该代码不在该行之后。让我知道我需要做出哪些改变。
【解决方案3】:

这样就可以了。我测试了解决方案并且它有效。我必须对 ffmpeg 命令进行一项参数更改。在我的机器上,它为映射引发了错误。我在映射后添加了一个问号以忽略错误。

代码采用以下文件夹结构:

<?php

  error_reporting(E_ALL);

  $in_folder = sprintf("%s/mp4", __DIR__);
  $out_folder = sprintf("%s/mp3", __DIR__);

  if(!file_exists($in_folder)){
    mkdir($in_folder);
  }

  if(!file_exists($out_folder)){
    mkdir($out_folder);
  }

  $items = scandir($in_folder);
  foreach($items as $item){
    if(preg_match('/^.*\.mp4$/', $item)){
      $file_name = str_replace(".mp4", "", $item);
      $in_file = sprintf("%s/%s.mp4", $in_folder, $file_name);
      $out_file = sprintf("%s/%s.mp4", $out_folder, $file_name);
      if(file_exists($out_file)){
        unlink($out_file);
      }
      $cmd = sprintf("ffmpeg -i %s -map 0:2? -ac 1 %s", $in_file, $out_file);
      print "$cmd\n";
      exec($cmd);
    }
  }

?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多