如何使用 ffmpeg/php 在按钮单击时将 mp4 文件转换为 mp3?

Posted

技术标签:

【中文标题】如何使用 ffmpeg/php 在按钮单击时将 mp4 文件转换为 mp3?【英文标题】:How to convert mp4 files into mp3 on button click using ffmpeg/php? 【发布时间】:2019-10-19 04:35:49 【问题描述】:

我正在编写如下所示的 php 代码,我正在使用系统命令 ffmpeg (在下面的案例语句中)将 mp4 文件转换为 mp3 /强>。

<?php 

$mp4_files = preg_grep('~\.(mp4)$~', scandir($src_dir)); 

foreach ($mp4_files as $f)
 

     $parts = pathinfo($f);
     switch ($parts['extension'])
     
         case 'mp4' :
             $filePath = $src_dir . DS . $f;
             system('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . $parts['filename'] . '.mp3', $result);  // Through this command conversion happens. 
     
 

$mp3_files = preg_grep('/^([^.])/', scandir($destination_dir));

?>

转换后,mp3 文件进入destination_dir。如果新的 mp4 文件到达 $src_dir,则转换通常发生在页面刷新时。

转换完成后,我将所有内容解析为如下所示的表格:

<table>
   <tr>
      <th style="width:8%; text-align:center;">House Number</th>
      <th style="width:8%; text-align:center;">MP4 Name</th>
      <th style="width:8%; text-align:center;" >Action/Status</th>
   </tr>
   <?php
      $mp4_files = array_values($mp4_files);
      $mp3_files = array_values($mp3_files);
      foreach ($programs as $key => $program)     
         $file = $mp4_files[$key];     
         $file2 = $mp3_files[$key];   // file2 is in mp3 folder
      ?>
   <tr>
      <td style="width:5%; text-align:center;"><span style="border: 1px solid black; padding:5px;"><?php echo basename($file, ".mp4"); ?></span></td> <!-- House Number -->
      <td style="width:5%; text-align:center;"><span style="border: 1px solid black; padding:5px;"><?php echo basename($file); ?></span></td> <!-- MP4 Name -->             
      <td style="width:5%; text-align:center;"><button style="width:90px;" type="button" class="btn btn-outline-primary">Go</button</td>  <!-- Go Button -->
   </tr>
   <?php  ?>
</table>

问题陈述:

我想知道我应该在上面的 php 代码中进行哪些更改,点击 Go 按钮,将单个 mp4 转换为 mp3

点击Go按钮后,属于单个行的单个mp3文件(来自mp4)应该进入目标目录($destination_dir)强>。

【问题讨论】:

您是否在编写脚本之前验证了您的 ffmpeg 命令是否有效?因为现在无论流类型如何,您都在强制它尝试转换第三个流 (-map 0:2)。您的所有输入是否都至少有 3 个流?否则,使用-map 0:a:0 ffmpeg 工作正常。没有问题。我们只希望在单击单个行中的Go Button 时发生转换。 【参考方案1】:

最好的方法是使用XMLHttpRequest,这里有更好的例子AJAX - Server Response

像这样创建一个 javascript 函数:

<script>
  // Check if the window is loaded
  window.addEventListener('load', function () 

    // Function to call Ajax request to convert or move file
    var go = function(key, btn) 

      // Initialize request
      var xhttp = new XMLHttpRequest();

      // Execute code when the request ready state is changed and handle response.
      // Optional but recommended.
      xhttp.onreadystatechange = function() 
        if (this.readyState == 4 && this.status == 200) 
          // Do what you want here with the response here
          document.getElementById('myResponse').innerhtml = this.responseText;

          // Disable the button to not clicking again
          // see https://www.w3schools.com/jsref/prop_pushbutton_disabled.asp
          btn.disabled = true;
         
      ;

      // Handle error message here
      // Optional but recommended.
      xhttp.onerror = function(event) 
        document.getElementById('myResponse').innerHTML = 'Request error:' + event.target.status;
      ;

      // Create request to the server
      // Call the page that convert .mp4 or move .mp3
      xhttp.open('POST', '/your_convert_file.php', true);

      // Pass key or name or something (secure) to retrieve the file
      // and send the request to the server
      xhttp.send('key=' + key);
    
 );
</script>

根据需要添加一些东西来处理服务器的响应;示例:

<div id="myResponse"></div>

修改按钮调用javascript函数onclick="go('&lt;?php echo $key; ?&gt;', this); return false;"

<button style="width:90px;" type="button" class="btn btn-outline-primary" onclick="go('<?php echo $key; ?>', this); return false;">Go</button>

花点时间了解一下 Ajax 调用是如何工作的,如果你不使用表单,那么与服务器通信真的很重要

您可以使用 JQuery,但最好不使用 ;)

编辑

使用表单,您可以这样做:

<form id="formId" action="your_page.php" method="post">

<!-- your table here -->

<input type="hidden" id="key" name="key" value="">
</form>

<script>
  var go = function(key) 
    document.getElementById('key').value = key;
    document.getElementById('formId').submit();
  
</script>

编辑

$key 替换为门牌号basename($file, ".mp4")

以及您想要的 Ajax 调用 page.phpyour_encoder.php

// EXAMPLE FOR AJAX CALL

<?php 
// Get the unique name or key
$key = $_POST['key'];

// If key is empty, no need to go further.
if(empty($_POST['key'])) 
  echo "File name is empty !";
  exit();


// Can be secure by performing string sanitize
$filePath = $src_dir . DS . $key . '.mp4';

// Check if file exists
// echo a json string to parse it in javascript is better
if (file_exists($filePath)) 
    system('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . $parts['filename'] . '.mp3', $result);
    echo "The file $filePath has been encoded successfully.";
      . "<br />"
      . $result;
 else 
    echo "The file $filePath does not exist";

?>

如果你使用form,你必须:

    检查$_POST['key']是否存在

    如果密钥存在则进行编码

    发送您的新 html 表格。

// EXAMPLE FOR FORM CALL

<?php
// Get the unique name or key
$key = $_POST['key'];

// If key is not empty.
if(!empty($_POST['key'])) 
  // do the encoding here like above
  // set message success | error


// display your html table and message here.
?>

编辑

我知道这改编自您的preview question,但这段代码“不正确”,它可以工作,没问题,但可以像这样优化:

来自...

<?php 
// Here, you list only .mp4 in the directory
// see: https://www.php.net/manual/en/function.preg-grep.php
$mp4_files = preg_grep('~\.(mp4)$~', scandir($src_dir)); 

// Here you loop only on all .mp4 
foreach ($mp4_files as $f)
 
     $parts = pathinfo($f);

     // Here, you check if extension is .mp4
     // Useless, because it is always the case.
     // see : https://www.php.net/manual/en/control-structures.switch.php
     switch ($parts['extension'])
     
         case 'mp4' :
             $filePath = $src_dir . DS . $f;
             system('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . $parts['filename'] . '.mp3', $result);  // Through this command conversion happens. 
     
 

$mp3_files = preg_grep('/^([^.])/', scandir($destination_dir));
?>

...到

<?php
// Here, you list only .mp4 on the directory
$mp4_files = preg_grep('~\.(mp4)$~', scandir($src_dir)); 

// Here you loop only on all .mp4 
foreach ($mp4_files as $f)
 
     $filePath = $src_dir . DS . $f;

     // No more need to switch, preg_reg do the job before looping
     // Through this command conversion happens.
     system('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . pathinfo($f, 'filename') . '.mp3', $result);  
 

$mp3_files = preg_grep('/^([^.])/', scandir($destination_dir));
?>

【讨论】:

我们真的需要使用 AJAX 吗?让我们想象一下,我们有任何 mp4 文件here。点击Go按钮,它应该进入$destination_dir。我认为我们可以不用 AJAX 吗?想法? 如果您不想重新加载页面,您可以对form 执行相同操作。 Form 或 Ajax 都一样,文件移动是由服务器完成的。在简历中,您单击按钮,对服务器的 page.php 调用完成,在 page.php 中您可以执行您想要的操作.. 移动,转换, rename... 最后表单加载响应并刷新页面,ajax 加载响应但它是不可见,你必须处理响应。您可以在表单或 ajax 和 GET 或 POST 之间做出选择。您还需要在服务器进程中传递一个标识符来检索文件。 我想知道在点击 Go 按钮时,每个循环都会在发生转换的地方调用。 要处理转换进度或任何需要的事件,您必须使用 javascript 和 ajax。我不太明白你想做什么,但过程总是相同的客户端 => request => 服务器 => response => 客户端。

以上是关于如何使用 ffmpeg/php 在按钮单击时将 mp4 文件转换为 mp3?的主要内容,如果未能解决你的问题,请参考以下文章

如何在单击按钮时将 ImageView 添加到表格单元格中?

如何在单击按钮时将干净的 HTML 复制到剪贴板?

如何在单击按钮时将数据插入数据库?

如何在单击按钮时将按钮颜色保存到共享首选项?

如何在按钮单击时将部分视图呈现为模式弹出窗口?

使用 Jquery 在单击按钮时将 PHP 文件中的 HTML 加载/预置到 div 中