|
#!/usr/bin/env bash |
|
set -euo pipefail |
|
|
|
if [ $# -eq 0 ]; then |
|
echo "This script takes two mandatory options - \$1 is the input video, \$2 is the |
|
input subtitles." |
|
echo |
|
echo "By default, we burn in hard subs; you may use --soft-subs to embed soft |
|
subs. See: https://en.wikipedia.org/wiki/Subtitle_(captioning)#Types" |
|
|
|
# Note: mkv would allow default subs on (`-disposition:s:s:0 forced`), but mkv |
|
# doesn't work out of box in Quicktime |
|
exit 0 |
|
fi |
|
|
|
############################### |
|
# verify correct getopt version |
|
# |
|
# this assumes you're using gnu's getopt, which is not the same as osx' default |
|
# getopt |
|
############################### |
|
# If we've got brew installed, use its gnu-getopt |
|
if [ -x "$(command -v brew)" ]; then |
|
if ( ! brew list gnu-getopt ); then |
|
echo "You need to install gnu-getopt:" |
|
echo " brew install gnu-getopt" |
|
exit 1 |
|
fi |
|
|
|
brew_prefix=$(brew --prefix gnu-getopt) |
|
export PATH=${brew_prefix}/bin:$PATH |
|
fi |
|
|
|
set +e |
|
opt=$(getopt -T) |
|
set -e |
|
# 4 is the return code from gnu's `getopt -T`, and the -n $opt checks that its |
|
# stdout is empty, not '--' (it will be '--' if using the non-gnu osx getopt |
|
if (( $? != 4 )) && [[ -n $opt ]]; then |
|
echo "Either no getopt is installed, or you're using a non-gnu getopt." |
|
echo "If you're on OS X, you can install gnu-getopt using homebrew to fix |
|
this." |
|
exit 1 |
|
fi |
|
############################## |
|
# end verifying correct getopt |
|
############################## |
|
|
|
OPTS=$(getopt --options s --longoptions soft-subs "$@") |
|
eval set -- "$OPTS" |
|
|
|
SOFTSUBS=0 |
|
while true ; do |
|
case "$1" in |
|
--soft-subs|-s) |
|
SOFTSUBS=1 |
|
shift |
|
;; |
|
--) |
|
shift |
|
break |
|
;; |
|
*) |
|
echo "Unknown option: $1" |
|
exit 1 |
|
;; |
|
esac |
|
done |
|
|
|
INVIDEO=$1 |
|
INSUBS=$2 |
|
CCOVERLAY=$(dirname "$0")/cc.png |
|
|
|
if ( ! command -v ffmpeg ); then |
|
echo "This script depends on ffmpeg." |
|
exit 1 |
|
fi |
|
|
|
if [[ "$INVIDEO" == "" ]]; then |
|
echo "No in video (foo.mp4?) provided." |
|
echo |
|
exit 1 |
|
fi |
|
|
|
if ! [[ "$INSUBS" =~ .srt$ ]]; then |
|
echo "No subtitles provided." |
|
echo |
|
echo "Debug: options given: INVIDEO: ${INVIDEO}, INSUBS: ${INSUBS}" |
|
exit 1 |
|
fi |
|
|
|
if (( "$SOFTSUBS" )); then |
|
# if this file needs scaling at some point, use imagemagick: |
|
# convert cc.png -resize 120x120 cc.png |
|
if [[ ! -f $CCOVERLAY ]]; then |
|
echo "No ccoverlay image found." |
|
exit 1 |
|
fi |
|
fi |
|
|
|
tmpfile=$(mktemp /tmp/postprocess-video.XXXXXX.mp4) |
|
rm "$tmpfile" # so ffmpeg doesn't ask if you want to overwrite it |
|
|
|
set -x |
|
if (( "$SOFTSUBS" )); then |
|
# Add CCOVERLAY watermark in bottom right corner |
|
ffmpeg -i "$INVIDEO" \ |
|
-vf "movie=${CCOVERLAY} [watermark]; [in][watermark] overlay=(main_w-overlay_w-10):(main_h-overlay_h-10) [out]" \ |
|
"$tmpfile" |
|
else |
|
ffmpeg -i "$INVIDEO" -vf subtitles="$INSUBS" "$tmpfile" |
|
fi |
|
|
|
|
|
ffmpeg -i "$tmpfile" -f srt -i "$INSUBS" \ |
|
-c:v copy -c:a copy -c:s mov_text \ |
|
-metadata:s:s:0 language=English \ |
|
out.mp4 |
|
|
|
# could put this in a signal handler if you wanted to be really sure it gets |
|
# cleaned up |
|
rm "$tmpfile" |
|
|
|
if (( "$SOFTSUBS" )); then |
|
echo "Done, with soft subs! See out.mp4" |
|
else |
|
echo "Done, with hard and soft subs! See out.mp4" |
|
fi |
If you are not a regular bash user, this is the format for the CLI:
./captioning.sh video.mp4 subs.srt