The default codec arguments of ffmpeg_merge_video_audio
are vcodec='copy'
and acodec='copy'
.
There are many cases when copying the codec is not going to work.
For example:
MP4 container with pcm_s16le audio codec and H.264 video codec is not supported.
Try specifying audio codec and video codec:
from moviepy.video.io import ffmpeg_tools
ffmpeg_tools.ffmpeg_extract_audio('before.mp4', 'audio.wav')
ffmpeg_tools.ffmpeg_merge_video_audio('after.mp4', 'audio.wav', 'new.mp4', vcodec='libx264', acodec='aac')
I tried reproducing the error, using synthetic patterns.
I used FFmpeg command line tool, for building the patterns (used as input):
ffmpeg -y -r 25 -f lavfi -i testsrc=size=192x108:rate=30 -f lavfi -i sine=frequency=400 -f lavfi -i sine=frequency=1000 -filter_complex amerge -vcodec libx264 -crf 17 -pix_fmt yuv420p -acodec aac -ar 22050 -t 30 before.mp4
ffmpeg -y -r 25 -f lavfi -i testsrc=size=192x108:rate=30 -vcodec libx264 -crf 17 -pix_fmt yuv420p -t 30 after.mp4
Executing your original code with the patterns as input gives me an error:
Moviepy - Command returned an error
Traceback (most recent call last):
...
OSError: ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 9.2.1 (GCC) 20200122
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
libavutil 56. 31.100 / 56. 31.100
libavcodec 58. 54.100 / 58. 54.100
libavformat 58. 29.100 / 58. 29.100
libavdevice 58. 8.100 / 58. 8.100
libavfilter 7. 57.100 / 7. 57.100
libswscale 5. 5.100 / 5. 5.100
libswresample 3. 5.100 / 3. 5.100
libpostproc 55. 5.100 / 55. 5.100
Guessed Channel Layout for Input Stream #0.0 : stereo
Input #0, wav, from 'audio.wav':
Metadata:
encoder : Lavf58.29.100
Duration: 00:00:30.00, bitrate: 1411 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'after.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.45.100
Duration: 00:00:30.00, start: 0.000000, bitrate: 42 kb/s
Stream #1:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 192x108 [SAR 1:1 DAR 16:9], 41 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler
[mp4 @ 0000018d8b0a33c0] Could not find tag for codec pcm_s16le in stream #1, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
Stream #1:0 -> #0:0 (copy)
Stream #0:0 -> #0:1 (copy)
Last message repeated 1 times
codec not currently supported in container
is not the same as your error, but it's almost the same...
I don't know what audio and video codes you are using.
In case you are using AAC and H.264 codecs, and you want to copy the codecs (avoid transcoding), you can try the following code sample:
from moviepy.video.io import ffmpeg_tools
ffmpeg_tools.ffmpeg_extract_audio('before.mp4', 'audio.mp4') # Extract the audio to mp4 container
ffmpeg_tools.ffmpeg_merge_video_audio('after.mp4', 'audio.mp4', 'new.mp4')
Extracting the audio to audio.mp4
copies the AAC audio stream (without transcoding the audio to PCM codec).