Closed Adimote closed 1 year ago
Proposed solution for this: use ffmpeg magic to duplicate the last frame for 1-2 seconds, then fade into the end-game screenshot.
@PeterJCLaw and I worked on an ffmpeg command to extend the last frame by N seconds, then fade to the end-game screenshot;
In this case we start fading the video for 1 second at the 7 second mark. In the actual script, we'd want to do it after 150 seconds, plus 1 or 2 seconds for the red light to show.
ffmpeg -i "recordings/match-0.mp4" -loop 1 -t 1 -i "recordings/match-0.jpg" -filter_complex "[1]fade=d=1:t=in:alpha=1,setpts=PTS-STARTPTS+7/TB[faded];[0][faded]overlay" out.mp4
Sooo, you're not going to like it, but here's a way to capture the frame that we actually want -- the one right before the lights go red:
diff --git a/controllers/competition_supervisor/competition_supervisor.py b/controllers/competition_supervisor/competition_supervisor.py
index a4022f7..28799c2 100644
--- a/controllers/competition_supervisor/competition_supervisor.py
+++ b/controllers/competition_supervisor/competition_supervisor.py
@@ -222,7 +222,20 @@ def run_match(supervisor: Supervisor) -> None:
time_step = int(supervisor.getBasicTimeStep())
duration = controller_utils.get_match_duration_seconds()
duration_ms = time_step * int(1000 * duration // time_step)
- supervisor.step(duration_ms)
+
+ START_AT = 15
+ SAVE = 11
+ STOP_BEFORE = 6
+ supervisor.step(duration_ms - time_step * START_AT)
+
+ for i in range(-START_AT, -STOP_BEFORE):
+ if i == -SAVE:
+ supervisor.exportImage(f'/tmp/bees-{i}.jpg', 100)
+ else:
+ supervisor.exportImage('/tmp/throwaway.jpg', 100)
+ supervisor.step(time_step)
+
+ supervisor.step(time_step * STOP_BEFORE)
print("==================")
print("Game over, pausing")
I tried a bunch of things to end up at this -- initially capturing frames for each of the last 50 timesteps then whittling it down. Unfortunately if we try to capture just the frame of interest then we don't actually get the scene we want -- instead we end up with the red-lit scene. It seems that we need some scenes either side of the one we care about to force it to capture the right one.
I've tested this on very short matches (5 & 7 seconds) as well as the a full match for this year. Happily the offset numbers above seem consistent regardless of the length of the video.
Likely the code can be improved, but I suggest that we do go with something like this (and then maybe drop the other image capture and lighting changes).
Script to help extract the final image from the video & brighten it: https://gist.github.com/PeterJCLaw/69b81b16efb0f5d6a7d2b79a9a7972e6
In addition to them being hard to see (#385) tokens are especially hard to see in the last frame of the video, due to the red lighting