#!/bin/bash

# ======================================================================== #
# Downloads a YouTube video with all the subtitles packed into a .mkv file #
# ======================================================================== #

# Usage: ./ytdl-subs.sh "YOUTUBE_URL" "OUTPUT_NAME_WITHOUT_EXTENSION"

UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

youtube-dl --all-subs --write-sub --sub-format srt "$1" --format bestvideo+bestaudio -o "$UUID"

declare -a SUBS=()
declare -a LANGS=()

TARGET=""
METADATA=""
MAPPED=""

function join_by
{
	local d=${1-}
	local f=${2-}

	if shift 2; then
		printf %s "$f" "${@/#/$d}"
	fi
}

for NAME in $(find . -name "$UUID*\.mp4" -o -name "$UUID*\.webm" -o -name "$UUID*\.mkv"); do
	BASENAME=$(basename "$NAME")
	if [ ! -f "${BASENAME%.*}.mkv" ]; then
		ffmpeg -i "$BASENAME" -c:v copy -c:a copy "${BASENAME%.*}.mkv"
		TARGET="${BASENAME%.*}.mkv"
	else
		TARGET="$BASENAME"
	fi
	if [[ ! "$BASENAME" == *"\.mkv" ]]; then
		rm "$BASENAME"
	fi
done

for NAME in $(find . -name "$UUID*\.vtt" -o -name "$UUID*\.srt"); do
	BASENAME=$(basename "$NAME")
	if [[ ! "$BASENAME" == *"\.srt" ]]; then
		if [ ! -f "${BASENAME%.*}.srt" ]; then
			ffmpeg -i "$BASENAME" "${BASENAME%.*}.srt"
		fi
		rm "$BASENAME"
	fi
done

for NAME in $(find . -name "$UUID*\.srt"); do
	BASENAME=$(basename "$NAME")

	[[ "$BASENAME" =~ \.([A-Za-z]+)\.srt ]]

	LANGS=("${LANGS[@]}" "${BASH_REMATCH[1]}")
	SUBS=("${SUBS[@]}" "$BASENAME")
done

for INDEX in "${!LANGS[@]}"; do
	LANG=$(printf '%s\n' "${LANGS[$INDEX]}" | awk '{ print toupper($0) }')
	METADATA="${METADATA}-metadata:s:s:$INDEX language=$LANG "
	MAPPED="${MAPPED}-map $((INDEX + 1)) "
done

ffmpeg -i "$TARGET" -f srt \
-i $(join_by ' -i ' "${SUBS[@]}") \
-map 0:v -map 0:a $MAPPED \
-c:v copy -c:a copy \
$METADATA \
-c:s copy "$2.mkv"

rm "$TARGET"

for NAME in $(find . -name "$UUID*\.vtt" -o -name "$UUID*\.srt"); do
	rm $(basename "$NAME")
done