Skip to content

Instantly share code, notes, and snippets.

@hfossli
Last active May 12, 2022 07:32
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save hfossli/6003302 to your computer and use it in GitHub Desktop.
Save hfossli/6003302 to your computer and use it in GitHub Desktop.
A bash script for reversing videos using ffmpeg and sox.
#!/bin/bash
# Created by Håvard Fossli <hfossli@gmail.com> in 2013
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
#
# Description
# A bash script for reversing videos using ffmpeg and sox.
#
# Keywords
# Terminal, bash, unix, mac, shell, script, video, movie, reverse, inverse, audio, video, ffmpeg, sox.
#
# Usefull links when working with ffmpeg
# - https://sites.google.com/site/linuxencoding/ffmpeg-tips
# - http://pvdm.xs4all.nl/wiki/index.php/Convert_an_AVCHD_/_MTS_file_to_MP4_using_ffmpeg
# - http://rodrigopolo.com/ffmpeg/cheats.php
# - http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs
#
# arg1: name of program
function assert_program_exists() {
command -v $1 >/dev/null 2>&1 || {
echo >&2 "You must have $1 installed in order to run this script. Try:";
echo "\$ brew install $1"
exit 1;
}
}
# arg1: path to input file / source
function fallback_output_path() {
if [[ -z "$1" ]] ; then
echo "Bad input to get_video_duration_in_seconds_from_ffmpeg_info()"
echo "Input givven $1"
exit 1
else
__FILE_NAME=`rev <<< "$1" | cut -d"." -f2- | rev`
__FILE_EXT=`rev <<< "$1" | cut -d"." -f1 | rev`
__OUT_FILE_FORMAT="${__FILE_NAME}-reversed.mp4"
echo $__OUT_FILE_FORMAT
exit 1
fi
}
function echo_variables {
echo
echo "### Variables ###"
echo
}
function usage {
echo "For help and detailed guide type:"
echo "\$ $0 -h"
}
function detailed_guide {
echo "
Example:
\$ $0 input.file output-filename
Info:
- input file may be any kind of file reconginzed by ffmpeg
Flags:
-i Path to input (string)
-o Path to output (string)
-o Path to output (string)
-o Path to output (string)
-o Path to output (string)
"
}
# Allow to be terminated with ctrl + c
trap "exit" INT
# Assert ffmpeg is installed
assert_program_exists "ffmpeg"
# Set variables and default values
typeset -i CHUNK_LEN
INPUT_PATH=''
OUTPUT_PATH=''
INCLUDE_AUDIO_STREAM=true
VERBOSE=false
PLAY_SOUND=false
HELP=false
DEINTERLACE=false
FFMPEG_IN_PARAMS=''
FFMPEG_OUT_PARAMS=''
# Grab input arguments
while getopts “i:o:dvip:q:sh” OPTION
do
case $OPTION in
i) INPUT_PATH=$(echo "$OPTARG" | sed 's/ /\\ /g' ) ;;
o) OUTPUT_PATH=$(echo "$OPTARG" | sed 's/ /\\ /g' ) ;;
d) DEINTERLACE=true ;;
v) VERBOSE=true ;;
a) INCLUDE_AUDIO_STREAM=false ;;
p) FFMPEG_IN_PARAMS="$OPTARG" ;;
q) FFMPEG_OUT_PARAMS="$OPTARG" ;;
s) PLAY_SOUND=true ;;
h) HELP=true ;;
?) usage
exit 1
;;
esac
done
if $HELP ; then
detailed_guide
exit 1
fi
if [[ -z $INPUT_PATH ]] ; then
echo "Invalid source"
usage
exit 1
fi
if [ -z "$OUTPUT_PATH" ] ; then
OUTPUT_PATH=$(fallback_output_path $INPUT_PATH)
fi
TMP_DIR=$(mktemp -dt "test")
AUDIO_PATH=${TMP_DIR}/backwards.wav
AUDIO_PARAMS=''
if $VERBOSE ; then
echo "Created empty directory $TMP_DIR"
ls -la $TMP_DIR
fi
if $DEINTERLACE ; then
ffmpeg -i $INPUT_PATH -an -qscale 1 -vf yadif $FFMPEG_IN_PARAMS ${TMP_DIR}/%06d.jpg
else
ffmpeg -i $INPUT_PATH -an -qscale 1 $FFMPEG_IN_PARAMS ${TMP_DIR}/%06d.jpg
fi
if $INCLUDE_AUDIO_STREAM ; then
assert_program_exists "sox"
ffmpeg -i $INPUT_PATH -vn -ac 2 ${TMP_DIR}/audio.wav
sox -V ${TMP_DIR}/audio.wav ${TMP_DIR}/audio_reverse.wav reverse
AUDIO_PARAMS="-i ${TMP_DIR}/audio_reverse.wav"
fi
cat $(ls -r $TMP_DIR/*jpg) | ffmpeg -f image2pipe -vcodec mjpeg -r 25 -i - -i $TMP_DIR/audio_reverse.wav $FFMPEG_OUT_PARAMS $OUTPUT_PATH
if $VERBOSE ; then
echo
echo "Will $TMP_DIR"
ls -la $TMP_DIR
fi
echo "Done!"
exit 1
rm -rf $TMP_DIR
if $PLAY_SOUND ; then
# & means async
say "Done! ." &
fi
@dequis
Copy link

dequis commented Feb 20, 2015

Having issues with this script, mktemp -dt "test" says mktemp: too few X's in template ‘test’. After turning test into testXXX it still generated an empty file. Also you've got Path to output (string) four times in the help. I just gave up with this script and did it manually with the steps described in the stack overflow answer.

@Pistos
Copy link

Pistos commented Jun 27, 2015

I also got the too few X message.

@hfossli
Copy link
Author

hfossli commented Jun 27, 2015

It worked on my mac at the time of writing.

@Unpaid8503
Copy link

Change the line 130 to TMP_DIR=$(mktemp -dt "testXXXX") if you get the too few X error.

@richardpl
Copy link

Do not use abandoned sox. ffmpeg have areverse filter already.

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