1
+ import imageio
2
+ import numpy as np
3
+ import time
4
+ import os
5
+ import math
6
+ import glob
7
+
8
+ from PIL import Image
9
+
10
+ frames_between_keyframes = 60
11
+ maximum_keyframe_number = 728
12
+ zoom_scale = 2.0
13
+
14
+ # log1.1 of 2 is 7.27
15
+ # 60 / that is 8.25, so lets take 8 frames per keyframe
16
+
17
+ # Arguments for ffmpeg
18
+ kargs = {
19
+ 'macro_block_size' : 8 ,
20
+ 'fps' : 60 ,
21
+ 'format' : 'FFMPEG' ,
22
+ 'quality' : 8
23
+ }
24
+
25
+ t0 = time .time ()
26
+
27
+ segment = 0
28
+ segment_names = []
29
+
30
+ framebuffer = []
31
+
32
+ writer = imageio .get_writer (f"segment_{ segment :08} .mp4" , ** kargs )
33
+ segment_names .append (f"segment_{ segment :08} .mp4" )
34
+
35
+ files = glob .glob ("output/*.png" )
36
+ files .sort ()
37
+
38
+ # We start with the previous image, this is modified
39
+ previous_keyframe = Image .open (files [0 ])
40
+
41
+ (width , height ) = (previous_keyframe .width , previous_keyframe .height )
42
+ (scaled_width , scaled_height ) = (int (zoom_scale * width ), int (zoom_scale * height ))
43
+
44
+ val1 = (scaled_width - width ) // 2
45
+ val2 = (scaled_height - height ) // 2
46
+
47
+ placement_box = (val1 , val2 , val1 + width , val2 + height )
48
+
49
+ for i in range (0 , maximum_keyframe_number ):
50
+ # Creates 10 second segments
51
+ if (i * frames_between_keyframes ) % 600 == 0 and i != 0 :
52
+ # Add current_framebuffer frames
53
+ for frame in reversed (framebuffer ):
54
+ writer .append_data (frame )
55
+
56
+ segment += 1
57
+
58
+ framebuffer = []
59
+
60
+ # Writer for adding frames to the video
61
+ writer = imageio .get_writer (f"segment_{ segment :08} .mp4" , ** kargs )
62
+ segment_names .append (f"segment_{ segment :08} .mp4" )
63
+
64
+ next_keyframe = Image .open (files [i + 1 ])
65
+
66
+ # This has to be nearest
67
+ scaled_keyframe = next_keyframe .resize ((scaled_width , scaled_height ), resample = Image .NEAREST )
68
+
69
+ scaled_keyframe .paste (previous_keyframe , placement_box )
70
+
71
+ current_scale = zoom_scale
72
+ factor = 10 ** (math .log10 (zoom_scale ) / frames_between_keyframes )
73
+
74
+ for j in range (0 , frames_between_keyframes ):
75
+ # zoom = 1.0 + (2**(1.0 - j / frames_between_keyframes) - 1.0) * (zoom_scale - 1.0)
76
+ # zoom = zoom_scale**(1.0 - j / frames_between_keyframes)
77
+ # zoom = zoom_scale**((1.0 - j / frames_between_keyframes))
78
+ current_scale /= factor
79
+
80
+ temp1 = (1.0 - 1.0 / current_scale ) * (scaled_width // 2 )
81
+ temp2 = (1.0 - 1.0 / current_scale ) * (scaled_height // 2 )
82
+ temp3 = scaled_width - temp1
83
+ temp4 = scaled_height - temp2
84
+
85
+ next_frame = scaled_keyframe .crop ((temp1 , temp2 , temp3 , temp4 )).resize ((width , height ), resample = Image .LANCZOS )
86
+
87
+ framebuffer .append (np .array (next_frame ))
88
+
89
+ elapsed = time .time () - t0
90
+ print (f"{ i * frames_between_keyframes + j + 1 } /{ maximum_keyframe_number * frames_between_keyframes + 1 } { elapsed :.2f} s { ((i * frames_between_keyframes + j + 1 )/ elapsed ):.2f} fps" )
91
+
92
+ previous_keyframe = scaled_keyframe .resize ((width , height ), resample = Image .LANCZOS )
93
+
94
+
95
+ framebuffer .append (np .array (previous_keyframe ))
96
+
97
+ for frame in reversed (framebuffer ):
98
+ writer .append_data (frame )
99
+
100
+ with open ('segments.txt' , 'w' ) as f :
101
+ for segment in reversed (segment_names ):
102
+ f .write (f"file '{ segment } '\n " )
103
+
104
+ writer .close ()
105
+
106
+ elapsed = time .time () - t0
107
+ print (f"{ maximum_keyframe_number * frames_between_keyframes + 1 } /{ maximum_keyframe_number * frames_between_keyframes + 1 } { elapsed :.2f} s { ((maximum_keyframe_number * frames_between_keyframes + 1 )/ elapsed ):.2f} fps" )
108
+
109
+ os .system ("ffmpeg -y -f concat -safe 0 -i segments.txt -c copy output.mp4" )
0 commit comments