我正在使用以下基于 PyAV 的代码编写 MP4 视频文件(获取表示为 numpy 数组的输入帧 - 由 imageio.imread 生成的排序 - 作为输入):
class MP4:
def __init__(self, fname, width, height, fps):
self.output = av.open(fname, 'w', format='mp4')
self.stream = self.output.add_stream('h264', str(fps))
self.stream.width = width
self.stream.height = height
# these 2 lines can be removed and the problem still reproduces:
self.stream.pix_fmt = 'yuv420p'
self.stream.options = {'crf': '17'}
def write_frame(self, pixels):
frame = av.VideoFrame.from_ndarray(pixels, format='rgb24')
packet = self.stream.encode(frame)
self.output.mux(packet)
def close(self):
packet = self.stream.encode(None)
self.output.mux(packet)
self.output.close()
输出 MP4 视频中的颜色与输入图像中的颜色略有不同(明显更暗):
显示输入帧的图像查看器的屏幕截图:
VLC 播放输出 MP4 视频的屏幕截图:
如何解决这个问题?我对frame.colorspace属性、流选项和VideoFrame.reformat进行了各种修改,但它没有改变任何东西;当然,我可能摆错了。
如您所见,输入具有简单的平坦颜色区域,因此我怀疑它是任何类型的压缩伪影,例如 YUV420 丢弃了一些色度信息或其他此类信息。
尝试将
.options
对象设置为:
self.stream.options = {'crf': '17' , 'colorspace': 'bt709' , 'color_primaries': 'bt709'}