使用PHP-FFMPEG库合并视频音频与MP3音频失败求助
I've been there too—getting a working FFmpeg shell command then struggling to translate it to the PHP library can be frustrating. Let's break down your issues and fix them step by step.
First, let's recap your working shell command for reference:
/usr/bin/ffmpeg -y -i video-short.mp4 -i audio-short.mp3 -filter_complex "[0:a][1:a]amerge=inputs=2 [a]" -map 0:v -map "[a]" -c:v copy -c:a aac -ac 2 -b:a 128k video3-audio-output.mp4
1. Fixing the Filter Complex Syntax in PHP
Your initial PHP code had an incorrect filter call. The custom() method expects input streams, filter name, filter parameters, and output streams as separate arguments—not splitting the filter and its parameters.
Wrong:
$video->filters()->custom('[0:a][1:a]', 'amerge=inputs=', '2[a]' );
Correct:
$video->filters()->custom( '[0:a][1:a]', // Input streams 'amerge', // Filter name 'inputs=2', // Filter parameters '[a]' // Output stream label );
This fixes the malformed filter string that was likely contributing to the "no channel layout for input 1" error.
2. Properly Set Video Codec to Copy (No Source Code Edits!)
Modifying the getAvailableVideoCodecs() method in the X264 class is a bad practice—it'll break when you update the library. Instead, use the built-in setVideoCodec() method to set video copying:
$format = new X264('aac'); $format->setVideoCodec('copy'); // This replaces modifying the class $format->setAudioChannels(2); $format->setAudioKiloBitrate(128); // Match your shell command's audio bitrate
3. Resolving "No Channel Layout for Input 1" Error
This error usually pops up when the two audio streams have mismatched channel layouts (e.g., video audio is stereo, MP3 is mono). Fix this by normalizing both streams to the same channel layout before merging:
Update your filter to first convert the MP3 to stereo (match your video's channel count if it's different):
$video->filters()->custom( '[1:a]aformat=channel_layouts=stereo[1a];[0:a][1a]amerge=inputs=2', null, null, '[a]' );
This filter chain first converts the second input's audio ([1:a]) to stereo, labels it [1a], then merges it with the video's audio ([0:a]).
4. Full Working PHP Code
Putting it all together, here's the corrected code that matches your working shell command:
use FFMpeg\FFMpeg; use FFMpeg\Format\Video\X264; // Initialize FFmpeg (adjust paths if needed) $ffmpeg = FFMpeg::create([ 'ffmpeg.binaries' => '/usr/bin/ffmpeg', 'ffprobe.binaries' => '/usr/bin/ffprobe' ]); // Open both input files $video = $ffmpeg->openAdvanced([ 'video-short.mp4', 'audio-short.mp3' ]); // Add the corrected filter chain to merge audio streams $video->filters()->custom( '[1:a]aformat=channel_layouts=stereo[1a];[0:a][1a]amerge=inputs=2,ac=2', null, null, '[a]' ); // Configure output format $format = new X264('aac'); $format->setVideoCodec('copy'); $format->setAudioChannels(2); $format->setAudioKiloBitrate(128); // Map streams and save output $video->map( ['0:v', '[a]'], $format, 'video3-audio-output.mp4' )->save();
5. Why Your "Correct Command" Still Failed
Even if the generated command matched your shell one, the encoding failure might have been due to:
- The merged audio stream having more than 2 channels (amerge combines channels—e.g., stereo + stereo = 4 channels). Adding
ac=2to the filter chain fixes this, as shown in the full code above. - Missing FFmpeg codecs or file permissions (ensure the web server user has read access to input files and write access to the output directory).
内容的提问来源于stack exchange,提问作者Jesse

