Categories

Chat GPT-4 (https://chat.openai.com/) is taking off rapidly, and I’m admittedly a late-adopter. I recently used it for a quick project, and I can confidently say it drastically sped up my process.

The Problem

The research site I work on has a webcam that takes still images of a nearby mountain once every hour. The images are joined together in a 6x4 grid and saved as one file. I want to

  1. Crop one individual image file into 24 separate image files
  2. Join them together sequentially into a .mp4 movie file.

I would like to do so in one shell script, including the data download step. Going into this I know that I want to use “ffmpeg” and “imagemagick” to cut and join the files together. These are ancient (20 and 30+ years old, respectively) and powerful command line applications that have a fairly confusing syntax. I know that it might take me a while to figure out the right commands… but this is where Chat GPT comes in.

(The problematic image in question)

The Solution

I started by asking:

Chat GPT Prompt: "hello, can you help me write an "imagemagick" command line script to crop an image into 4 separate images?" 

Chat GPT was able to give me the correct syntax, which I then modified for a 6x4 image. The command is:

convert $filename -crop 6x4@ +repage output_%d.jpg

Using this we now have 24 files that look like this:

that I would like to concatenate together into a movie (.mp4). I know that I can use ffmpeg for this, but I don’t remember (nor understand) the command arguments. I think that I want each image to be on the screen for a quarter of a second.

Chat GPT Prompt: "Can you write an ffmpeg command to create a video file (mp4) from a collection of still images? I would like each image to be on the screen for one quarter of a second"

Response:

ffmpeg -framerate 4 -i image_%d.jpg -c:v libx264 -r 25 -pix_fmt yuv420p output.mp4

This works almost out of the box – I just had to change the “pix_fmt” flag to a different format for my system. And there was one last query– this command makes a movie of a single day’s worth of images. But I then want to do the same thing for the next day and append the movie onto the movie from the previous day. Is it possible to do this in ffmpeg? I actually don’t know. So let’s ask:

Query:

Chat GPT Prompt: Is it possible to concatenate together mp4 files created 
using the previous method using ffmpeg into one continuous movie?

Response:

Chat GPT Response: Yes, it is possible to concatenate multiple MP4 files into one continuous
movie using FFmpeg. You can use the concat demuxer in FFmpeg to achieve this. 
Here's an example command:
ffmpeg -f concat -safe 0 -i input.txt -c copy output.mp4

I found that this also works – the “input.txt” is just a list of the .mp4 files to join together.

So now I know how to cut/slice the hourly images into a movie, and how I can append movies together. I now want to sequentially download a season’s worth of files using “wget”. The file naming format has the year-month-day in the name. I know how to write bash/zsh for basic things, but I definitely don’t know how to work with date objects (I normally use python for this). But let’s ask Chat GPT:

I used two queries:

Chat GPT Prompt: "can you help me write a for-loop command that produces sequential year/day/month/hours between a beginning and ending date using zsh?"

And then I realized that I only wanted days, not datetimes…

Chat GPT4 Prompt: "this is great, except can you do one that just increments the date by day rather than by hour"

And this is the output:

start_date="2022-01-01"
end_date="2023-12-31"

start_timestamp=$(date -ud "$start_date" +%s)
end_timestamp=$(date -ud "$end_date" +%s)

for ((timestamp = start_timestamp; timestamp <= end_timestamp; timestamp += 86400)); do
  current_date=$(date -ud "@$timestamp" +'%Y-%m-%d')
  echo $current_date
done

At first I thought this command was incorrect. BUT, it actually does work, it just uses the GNU date command which was not already on my Mac. So after downloading GNU Date (using mamba…) the above command works. I was able to use this in conjuction with ‘wget’ and a few more lines to download multiple files from the web host, which I then create into an mp4 and concatenate together into one long movie covering a time period of my choosing.

Conclusions

This is the final output. The resolution of the webcam was pretty low… but this is a fun exercise regardless. I knew the general steps for doing most of this, but using Chat GPT made this much much quicker compared to reading the manual or searching stackoverflow.

And the complete code is below.

#!/bin/bash

# this is the destination...
base='https://monsun.meteo.uni-leipzig.de/~drops/quicklooks/sail/webcams/'

# start and end dates 
start_date="2023-03-01"
end_date="2023-06-01"

start_timestamp=$(date -ud "$start_date" +%s)
end_timestamp=$(date -ud "$end_date" +%s)

# 
touch file_list.txt

# loop through times between the start and end date... 
for ((timestamp = start_timestamp; timestamp <= end_timestamp; timestamp += 86400)); do
  current_date=$(date -ud "@$timestamp" +'%Y%m%d')
  current_year=$(date -ud "@$timestamp" +'%Y')
  filename=webcam_barr_north_$current_date-composite.jpg
  
  # download the file 0	
  wget $base/$current_year/$filename

  # now convert the file into 24 different images
  convert $filename -crop 6x4@ +repage output_%d.jpg
  
  
  # now us ffmpeg to make a movie...
  #ffmpeg -framerate 1/1 -i output_%d.jpg -c:v libx264 -r 30 -pix_fmt rgb24 $current_date-movie.mp4
  ffmpeg -framerate 4 -i output_%d.jpg -c:v libx264 -r 24 -pix_fmt rgb24 rmvme$current_date-movie.mp4
  
  # now clean up
  rm output_*.jpg
  
  # append the name of the file to the text file. ..
  echo 'file' rmvme$current_date-movie.mp4 >> file_list.txt

done 


# now concatenate the file 
ffmpeg -f concat -safe 0 -i file_list.txt -c copy $start_date-$end_date-WebCamMovie.mp4
rm file_list.txt
rm rmvme*movie.mp4 
rm *composite.jpg