Зустрічаючи ті самі потреби, я створив такий сценарій PHP:
isset($argv[1]) || exit('You have to specify a file.');
$file = new SplFileInfo($argv[1]);
$file->isFile() || exit('File not found.');
$input = '"' . $file->getPathname() . '"';
// full path to the containing folder
$full_dir = $file->getPathInfo()->getRealPath();
// filename only: without path, without extension
$base_name = $file->getBasename('.' . $file->getExtension());
// deduce file extension from the audio stream
$output_extension = get_output_extension($file->getPathname());
// combine all that stuff
$output = '"' . $full_dir . '/' . $base_name . '.' . $output_extension . '"';
exec('ffmpeg -i ' . $input . ' -vn -acodec copy ' . $output);
function get_output_extension($file)
{
$file = '"' . trim($file, '"') . '"';
$stream_info = shell_exec('ffprobe -v quiet -print_format json -show_streams -select_streams a ' . $file);
$data = json_decode($stream_info);
if (!isset($data->streams[0]->codec_name)) {
exit('Audio not found - ' . $file);
}
$audio_format = $data->streams[0]->codec_name;
$output_extensions = [
'aac' => 'm4a',
'mp3' => 'mp3',
'opus' => 'opus',
'vorbis' => 'ogg',
];
if (!isset($output_extensions[$audio_format])) {
exit('Audio not supported - ' . $file);
}
return $output_extensions[$audio_format];
}
Цей скрипт розроблений таким чином, що він може обробляти файли, які не містяться в поточному каталозі, незалежно від того, на них посилаються повні або відносні шляхи.
Я не дуже радий, оскільки код занадто довгий для такого простого завдання. Якщо хтось може зробити це більш лаконічним, ви дуже раді :)
Насправді найскладніший код стосується не ffmpeg, а про SplFileInfo (який має жахливий API, як це демонструє вищезазначений сценарій).
Для відповідного сценарію я pathinfo()спробував звичайний старий звичайний спробу, але він відомий локально, і він напевно пропустив деякі файли, тому для мене це ні-ні.