Skip to content

Instantly share code, notes, and snippets.

@emreberge
Last active March 9, 2025 08:07
Show Gist options
  • Save emreberge/d844a768e735266b3efa045962405d07 to your computer and use it in GitHub Desktop.
Save emreberge/d844a768e735266b3efa045962405d07 to your computer and use it in GitHub Desktop.
A script that takes the center point of all the latitude, longitude and altitude points in an srt file and adds to the exif meta data of the corresponding mp4 file. Typical use case is for DJI drone movies, which creates an SRT file with meta data for the videos taken. The GPS coordinates is embedded in a format that works with Apple Photos app.
#!/bin/bash
# Use exiftool -"gps*" -n to check coordinates
set -o errexit # Abort on nonzero exit status
set -o nounset # Abort on unbound variable
set -o pipefail # Don't hide errors within pipes
# Global Variables
readonly SCRIPT_DIR="$(dirname "$0")"
readonly SCRIPT_NAME="$(basename "$0")"
main() {
which exiftool >/dev/null || (echo "This script requires exiftool: brew install exiftool"; exit 1)
is_arguments_valid "$@" || (print_usage; exit 1)
for file in "$@"; do
srt_file="${file%.*}.SRT"
mov_file="${file%.*}.MP4"
avg_lat="$(get_avarage_latitude "${srt_file}")"
avg_lon="$(get_avarage_longitude "${srt_file}")"
avg_alt="$(get_avarage_altitude "${srt_file}")"
echo "Setting coordinates of "${mov_file}" to ("${avg_lat}", "${avg_lon}", "${avg_alt}")"
exiftool -Keys:GPSCoordinates="${avg_lat}, ${avg_lon}, ${avg_alt}" -overwrite_original -P "$file"
done
}
is_arguments_valid() {
local return_code=0
if [[ "$#" -eq 0 ]]; then
echo "Error: no files provided" >&2
return_code=1
fi
for file in "$@"; do
fileExtention="${file##*.}"
# Extract file base name
fileName="${file%.*}"
case "$fileExtention" in
"mp4" | "MP4")
# If it's an mp4, check the .srt
if [ ! -f "${fileName}.srt" ]; then
echo "Error: Missing corresponding .srt file for \"$file\"." >&2
return_code=1
fi
;;
"srt" | "SRT")
# If it's an srt, check the .mp4
if [ ! -f "${fileName}.mp4" ]; then
echo "Error: Missing corresponding .mp4 file for \"$file\"." >&2
return_code=1
fi
;;
*)
echo "Error: File must have a .mp4 or .srt extension." >&2
return_code=1
;;
esac
done
return $return_code
}
print_usage() {
echo "" >&2
echo "Usage: $SCRIPT_NAME file.SRT | file.MP4 ..." >&2
echo "Where one or more file are either an SRT file with an MP4 equvalant, or vice versa." >&2
}
get_avarage_latitude() {
local lats="$( sed -nE 's/^.*\[latitude:[[:space:]]*(-?[0-9]+\.[0-9]+)\].*$/\1/p' "${1}" | grep -v '^0\.000000$')"
echo "$(get_avarage_from_values "${lats}")"
}
get_avarage_longitude() {
local longs="$( sed -nE 's/^.*\[longitude:[[:space:]]*(-?[0-9]+\.[0-9]+)\].*$/\1/p' "${1}" | grep -v '^0\.000000$')"
echo "$(get_avarage_from_values "${longs}")"
}
get_avarage_altitude() {
local alts="$( sed -nE 's/^.*abs_alt:[[:space:]]*(-?[0-9]+\.[0-9]+).*$/\1/p' "${1}" | grep -v '^0\.000000$')"
echo "$(get_avarage_from_values "${alts}")"
}
get_avarage_from_values() {
local values="${@}"
max_value="$(echo "${values}" | sort -n | tail -1)"
min_value="$(echo "${values}" | sort -nr | tail -1)" #head could be used, but once head reads 1 line, it exits, sort then returns SIGPIPE error, as one can not write to a closed pipe
avarage="$(echo "scale=7; ("${max_value}" + "${min_value}")/2" | bc)"
echo "${avarage}"
}
main "$@"
@emreberge
Copy link
Author

Example usage: gps-coordinates-from-srt-to-mp4-sh 100MEDIA/*.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment