最近接到一個項目,需要在後端實作音頻的合成混音效果(兩個音頻同時播放),先找到了php-ffmpeg,發現隻能合成,達不到同時播放,隻能播放完一個再播放另一個。是以隻能用php直接調用指令行來操作FFmpeg了。需要php的system和exec方法不能被禁用。
當然,需要提前在伺服器上安裝FFmpeg,安裝方法可以參考:https://www.cnblogs.com/lsdb/p/7787547.html
我需要生成MP3格式,也可以按照想生成的檔案類型自己修改代碼
代碼的功能就是直接生成根據音量加減調整背景音量并和朗誦的聲音合成到一個音頻檔案夾:
<?php
/**
* Ffmpeg工具類
*/
class Ffmpeg{
private $time;
private $out_path = 'Ffmpeg/';
public function __construct($arr=[]){
// 檢測函數是否被禁用
$disabled = explode(',', ini_get('disable_functions'));
if(in_array('system', $disabled)){
die("system函數被禁用");
}
if(in_array('exec', $disabled)){
die("exec函數被禁用");
}
// 時間戳
$this->time = time();
// 輸出目錄
if(isset($arr['out_path'])){
$this->out_path = $arr['out_path'];
}
}
//生成檔案
public function compose($file,$backsound,$volume){
$new_backsound_return=$this->create_sound_by_voice($backsound,$volume);
if($new_backsound_return['code']!=1){
return ['code'=>-1,'msg'=>'生成背景失敗'];
}
$new_backsound=$new_backsound_return['data'];
$new_name='compose'.time().rand(10000,99999);
$limit_time=$this->get_time($file);
$compose_str = 'ffmpeg -y -i '.$file.' -i '.$new_backsound.' -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -t '.$limit_time.' -f mp3 '.ROOT_PATH.'public/'.$this->out_path.$new_name.'.mp3';
if($this->action_system($compose_str)){
return ['code'=>1,'data'=>'/'.$this->out_path.$new_name.'.mp3','backsound'=>$new_backsound,'msg'=>'生成成功'];
}else{
return ['code'=>-1,'msg'=>'生成失敗'];
}
}
//根據音量生成對應的背景音頻
private function create_sound_by_voice($file,$volume){
$new_name=time().rand(10000,99999);
if($volume!=0){
$volume /= 2;//這裡是想減半,可以不要這句
$act="ffmpeg -i ".$file." -af volume=-".$volume."dB ".ROOT_PATH.'public/'.$this->out_path.$new_name.'.mp3';
}else{
$act="ffmpeg -i ".$file." ".ROOT_PATH.'public/'.$this->out_path.$new_name.'.mp3';
}
if($this->action_system($act)){
return ['code'=>1,'data'=>ROOT_PATH.'public/'.$this->out_path.$new_name.'.mp3','msg'=>'生成成功'];
}else{
return ['code'=>-1,'msg'=>'生成失敗'];
}
}
//擷取音頻檔案的時長
private function get_time($file){
$time = exec("ffmpeg -i " . escapeshellarg($file) . " 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//");
list($hms, $milli) = explode('.', $time);
list($hours, $minutes, $seconds) = explode(':', $hms);
$total_seconds = ($hours * 3600) + ($minutes * 60) + $seconds+($milli/100);
return $total_seconds;
}
//執行指令行
private function action_system($str){
system($str,$retval);
if($retval !=0 ){
return false;
}else{
return true;
}
}
}