Skip to content

Instantly share code, notes, and snippets.

@ctrlcctrlv
Created July 29, 2014 18:35
Show Gist options
  • Save ctrlcctrlv/0ca18ecad315f56b8ede to your computer and use it in GitHub Desktop.
Save ctrlcctrlv/0ca18ecad315f56b8ede to your computer and use it in GitHub Desktop.
Convert softsubbed MKV files into hardsubbed MP4 files for playback via Roku, low powered devices etc, keep all fonts intact.
#!/bin/sh
# HARDSUB.SH
# (c) 2014 Fredrick Brennan
#
# Usage notes:
# This script requires that ~/.fonts is in your fontconfig path.
# This script also requires mkvmerge, realpath and ffmpeg to be installed. Only supports SSA subs and MKV files.
# Also note that this script can take a long time to run.
# Run as `hardsub.sh FILE_NAME`
# You should be able to delete the following created files after it is done: done_subtitles.ass and the entire contents of ~/.fonts/MKV
# They are not deleted automatically because you may want to use them again for a subsequent ffmpeg run
DIRECTORY=$HOME/.fonts/MKV
# Save $1 because `set` will overwrite it
VIDEO_FILE=`realpath "$1"`
OUTPUT=$2
WD=`pwd`
declare -a FONTS
declare -a SUBTITLES
# Create fonts directory
if [ ! -d "$DIRECTORY" ]; then
mkdir "$DIRECTORY"
fi
if [ ! -f "$VIDEO_FILE" ]; then
echo "Cannot read $VIDEO_FILE"
exit 1
fi
if [ -z "$OUTPUT" ]; then
echo "Warning: No output file specified, will use output.mp4"
OUTPUT='output.mp4'
fi
# Use mkvmerge to get all our subtitles
MKVMERGE=`mkvmerge -i "$VIDEO_FILE"`
if [ $? -ne 0 ]; then
echo "mkvmerge failed to run!"
echo "$MKVMERGE"
exit 1
fi
# Get the track IDs of our subtitles
while read LINE; do
set $LINE
# $LINE should look like:
# $1 $2 $3 $4 $5
# Track ID 3: subtitles (SubStationAlpha)
if [ $1 = 'Track' ]; then
if [ $4 = 'subtitles' ]; then
TRACK_ID=${3//[!0-9]/};
SUBTITLES+=("$TRACK_ID")
fi
fi
# $LINE should look like:
# $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11
# Attachment ID 1: type 'application/x-truetype-font', size 58224 bytes, file name '9SALERNO.TTF'
if [ $1 = 'Attachment' ]; then
if [ $5 = "'application/x-truetype-font'," ]; then
ATTACH_ID=${3//[!0-9]/};
FONTS+=("$ATTACH_ID")
fi
fi
done <<< "$MKVMERGE"
if [ ${#SUBTITLES[@]} -eq 0 ]; then
echo 'Error: File has no subtitles!'
exit 1
fi
echo ${#SUBTITLES[@]} subtitle tracks found: ${SUBTITLES[*]}
echo ${#FONTS[@]} font attachments found: ${FONTS[*]}
#Extract all our subtitles
for i in ${SUBTITLES[@]}; do
mkvextract tracks "$VIDEO_FILE" "$i":subtitles"$i".ass
done
#Combine all subtitles into one mega SSA file; just simple concatenation seems to work.
cat subtitles* > done_subtitles.ass
#Delete separate subtitle files
rm subtitles*
#Extract all our fonts
cd $DIRECTORY
mkvextract attachments "$VIDEO_FILE" ${FONTS[*]}
cd $WD
#Do it. You can edit this line to your liking.
echo Running this line: ffmpeg -i \""$VIDEO_FILE"\" -acodec copy -vcodec libx264 -report -qscale 0 -vf "ass=done_subtitles.ass" "$OUTPUT"
echo
ffmpeg -i "$VIDEO_FILE" -acodec copy -vcodec libx264 -report -qscale 0 -vf "ass=done_subtitles.ass" "$OUTPUT"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment