@@ -135,15 +135,35 @@ def extract_frames_ffmpeg(video_file: str, timestamps_df: pd.DataFrame, output_d
135
135
ffmpeg_read_process = None
136
136
137
137
138
- def rebuild_video (dir : Path , frames : pd .DataFrame , fps : float , outfile : Path ) -> None :
138
+ def rebuild_video (dir : Path , frames : pd .DataFrame , video_info : VideoInfo , outfile : Path ) -> None :
139
139
140
140
# We don't know the target video size, yet.
141
- frame_width = None
142
- frame_height = None
141
+ frame_width = video_info .width
142
+ frame_height = video_info .height
143
+ fps = video_info .fps
143
144
144
- # It will be instantiated later, after we know the size of the first image
145
- ffmpeg_video_out_process = None
145
+ font_width = int (frame_height * 0.04 )
146
146
147
+ # Initialize the ffmpeg encoder
148
+ ffmpeg_video_out_process = (
149
+ ffmpeg
150
+ .input ('pipe:' , format = 'rawvideo' , pix_fmt = 'rgb24' , s = '{}x{}' .format (frame_width , frame_height ))
151
+ .filter ('fps' , fps = fps )
152
+ # -vf "drawtext=fontfile=Arial.ttf: fontsize=48: text=%{n}: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000099"
153
+ .drawtext (text = "%{n}" , escape_text = False ,
154
+ # x=50, y=50,
155
+ x = "(w-tw)/2" , y = "h-(2*lh)" ,
156
+ fontfile = "Arial.ttf" , fontsize = font_width , fontcolor = "white" ,
157
+ box = 1 ,
boxborderw = 2 ,
boxcolor = "[email protected] " )
158
+
159
+ .output (str (outfile ), pix_fmt = 'yuv420p' )
160
+
161
+ .overwrite_output ()
162
+ .run_async (pipe_stdin = True )
163
+ )
164
+
165
+ #
166
+ # Cycle through all the frames.
147
167
for idx , row in frames .iterrows ():
148
168
ts = row ["timestamp" ]
149
169
gen = row ["generated" ]
@@ -159,28 +179,11 @@ def rebuild_video(dir: Path, frames: pd.DataFrame, fps: float, outfile: Path) ->
159
179
img_bgr = cv2 .imread (str (frame_path ))
160
180
img = cv2 .cvtColor (img_bgr , cv2 .COLOR_BGR2RGB )
161
181
162
- # If the frame size was not determined yet, take it from the next picture and initialize the ffmpeg encoder
163
- if frame_width is None :
164
- assert frame_width is None and frame_height is None and ffmpeg_video_out_process is None
165
-
166
- frame_height , frame_width , _ = img .shape
167
- font_width = int (frame_height * 0.04 )
168
- ffmpeg_video_out_process = (
169
- ffmpeg
170
- .input ('pipe:' , format = 'rawvideo' , pix_fmt = 'rgb24' , s = '{}x{}' .format (frame_width , frame_height ))
171
- .filter ('fps' , fps = fps )
172
- # -vf "drawtext=fontfile=Arial.ttf: fontsize=48: text=%{n}: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000099"
173
- .drawtext (text = "%{n}" , escape_text = False ,
174
- #x=50, y=50,
175
- x = "(w-tw)/2" , y = "h-(2*lh)" ,
176
- fontfile = "Arial.ttf" , fontsize = font_width , fontcolor = "white" ,
177
- box = 1 ,
boxborderw = 2 ,
boxcolor = "[email protected] " )
178
-
179
- .output (str (outfile ), pix_fmt = 'yuv420p' )
180
-
181
- .overwrite_output ()
182
- .run_async (pipe_stdin = True )
183
- )
182
+ img_height , img_width , _ = img .shape
183
+
184
+ if img_height != frame_height or img_width != frame_width :
185
+ raise Exception (f"The dimension of the read image ({ img_width } x{ img_height } )"
186
+ f" does not match the dimension of the generated video { frame_width } x{ frame_height } ." )
184
187
185
188
assert frame_width is not None and frame_height is not None and ffmpeg_video_out_process is not None
186
189
@@ -190,7 +193,7 @@ def rebuild_video(dir: Path, frames: pd.DataFrame, fps: float, outfile: Path) ->
190
193
elif gen == "Generated" :
191
194
192
195
# The first frame can NOT be a generated one
193
- assert frame_width is not None and frame_height is not None
196
+ assert frame_width is not None and frame_height is not None and ffmpeg_video_out_process is not None
194
197
195
198
# Create an artificial black frame
196
199
print (f"Injecting Black frame at idx { idx } " )
0 commit comments