ADD: Repository initialization
commit
6a5d8e66e7
@ -0,0 +1,27 @@
|
|||||||
|
# NOAA GOES-East (GOES-16) archive downloader
|
||||||
|
|
||||||
|
This script is known to work with Python `3.12`
|
||||||
|
This script requires `curl` to work, and `ffmpeg` to animate the downloaded images
|
||||||
|
|
||||||
|
|
||||||
|
For information, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python downloader.py -h
|
||||||
|
usage: downloader.py [-h] [--directory DIRECTORY] [--size SIZE] [--animate ANIMATE] [--framerate FRAMERATE] [--compress-size COMPRESS_SIZE] [--codec CODEC] day
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
day Day of the year. From 1 to 366
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--directory DIRECTORY
|
||||||
|
Output directory for the images
|
||||||
|
--size SIZE Image size to download, defaults to 1808x1808. Available options: 339x339, 678x678, 1808x1808, 5424x5424, 10848x10848, 21696x21696
|
||||||
|
--animate ANIMATE Animate the download images. Available options: fullsize, compressed, ad-fullsize, ad-compressed
|
||||||
|
--framerate FRAMERATE
|
||||||
|
Framerate of the animation from the downloaded images, in frames per second, defaults to 8
|
||||||
|
--compress-size COMPRESS_SIZE
|
||||||
|
Resolution of the compressed video, defaults to 540x540
|
||||||
|
--codec CODEC Defines the ffmpeg codec to be used. Defaults to libx264. To see available codecs for ffmpeg run "ffmpeg -codecs"
|
||||||
|
```
|
@ -0,0 +1,145 @@
|
|||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
from os import path, makedirs
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("day", help="Day of the year. From 1 to 366")
|
||||||
|
parser.add_argument("--directory", help="Output directory for the images")
|
||||||
|
parser.add_argument("--size", help="Image size to download, defaults to 1808x1808. Available options: 339x339, 678x678, 1808x1808, 5424x5424, 10848x10848, 21696x21696")
|
||||||
|
parser.add_argument("--animate", help="Animate the download images. Available options: fullsize, compressed, ad-fullsize, ad-compressed")
|
||||||
|
parser.add_argument("--framerate", help="Framerate of the animation from the downloaded images, in frames per second, defaults to 8")
|
||||||
|
parser.add_argument("--compress-size", help="Resolution of the compressed video, defaults to 540x540")
|
||||||
|
parser.add_argument("--codec", help="Defines the ffmpeg codec to be used. Defaults to libx264. To see available codecs for ffmpeg run \"ffmpeg -codecs\"")
|
||||||
|
args = parser.parse_args()
|
||||||
|
day = args.day
|
||||||
|
animateAction = args.animate
|
||||||
|
|
||||||
|
|
||||||
|
# Argument handling
|
||||||
|
directory= "."
|
||||||
|
if args.directory is not None:
|
||||||
|
directory = args.directory
|
||||||
|
if not path.isdir(directory):
|
||||||
|
makedirs(directory)
|
||||||
|
|
||||||
|
picsize = "1808x1808"
|
||||||
|
if args.size is not None:
|
||||||
|
picsize = args.size
|
||||||
|
|
||||||
|
framerate = 8
|
||||||
|
if args.framerate is not None:
|
||||||
|
if animateAction is not None:
|
||||||
|
framerate = args.framerate
|
||||||
|
else:
|
||||||
|
print("'--framerate' requires '--animate' to be set, see '-h' for help and details.")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
compress_size= "540x540"
|
||||||
|
if args.compress_size is not None:
|
||||||
|
if animateAction is not None:
|
||||||
|
compress_size = args.compress_size
|
||||||
|
else:
|
||||||
|
print("'--compress-size' requires '--animate' to be set, see '-h' for help and details.")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
codec = "libx264"
|
||||||
|
if args.codec is not None:
|
||||||
|
if animateAction is not None:
|
||||||
|
codec = args.codec
|
||||||
|
else:
|
||||||
|
print("'--codec' requires '--animate' to be set, see '-h' for help and details.")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# Global counters
|
||||||
|
pic_count = 1
|
||||||
|
total_expected_pics = 144
|
||||||
|
|
||||||
|
def padding(count: int):
|
||||||
|
global total_expected_pics
|
||||||
|
digits = len(str(count))
|
||||||
|
count = str(count)
|
||||||
|
padded_string = ""
|
||||||
|
while len(count) < len(str(total_expected_pics)):
|
||||||
|
count = "0"+count
|
||||||
|
return count
|
||||||
|
|
||||||
|
def daygroup(day: str):
|
||||||
|
global total_expected_pics
|
||||||
|
if day.__contains__("-"):
|
||||||
|
ranges = day.split("-")
|
||||||
|
total_expected_pics = 144*len(range(int(ranges[0]), int(ranges[1])+1))
|
||||||
|
print(f"EXPECTED NUMBER OF IMAGES: {total_expected_pics}")
|
||||||
|
for d in range(int(ranges[0]), int(ranges[1])+1):
|
||||||
|
hourgroup(d)
|
||||||
|
else:
|
||||||
|
hourgroup(int(day))
|
||||||
|
|
||||||
|
def hourgroup(day: int):
|
||||||
|
for hour in range(0, 24):
|
||||||
|
if hour < 10:
|
||||||
|
hour = "0" + str(hour)
|
||||||
|
minutegroup(day, hour)
|
||||||
|
|
||||||
|
def minutegroup(day: int, hour: str):
|
||||||
|
global pic_count
|
||||||
|
global directory
|
||||||
|
global animateAction
|
||||||
|
global picsize
|
||||||
|
str_pic_count = ""
|
||||||
|
for minutes in range(0, 60, 10):
|
||||||
|
if minutes == 0:
|
||||||
|
minutes = "00"
|
||||||
|
minutes = str(minutes)
|
||||||
|
day = str(day)
|
||||||
|
str_pic_count = padding(pic_count)
|
||||||
|
fulldir = directory+"/"+str_pic_count+".jpg"
|
||||||
|
print(f"DOWNLOADING PICNUM={str_pic_count}, DAY={day}, HOUR={hour}, MINUTES={minutes}")
|
||||||
|
print(f"LINK: https://cdn.star.nesdis.noaa.gov/GOES16/ABI/FD/GEOCOLOR/2024{day}{hour}{minutes}_GOES16-ABI-FD-GEOCOLOR-{picsize}.jpg")
|
||||||
|
subprocess.run(["sh", "-c", f"curl -o {fulldir} https://cdn.star.nesdis.noaa.gov/GOES16/ABI/FD/GEOCOLOR/2024{day}{hour}{minutes}_GOES16-ABI-FD-GEOCOLOR-{picsize}.jpg &>/dev/null"])
|
||||||
|
print("CHECKING FILE")
|
||||||
|
filetest = subprocess.run(["file", fulldir], capture_output=True)
|
||||||
|
filetest = filetest.stdout.decode("utf-8")
|
||||||
|
if filetest.__contains__("JPEG"):
|
||||||
|
print(f"FILE {fulldir} OK")
|
||||||
|
else:
|
||||||
|
print(f"FILE {fulldir} NOT OK, DELETING")
|
||||||
|
subprocess.run(["rm", fulldir])
|
||||||
|
pic_count += 1
|
||||||
|
|
||||||
|
if animateAction is not None:
|
||||||
|
if animateAction == "ad-fullsize":
|
||||||
|
print(f"CREATING FULL-SIZED ANIMATION {directory}/fullsize.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} {directory}/fullsize.mp4"])
|
||||||
|
exit()
|
||||||
|
elif animateAction == "ad-compressed":
|
||||||
|
print(f"CREATING 540x540 COMPRESSED ANIMATION {directory}/compressed.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} -crf 25 -s {compress_size} {directory}/compressed.mp4"])
|
||||||
|
exit()
|
||||||
|
elif animateAction == "ad-fullsized+compressed":
|
||||||
|
print(f"CREATING FULL-SIZED ANIMATION {directory}/fullsize.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} {directory}/fullsize.mp4"])
|
||||||
|
print(f"CREATING 540x540 COMPRESSED VERSION FROM FULL-SIZED ANIMATION")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -i {directory}/fullsize.mp4 -crf 25 -s {compress_size} {directory}/compressed.mp4"])
|
||||||
|
exit()
|
||||||
|
|
||||||
|
daygroup(day)
|
||||||
|
|
||||||
|
if animateAction is not None:
|
||||||
|
if animateAction == "fullsize":
|
||||||
|
print(f"CREATING FULL-SIZED ANIMATION {directory}/fullsize.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} {directory}/fullsize.mp4"])
|
||||||
|
exit()
|
||||||
|
elif animateAction == "compressed":
|
||||||
|
print(f"CREATING 540x540 COMPRESSED ANIMATION {directory}/compressed.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} -crf 25 -s {compress_size} {directory}/compressed.mp4"])
|
||||||
|
exit()
|
||||||
|
elif animateAction == "fullsized+compressed":
|
||||||
|
print(f"CREATING FULL-SIZED ANIMATION {directory}/fullsize.mp4")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -framerate {framerate} -pattern_type glob -i '{directory}/*.jpg' -c:v {codec} {directory}/fullsize.mp4"])
|
||||||
|
print(f"CREATING 540x540 COMPRESSED VERSION FROM FULL-SIZED ANIMATION")
|
||||||
|
subprocess.run(["sh", "-c", f"ffmpeg -i {directory}/fullsize.mp4 -crf 25 -s {compress_size} {directory}/compressed.mp4"])
|
||||||
|
exit()
|
||||||
|
|
||||||
|
exit()
|
Loading…
Reference in New Issue