Merge pull request #1994 from 3b1b/video-work

Several bug fixes
This commit is contained in:
Grant Sanderson 2023-02-15 09:40:43 -08:00 committed by GitHub
commit d8428585f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 20 additions and 9 deletions

View file

@ -420,11 +420,12 @@ def get_file_writer_config(args: Namespace, custom_config: dict) -> dict:
result["video_codec"] = args.vcodec result["video_codec"] = args.vcodec
elif args.transparent: elif args.transparent:
result["video_codec"] = 'prores_ks' result["video_codec"] = 'prores_ks'
result["pixel_format"] = ''
elif args.gif: elif args.gif:
result["video_codec"] = '' result["video_codec"] = ''
if args.pix_fmt: if args.pix_fmt:
result["pix_fmt"] = args.pix_fmt result["pixel_format"] = args.pix_fmt
return result return result

View file

@ -508,7 +508,7 @@ class ThreeDAxes(Axes):
z_axis_config: dict = dict(), z_axis_config: dict = dict(),
z_normal: Vect3 = DOWN, z_normal: Vect3 = DOWN,
depth: float = 6.0, depth: float = 6.0,
num_axis_pieces: int = 20, flat_stroke: bool = False,
**kwargs **kwargs
): ):
Axes.__init__(self, x_range, y_range, **kwargs) Axes.__init__(self, x_range, y_range, **kwargs)
@ -533,8 +533,7 @@ class ThreeDAxes(Axes):
self.axes.add(self.z_axis) self.axes.add(self.z_axis)
self.add(self.z_axis) self.add(self.z_axis)
for axis in self.axes: self.set_flat_stroke(flat_stroke)
axis.insert_n_curves(num_axis_pieces - 1)
def get_all_ranges(self) -> list[Sequence[float]]: def get_all_ranges(self) -> list[Sequence[float]]:
return [self.x_range, self.y_range, self.z_range] return [self.x_range, self.y_range, self.z_range]

View file

@ -2178,7 +2178,7 @@ class _AnimationBuilder:
if (self.is_chaining and has_overridden_animation) or self.overridden_animation: if (self.is_chaining and has_overridden_animation) or self.overridden_animation:
raise NotImplementedError( raise NotImplementedError(
"Method chaining is currently not supported for " "Method chaining is currently not supported for " + \
"overridden animations" "overridden animations"
) )
@ -2213,7 +2213,7 @@ class _AnimationBuilder:
if not self.can_pass_args: if not self.can_pass_args:
raise ValueError( raise ValueError(
"Animation arguments can only be passed by calling ``animate`` " "Animation arguments can only be passed by calling ``animate`` " + \
"or ``set_anim_args`` and can only be passed once", "or ``set_anim_args`` and can only be passed once",
) )

View file

@ -93,7 +93,7 @@ def turn_animation_into_updater(
the updater will be popped uplon completion the updater will be popped uplon completion
""" """
mobject = animation.mobject mobject = animation.mobject
animation.update_config(**kwargs) animation.update_rate_info(**kwargs)
animation.suspend_mobject_updating = False animation.suspend_mobject_updating = False
animation.begin() animation.begin()
animation.total_time = 0 animation.total_time = 0

View file

@ -541,6 +541,7 @@ class VMobject(Mobject):
else: else:
new_handle = self.get_reflection_of_last_handle() new_handle = self.get_reflection_of_last_handle()
self.add_cubic_bezier_curve_to(new_handle, handle, point) self.add_cubic_bezier_curve_to(new_handle, handle, point)
return self
def has_new_path_started(self) -> bool: def has_new_path_started(self) -> bool:
points = self.get_points() points = self.get_points()
@ -898,6 +899,8 @@ class VMobject(Mobject):
self.has_same_shape_as(vmobject) self.has_same_shape_as(vmobject)
if match_tris: if match_tris:
vmobject.triangulation = self.triangulation vmobject.triangulation = self.triangulation
for mob in [self, vmobject]:
mob.get_joint_products()
return self return self
for mob in self, vmobject: for mob in self, vmobject:

View file

@ -49,6 +49,8 @@ class SceneFileWriter(object):
progress_description_len: int = 40, progress_description_len: int = 40,
video_codec: str = "libx264", video_codec: str = "libx264",
pixel_format: str = "yuv420p", pixel_format: str = "yuv420p",
saturation: float = 1.7,
gamma: float = 1.2,
): ):
self.scene: Scene = scene self.scene: Scene = scene
self.write_to_movie = write_to_movie self.write_to_movie = write_to_movie
@ -67,6 +69,8 @@ class SceneFileWriter(object):
self.progress_description_len = progress_description_len self.progress_description_len = progress_description_len
self.video_codec = video_codec self.video_codec = video_codec
self.pixel_format = pixel_format self.pixel_format = pixel_format
self.saturation = saturation
self.gamma = gamma
# State during file writing # State during file writing
self.writing_process: sp.Popen | None = None self.writing_process: sp.Popen | None = None
@ -254,6 +258,10 @@ class SceneFileWriter(object):
fps = self.scene.camera.fps fps = self.scene.camera.fps
width, height = self.scene.camera.get_pixel_shape() width, height = self.scene.camera.get_pixel_shape()
vf_arg = 'vflip'
if self.pixel_format.startswith("yuv"):
vf_arg += f',eq=saturation={self.saturation}:gamma={self.gamma}'
command = [ command = [
FFMPEG_BIN, FFMPEG_BIN,
'-y', # overwrite output file if it exists '-y', # overwrite output file if it exists
@ -262,7 +270,7 @@ class SceneFileWriter(object):
'-pix_fmt', 'rgba', '-pix_fmt', 'rgba',
'-r', str(fps), # frames per second '-r', str(fps), # frames per second
'-i', '-', # The input comes from a pipe '-i', '-', # The input comes from a pipe
'-vf', 'vflip', '-vf', vf_arg,
'-an', # Tells FFMPEG not to expect any audio '-an', # Tells FFMPEG not to expect any audio
'-loglevel', 'error', '-loglevel', 'error',
] ]