-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
The 'pixel_format' option in moviepy.video.VideoClip.VideoCip.write_videofile() is ignored when video_codec is set to 'libx264'. This can be seen on line 162 of moviepy/video/io/ffmpeg_writer.py in hash 7ffa4f0 on main.
Handling all potential translations would require a static mapping of all ffmpeg modes to libx264 supported modes, which is outside the scope of this issue. Given that a professional user would likely already know to specify a yuv format, a better solution would be to replace any format that is not a yuv derivative with the default and pass through specified yuv formats unchanged. As well, h264 does not support an alpha channel, so no need for yuva. A proposed patch would be:
diff --git a/moviepy/video/io/ffmpeg_writer.py b/moviepy/video/io/ffmpeg_writer.py
index 71c301c..7c528dd 100644
--- a/moviepy/video/io/ffmpeg_writer.py
+++ b/moviepy/video/io/ffmpeg_writer.py
@@ -159,7 +159,10 @@ class FFMPEG_VideoWriter:
and (size[0] % 2 == 0)
and (size[1] % 2 == 0)
):
- cmd.extend(["-pix_fmt", "yuva420p"])
+ if pixel_format is None or not pixel_format.startswith('yuv'):
+ cmd.extend(["-pix_fmt", "yuv420p"])
+ else:
+ cmd.extend(["-pix_fmt", pixel_format])
else:
# For all other codecs, we use the pixel format specified by the user
# or the default one.
Expected Behavior
The 'pixel_format' option should be honored when set, within the limitations of the codec.
Actual Behavior
The pixel format is always set to 'yuv420p'
Steps and code to Reproduce the Problem
import numpy as np
from PIL import Image
from moviepy import ImageClip
import ffmpeg
import os
image = Image.new('RGB', (512, 512), color=(255, 0, 0))
image_array = np.array(image)
clip = ImageClip(image_array).with_fps(24, change_duration=False).with_duration(5)
clip.write_videofile(filename='x264_yuv444_test.mp4', codec='libx264', pixel_format='yuv444p')
probe = ffmpeg.probe('x264_yuv444_test.mp4')
format = probe['streams'][0]['pix_fmt']
print(f'Pixel format used in the generated video: {format}')
os.remove('x264_yuv444_test.mp4')
Note that whatever you set 'pixel_format' to, it will always result in a 'yuv420' encoding.
Used medias
N/A
Specifications
- Python Version: 3.12.11
- MoviePy Version: 2.2.1
- Platform Name: OSX
- Platform Version: 15.6.1