Skip to content

Instantly share code, notes, and snippets.

@reedrw
Last active May 5, 2020 21:18
Show Gist options
  • Save reedrw/9195332ae9fab5989d1221328a118a9a to your computer and use it in GitHub Desktop.
Save reedrw/9195332ae9fab5989d1221328a118a9a to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
: "${SHOW:="${PWD##*/}"}"
: "${GROUP:=Group}"
shopt -s nullglob
# set color variables
#
#black="$(tput setaf 0)"
red="$(tput setaf 1)"
green="$(tput setaf 2)"
yellow="$(tput setaf 3)"
#blue="$(tput setaf 4)"
magenta="$(tput setaf 5)"
cyan="$(tput setaf 6)"
#white="$(tput setaf 7)"
reset="$(tput sgr0)"
#
main(){
case $1 in
mux)
selection "${@:2}"
for i in "${episodes[@]}"; do
mux "$i"
done
;;
demux)
if [[ ! "$2" == *.mkv ]]; then
echo "The \`demux\` argument requires a .mkv file as input" >&2
exit 1
fi
for i in "${@:2}"; do
demux "$i"
done
;;
*)
echo "Available arguments: mux, demux" >&2
exit 2
esac
}
selection(){
if [[ $# -eq 0 ]]; then
episodes=()
for f in */; do episodes+=("${f%/}"); done
else
for i in "$@"; do
if [[ -d $i ]]; then
episodes+=("$i")
elif [[ "$(grep -Eo '[0-9]+' <<< "$i" | wc -l)" == "2" ]]; then
FIRST="$(grep -Eo '[0-9]+' <<< "$i" | head -n 1)"
LAST="$(grep -Eo '[0-9]+$' <<< "$i")"
for j in $(seq -w "$FIRST" "$LAST"); do
[[ -d "$j" ]] && episodes+=("$j")
done
fi
done
fi
}
mux(){
unset TITLE
unset chapt_args
unset dub_args
unset sub_args
unset font_args
pushd "$1" > /dev/null || exit
echo "Getting mux arguments..."
muxargs
echo "Muxing mkv file..."
if [[ -f title ]]; then
echo "title file found."
TITLE="$(< title)"
fi
mkvmerge -q -o output.mkv \
--no-global-tags -S -B -T -M \
"${chapt_args[@]}" \
video.mkv \
"${dub_args[@]}" \
"${sub_args[@]}" \
"${font_args[@]}" \
--title "$TITLE"
echo "Getting CRC..."
crc32="$(crc32 output.mkv | tr '[:lower:]' '[:upper:]')"
case $1 in
''|*[!0-9]*)
NAME="$1.mkv"
;;
*)
NAME="[$GROUP] $SHOW - $1 [$crc32].mkv"
;;
esac
echo "Renaming File..."
mv -v output.mkv ../"$NAME"
popd > /dev/null || exit
}
muxargs(){
# video
###
if [[ ! -f video.mkv ]]; then
echo "no video.mkv found"
exit 1
fi
# audio
###
if compgen -G "dub*.mka"; then
dub_args=()
while read -r dub; do
if [[ $dub == *].mka ]]; then
dub_args+=("--language")
dub_args+=("0:$(rev <<< "$dub" | cut -d "[" -f1 | rev | cut -d "]" -f1)")
fi
if grep -q -E '(.*)' <<< "$dub"; then
dub_args+=("--track-name")
dub_args+=("0:$(cut -d '(' -f2- <<< "$dub" | rev | cut -d ')' -f2- | rev )")
fi
dub_args+=("$dub")
done <<< "$(for i in dub*.mka; do echo "$i"; done | sort -V)"
fi
# subs
# same as audio
###
if compgen -G "sub*"; then
sub_args=()
while read -r subs; do
if [[ $subs == *].ass ]] || [[ $subs = *].srt ]] ; then
sub_args+=("--language")
sub_args+=("0:$(rev <<< "$subs" | cut -d "[" -f1 | rev | cut -d "]" -f1)")
fi
if grep -q -E '(.*)' <<< "$subs"; then
sub_args+=("--track-name")
sub_args+=("0:$(cut -d '(' -f2- <<< "$subs" | rev | cut -d ')' -f2- | rev )")
fi
sub_args+=("$subs")
done <<< "$(for i in sub*; do echo "$i"; done | sort -V)"
fi
# fonts
###
if [[ -d fonts ]]; then
font_args=()
for font in fonts/*.[OTot][Tt][Ff]; do
font_args+=("--attachment-mime-type")
font_args+=("application/x-truetype-font")
font_args+=("--attach-file")
font_args+=("$font")
done
fi
# chapters
###
chapt_args=()
if [[ -f chapters.xml ]]; then
chapt_args+=("--chapters")
chapt_args+=("chapters.xml")
fi
}
demux(){
unset DE_TITLE
unset deaudio_args
unset desub_args
unset defont_args
unset dechapter_args
echo
echo "Demuxing '$1'"
local dirname
dirname="$(basename "$1" .mkv)"
mkdir "$dirname"
pushd "$dirname" > /dev/null || exit
ln -s ../"$1" ./
demuxargs "$1"
[[ ${#defont_args[@]} -eq 0 ]] || mkdir fonts
mkvextract -q "$1" \
tracks 0:video.mkv \
"${deaudio_args[@]}" \
"${desub_args[@]}" \
"${defont_args[@]}" \
"${dechapter_args[@]}"
[[ -n "$DE_TITLE" ]] && echo "$DE_TITLE" > title
rm "$1"
echo
# fix timestamps
for i in *.{mkv,mka}; do
echo "$green"Fixing timestamps "$reset"for "$red""$i""$reset"...
mkvmerge -q -o "output" "$i"
rm "$i"
mv "output" "$i"
done
popd > /dev/null || exit
echo
echo "Done!"
}
demuxargs(){
MKVJSON="$(mktemp)"
mkvmerge -J "$1" > "$MKVJSON"
echo
echo "$green"Grabbing audio and subtitle tracks..."$reset"
# audio
###
deaudio_args=()
local track_id
track_id=0
for i in $(jq -r '[.tracks[] | select(.type == "audio")] | .[].id' < "$MKVJSON"); do
TRACKNAME="$(jq -r ".tracks[$i].properties.track_name" < "$MKVJSON")"
TRACKLANG="$(jq -r ".tracks[$i].properties.language" < "$MKVJSON")"
deaudio_args+=("tracks")
if jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null && jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
deaudio_args+=("$i:dub$track_id ($TRACKNAME) [$TRACKLANG].mka")
echo "$i":"$yellow"dub"$track_id" "$magenta"\("$TRACKNAME"\) ["$TRACKLANG"].mka"$reset";
elif jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null; then
deaudio_args+=("$i:dub$track_id [$TRACKLANG].mka")
echo "$i":"$yellow"dub"$track_id" "$magenta"["$TRACKLANG"].mka"$reset";
elif jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
deaudio_args+=("$i:dub$track_id ($TRACKNAME).mka")
echo "$i":"$yellow"dub"$track_id" "$magenta"\("$TRACKNAME"\).mka"$reset";
fi
((++track_id))
done
# subtitles
###
desub_args=()
local track_id
track_id=0
for i in $(jq -r '[.tracks[] | select(.type == "subtitles")] | .[].id' < "$MKVJSON"); do
IDTYPE="$(jq -r ".tracks[$i].codec" < "$MKVJSON")"
TRACKNAME="$(jq -r ".tracks[$i].properties.track_name" < "$MKVJSON")"
TRACKLANG="$(jq -r ".tracks[$i].properties.language" < "$MKVJSON")"
desub_args+=("tracks")
if [[ "$IDTYPE" == "SubStationAlpha" ]]; then
if jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null && jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id ($TRACKNAME) [$TRACKLANG].ass")
echo "$i":"$yellow"sub"$track_id" "$magenta"\("$TRACKNAME"\) ["$TRACKLANG"].ass"$reset";
elif jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id [$TRACKLANG].ass")
echo "$i":"$yellow"sub"$track_id" "$magenta" ["$TRACKLANG"].ass"$reset";
elif jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id ($TRACKNAME).ass")
echo "$i":"$yellow"sub"$track_id" "$magenta"\("$TRACKNAME"\).ass"$reset";
fi
elif [[ "$IDTYPE" == "SubRip/SRT" ]]; then
if jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null && jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id ($TRACKNAME) [$TRACKLANG].srt")
echo "$i":"$yellow"sub"$track_id" "$magenta"\("$TRACKNAME"\) ["$TRACKLANG"].srt"$reset";
elif jq -e ".tracks[$i].properties.language" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id [$TRACKLANG].srt")
echo "$i":"$yellow"sub"$track_id" "$magenta" ["$TRACKLANG"].srt"$reset";
elif jq -e ".tracks[$i].properties.track_name" < "$MKVJSON" > /dev/null; then
desub_args+=("$i:sub$track_id ($TRACKNAME).srt")
echo "$i":"$yellow"sub"$track_id" "$magenta"\("$TRACKNAME"\).srt"$reset";
fi
fi
((++track_id))
done
# fonts
###
defont_args=()
echo ""
echo "$green"Grabbing attachments..."$reset"
for i in $(jq -r ".attachments[].id" < "$MKVJSON" ); do
defont_args+=("attachments")
defont_args+=("$i:fonts/$(jq -r ".attachments[$((i-1))].file_name" < "$MKVJSON")")
echo "$i":"$cyan"fonts/"$(jq -r ".attachments[$((i-1))].file_name" < "$MKVJSON")""$reset"
done
echo ""
echo "$green"Grabbing metadata..."$reset"
# chapters
###
dechapter_args=()
if jq -e ".chapters[0]" < "$MKVJSON" > /dev/null; then
echo "$magenta"Chapters"$reset" found.
dechapter_args+=(chapters)
dechapter_args+=(chapters.xml)
fi
# title
###
if jq -e ".container.properties.title" < "$MKVJSON" > /dev/null ; then
echo "$magenta"Title"$reset" found.
DE_TITLE="$(jq -r ".container.properties.title" < "$MKVJSON")"
fi
rm "$MKVJSON"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment