-
-
Save chigozienri/9d0a345d7c51da02dad1e18d30e58fc1 to your computer and use it in GitHub Desktop.
Extract frames from video every X seconds and geotag them using GPS data file. Requires exiftool and ffmpeg. Modified to prep Insta360 video for Streetview.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Updates to prep Insta360 One X2 video for Streetview upload. | |
# Brian Check | |
# 13 Mar 2021 | |
# Ksheesh Geotag Video Frames 0.0.1 | |
# | |
# Extract frames from video every X seconds and geotag them using GPS data file. | |
# Requires exiftool and ffmpeg. | |
# Copyright (c) 2017 krzysiu.net | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in all | |
# copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
# SOFTWARE. | |
# setlocal EnableDelayedExpansion | |
# Config starts here. Remember: | |
# * Paths and names: don't use quotes, even if it has spaces in the string. | |
# * Binaries: if they are in shared path, you may set just the binary name, | |
# i.e. "ffmpeg" (without quotes) for ffmpegBin variable. | |
# Path to ffmpeg binary. | |
# alias ffmpegBin=c:\bin\ffmpeg.exe | |
# Path to exiftool binary. | |
# set exiftoolBin=c:\bin\exiftool.exe | |
# Input video file | |
# This is the stiched MP4 from app or Insta360 Studio. h264 and h265 both work. | |
videoFile=$1 | |
insvFile=$2 | |
# The source of GPS data, i.e. GPX or other supported file. Wildcards are also | |
# possible, e.g. gpsDataFile=c:\gps_data\*.gpx | |
# Create .gpx using following command: | |
# exiftool.exe -ee -api largefilesupport -p .\gpx.fmt .\VID_20210312_063451_00_019.insv > .\VID_20210312_063451_00_019.gpx | |
# use Command Prompt, Powershell will cause issues, exiftool was unable to read file format. | |
# use the larger of the insv files, should be the file with 00. | |
exiftool -ee -api largefilesupport -p ~/gpx.fmt "$insvFile" > /tmp/gpx.gpx | |
gpsDataFile=/tmp/gpx.gpx | |
# Output directory for frame images (must exist; without trailing slash) | |
outputDirectory=./frames | |
# Prefix which will be added to image file names | |
framePrefix=frame_ | |
# Padding digit count (1-9) in frame file names (i.e. 3 will make 001.jpg and 2 will make 01.jpg) | |
paddingDigits=4 | |
# Get frame every X seconds. | |
getFrameEvery=3 | |
# Get timezone offset from UTC | |
offsetTime=-05:00 | |
# GPS Offset from video file | |
# Insta360 insv does not seem to start recording GPS until 10 seconds in | |
gpsOffset=+00:10 | |
# Video framerate | |
# This does not work, search for timeShift and modify function to correct for actual framerate, currently 29.97fps | |
# set /a frameRate=30000/1001 | |
# Date and time of the start of the video. You may use: | |
# * DateTimeOriginal - if the file has DateTimeOriginal tag | |
# * FileCreateDate - set timestamp to file creation date | |
# * FileModifyDate - set timestamp to file modify date | |
# * 0 - own timestamp (see videoTimestamp variable) | |
# INSV files do not have the above fields. CreateDate works. | |
dateSource=CreateDate | |
# If dateSource is set to 0, set here date and time of the start of the video. | |
# The format is yyyy:mm:dd hh:mm:ss | |
# videoTimestamp=$3 | |
# Config ends here. | |
# set exifDateParam=-tagsFromFile "%videoFile%" "-datetimeoriginal<%dateSource%" "-OffsetTimeOriginal=%offsetTime%" | |
# if %dateSource% equ 0 set exifDateParam="-datetimeoriginal=%videoTimestamp%Z" | |
if test -f "$outputDirectory"; then | |
echo "Can't access output directory $outputDirectory" 1>&2 | |
exit 1 | |
fi | |
if test -f "$videoFile"; then | |
echo "Can't access video file $videoFile" 1>&2 | |
exit 1 | |
fi | |
pushd $outputDirectory || exit | |
echo "Extracting frames..." | |
ffmpeg -loglevel error -hide_banner -stats -i "$videoFile" -q:v 2 -vf fps=fps=1/${getFrameEvery}:start_time=0:round=zero ${framePrefix}%0${paddingDigits}d.jpg | |
# if %errorlevel% neq 0 ( | |
# set errMsg=ffmpeg returned error | |
# goto error | |
# ) | |
echo Done! | |
echo Setting base timestamp to files. | |
fileNumber=0 | |
exiftool -tagsFromFile "$videoFile" "-datetimeoriginal<$dateSource" "-OffsetTimeOriginal=$offsetTime" -overwrite_original -globaltimeshift "+0:0:0 0:0:$timeShift" "$outputDirectory\\$framePrefix*.jpg" | |
echo Done! | |
echo Setting timestamp offsets. | |
fileNumber=0 | |
for f in "$outputDirectory\\$framePrefix"*.jpg; | |
do | |
frameNumber=${$f/$outputDirectory\\$framePrefix/} | |
frameNumber=${$frameNumber/.jpg/} | |
timeShift=${$frameNumber+(($getFrameEvery*30)-($getFrameEvery*(30000/1001)))} | |
if [ $fileNumber != 0 ]; then | |
exiftool -P -m -overwrite_original "-datetimeoriginal+=0:0:0 0:0:$timeShift" "%%~nxf" | |
fi | |
fileNumber=$fileNumber+1 | |
done | |
echo Done! | |
echo Geotagging images. | |
exiftool -P -geotag "$gpsDataFile" "-geosync=$gpsOffset" "-geotime<SubSecDateTimeOriginal" -overwrite_original "$outputDirectory\\$framePrefix*.jpg" | |
echo Done! | |
popd || exit | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment