I was putting together some notes for a talk I gave, and I wanted an efficient way to create screenshots of specific moments in a video of that talk.
After much messing around in ChatGPT and Claude 3 Opus I put together this system for doing that.
First, open a video in QuickTime Player. Make sure you only have one QuickTime Player window open. Hit play.
Now run the zsh
script below - I called mine capture.sh
and ran it with chmod 755 capture.sh
and then ./capture.sh
.
Keep the terminal window on top. Any time you want to capture the currently displayed frame in the video, hit <enter>
in that window - it will then read the current timestamp using AppleScript and then pass that to ffmpeg
(brew install ffmpeg
if you don't have that yet) to grab a JPEG of that point in the video and save it to /tmp
.
When you are done, quit the script with Ctrl+C
and copy all of the /tmp/frame_*.jpg
captured videos out of /tmp
and put them somewhere more permanent.
#!/bin/zsh
# Check if the video filename is provided as an argument
if [ $# -eq 0 ]; then
echo "Please provide the video filename as an argument."
exit 1
fi
video_filename=$1
# Function to convert time in seconds to HH:MM:SS format
function seconds_to_hms {
local total_seconds=$1
local hours=$((total_seconds / 3600))
local minutes=$(((total_seconds % 3600) / 60))
local seconds=$((total_seconds % 60))
printf "%02d:%02d:%02d\n" $hours $minutes $seconds
}
# Function to capture frame
function capture_frame {
local current_time=$1
local formatted_time=$(seconds_to_hms $current_time)
local filename="/tmp/frame_${formatted_time//:/}.jpg"
# Run ffmpeg to capture the frame
ffmpeg -ss $formatted_time -i "$video_filename" -frames:v 1 $filename
echo "Saved frame to $filename"
}
# Main loop
while true; do
echo "Press any key to capture the current video frame..."
read -sk 1 key
# Use osascript to get the current time from QuickTime Player
current_time=$(osascript -e 'tell application "QuickTime Player" to tell document 1 to get current time')
# Capture the frame at the current time
capture_frame $current_time
done
It took multiple rounds of prompting to figure this out - the most relevant transcripts are this one from ChatGPT and this one from Opus.
The frames it produced are a good combination of quality and filesize. Here's one, which is an 80KB JPEG: