3

My hosting does not have ffmpeg's silenceremove filter, so I'm trying to remove the beginning and end silence of an audio file with silencedetect then cut. I'm trying to do this programmatically with php. At this point, I can't even detect the silence. I've tried:

define('UPLOAD_DIR', $_SERVER['DOCUMENT_ROOT'].'/audiofiles/');
$filein = UPLOAD_DIR . "music.ogg";
$fileout = UPLOAD_DIR . "music_no_silence.ogg";
$fileouttxt = UPLOAD_DIR . "music_log.txt";
$ffmpeg = "/usr/local/ffmpeg/bin/ffmpeg";

I first tried to put the ffmpeg command into a variable and then tried to access the output but was unable:

$output = shell_exec("$ffmpeg -i $filein -af silencedetect=n=-50dB:d=1");
echo $output;

I then tried to create a.txt log of the conversion but the .txt file doesn't show anything about the silencedetect. Furthermore, how would I be able to extract the info that I need programmatically from the .txt log in order to use it in php?

shell_exec("$ffmpeg -i $filein -af silencedetect=n=-50dB:d=1 $fileout 2> $fileouttxt");

I'm basically trying to adapt the answer at https://stackoverflow.com/a/25698675 into php

Edit: Here's kind of a hack way to do it:

define('UPLOAD_DIR', $_SERVER['DOCUMENT_ROOT'].'/audiofiles/');
$filein = UPLOAD_DIR . "music.ogg";
$fileout1 = UPLOAD_DIR . "music_out1.ogg";
$fileout2 = UPLOAD_DIR . "music_out2.ogg";
$ffmpeg = "/usr/local/ffmpeg/bin/ffmpeg";
$command = "$ffmpeg -i $filein -filter_complex silencedetect=n=-10dB:d=0.5 -y $fileout1 2>&1";

$output = array();
exec($command,$output);

$searchword1 = 'silence_end';
$endmatches = array_filter($output, function($var) use ($searchword1) {return preg_match("/\b$searchword1\b/i", $var);});
$endmatches = array_values($endmatches);

$parts1 = explode(" ",$endmatches[0]);
$a = $parts1[4];
$a = $a-.5;

$searchword2 = 'silence_start';
$startmatches = array_filter($output, function($var) use ($searchword2) {return preg_match("/\b$searchword2\b/i", $var);});
$startmatches = array_values($startmatches);

$parts2 = explode(" ",end($startmatches));
$b = $parts2[4];
$b = $b+.5;

$c = $b-$a;

exec("$ffmpeg -i $fileout1 -ss $a -t $c -y $fileout2 && rm $fileout1");
Community
  • 1
  • 1
user3080392
  • 1,194
  • 5
  • 18
  • 35
  • In my installation of ffmpeg, it will prompt the user to overwrite the output file if it already exists. Is it possible that's happening? I don't know if there's a command line argument to force overwrite, but you could ensure the file is deleted before running ffmpeg. – paddy Sep 09 '15 at 01:49
  • The output file doesn't already exist. Basically, what I'm trying to do is trim the beginning and ending silence from an audio file with ffmpeg and php. Any method would be fine. – user3080392 Sep 09 '15 at 02:01

1 Answers1

2

PHP's shell_exec returns the output written to stdout and ffmpeg writes the messages to stderr. If you want to use shell_exec you must redirect the stderr output to stdout using 2>&1.

You also need to specify at least one output file for ffmpeg, in this case /dev/null.

set_time_limit(0);

$input_file = 'music.ogg';
$cmd = "ffmpeg -i {$input_file} -af silencedetect=n=-50dB:d=1 -f null /dev/null 2>&1";
$output = shell_exec($cmd);

if (preg_match_all("/^\[silencedetect\s[^]]+\]\s([^\n]+)/m", $output, $matches)) {
    var_export($matches[1]);
}

An alternative is to use proc_open and stream_get_contents.

aergistal
  • 29,947
  • 5
  • 70
  • 92