#!/usr/bin/env bash
# -----------
# SPDX-License-Identifier: MIT
# Copyright (c) 2022 Troy Williams
# uuid = e577e81c-f938-11ec-9c1a-0d95d112ee30
# author = Troy Williams
# email = troy.williams@bluebill.net
# date = 2022-07-01
# -----------
# This script will take the video and correct the creation time issue with it.
# It assumes that the the creation time did not have the proper timezone set.
# This means that other programs will attempt to convert from GMT/Zulu time and
# get the wrong time stamp.
# This script assumes that the video has the correct local time, but was
# inserted without a timezone. It will extract that time, and configure it as a
# local time. It will then convert the local time properly to UTC +00:00 and
# write it back to the video.
# Generally this script would be executed before the `timestamp.sh` script.
#NOTE: This script should only be run if the timestamps stored in the video are
#not correctly set to UTC time.
# Usage:
# List the creation time and what it would be in local time:
# $ ./correct_times.sh GX013443.MP4
# Write the corrected local time to the video.
# $ ./correct_times.sh GX013443.MP4 --update
# Write the corrected local time to the video.and overwrite the existing file
# $ ./correct_times.sh GX013443.MP4 --update --over-write
# loop through files in a folder:
# $ for FILE in ./2022-06-28/*; do ./correct_times.sh "${FILE}"; done
# $ for FILE in ./2022-06-28/*; do ./correct_times.sh "${FILE}" --update; done
# $ for FILE in ./2022-06-28/*; do ./correct_times.sh "${FILE}" --update --over-write; done
# Requirements:
# JSON parser: $ sudo apt install jq
# References
# https://stackoverflow.com/questions/16548528/command-to-get-time-in-milliseconds
# https://stackoverflow.com/questions/28016578/how-can-i-parse-create-a-date-time-stamp-formatted-with-fractional-seconds-utc
# https://serverfault.com/questions/1020446/linux-get-utc-offset-from-current-or-other-timezones-on-given-date-and-time
# https://man7.org/linux/man-pages/man1/date.1.html
# ----------------
# Set the script to halt on errors
set -e
if [[ -z "$1" ]]; then
echo "USAGE: $ 1./correct_times video.mp4 --update --over-write"
exit 1
fi
# Get the movie name
MOVIE=$1
echo "${MOVIE}"
# need to use raw mode `-r` in jq call to return a raw string otherwise it will be trouble to deal with
CREATED=$(ffprobe -loglevel 0 -print_format json -show_format -show_streams "${MOVIE}" | jq -r .format.tags.creation_time)
if [[ -z "${CREATED}" ]]; then
echo "ERROR - No creation_time in metadata! ${MOVIE}"
exit 1
fi
echo
echo "Video Create Time (Zulu): ${CREATED}"
# Convert the creation time to local time
LOCALTIME=$(date --date="${CREATED}" "+%FT%T %z (%Z)")
echo "Video Create Time (local): ${LOCALTIME}"
echo "--------"
# strip the timezone from the string
STRIPPED=$(TZ=UTC date --date="${CREATED}" "+%FT%T")
echo "Video Create Time (without timezone):${STRIPPED}"
# Express the string in the local timezone
TO_LOCAL=$(date --date="${STRIPPED}" "+%FT%T %z (%Z)")
echo "Video Create Time (to local):${TO_LOCAL}"
echo "--------"
# convert the local time string to UTC
CONVERTED=$(TZ=UTC date --date="${TO_LOCAL}" "+%FT%T.%6NZ") # this is the correct time string
echo "Video Create Time (to UTC):${CONVERTED}"
echo
# Video Create Time (Zulu): 2022-06-28T12:34:27.000000Z
# Video Create Time (local): 2022-06-28T08:34:27 -0400 (EDT)
# --------
# Video Create Time (without timezone):2022-06-28T12:34:27
# Video Create Time (to local):2022-06-28T12:34:27 -0400 (EDT)
# --------
# Video Create Time (to UTC):2022-06-28T16:34:27.000000Z
# -----------
OUTPUT="${MOVIE%%.*}".corrected."${MOVIE##*.}"
if [ "${2:-"invalid"}" == "--update" ]; then
# Write the converted timezone to the video
echo "Updating metadata ${MOVIE} -> ${OUTPUT}"
ffmpeg -i "${MOVIE}" -c copy -metadata creation_time="${CONVERTED}" "${OUTPUT}"
if [ "${3:-"invalid"}" == "--over-write" ]; then
echo "Moving ${OUTPUT} -> ${MOVIE}"
mv "${OUTPUT}" "${MOVIE}"
else
echo "To overwrite the existing video, use --over-write"
fi
else
echo "To update the metadata use --update"
fi |