Skip to content

Instantly share code, notes, and snippets.

@19wolf
Last active April 13, 2021 08:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 19wolf/91c4f5203a706ea6980ff08d1edd2da0 to your computer and use it in GitHub Desktop.
Save 19wolf/91c4f5203a706ea6980ff08d1edd2da0 to your computer and use it in GitHub Desktop.
#!/bin/bash
#Extract .ass subtitles from mkv, convert to .srt, strip html, re-add them
max_threads=4
function process_file () {
local input_file="$1"
file_start=`date +%s`
check_file "$input_file" && process_subtitles "$input_file" || return 1
file_end=`date +%s`
file_runtime=$((file_end-file_start))
echo "Completed in $file_runtime seconds -- $input_file" >> "$logfile"
}
function check_file () {
local this_file="$1"
if $(! grep -q "mkv" <<< "$this_file"); then #check that it's a supported type (currently only mkv)
echo "Not an mkv -- $input_file" >> "$logfile"
return 1
elif $(ffprobe -loglevel quiet -show_entries format_tags=description "$this_file" | grep -q "wolf-converted"); then #check if it's been converted
echo "Already converted -- $input_file" >> "$logfile"
return 1
elif $(! ffprobe -loglevel panic -select_streams s -show_entries stream=codec_name -of csv=p=0 "$this_file" | grep -q 'ass'); then #check there is something to convert
echo "Nothing to do -- $input_file" >> "$logfile"
return 1
else
return 0
fi #if all the checks pass, continue
}
function process_subtitles () {
local this_file="$1"
local combined_tracks=$(mktemp -up /tmp/ tmp-XXX.mkv)
local combined_tracks_tmp=$(mktemp -up /tmp/ tmp-XXX.mkv)
local temp_output=$(mktemp -up /tmp tmp-XXX.mkv)
subtitle_tracks=$(ffprobe -loglevel panic -select_streams s -show_entries stream=index,codec_name -of csv=p=0 "$this_file" | awk -F, '/ass/ {print $1}') #get a list of .ass subtitle track numbers
echo "Found $(echo $subtitle_tracks | wc -w) subtitles -- $this_file" >> "$logfile"
for subtitle_track in $subtitle_tracks; do #for each individual subtitle track of all the tracks, $subtitle_track the track number, not a counter
process_subtitle_track "$subtitle_track" "$this_file" "$combined_tracks-$subtitle_track.mkv" & #process track of file.mkv into file-track.mkv
if [[ $(jobs -r -p | wc -l) -ge $max_threads ]]; then #if number of background jobs is >= 4 wait for a job to finish
wait -n
fi
done
wait
for subtitle_track in $subtitle_tracks; do
if [ ! -f "$combined_tracks" ]; then
ffmpeg -loglevel error -i "$combined_tracks-$subtitle_track.mkv" -c copy "$combined_tracks" #copy file-track.mkv into combined-tracks.mkv
else
ffmpeg -loglevel error -i "$combined_tracks" -i "$combined_tracks-$subtitle_track.mkv" -c copy -map 0 -map 1 "$combined_tracks_tmp" && mv "$combined_tracks_tmp" "$combined_tracks" #copy file-track.mkv into combined-tracks.mkv
fi
rm -f "$combined_tracks-$subtitle_track.mkv"
done
ffmpeg -loglevel error -i "$this_file" -i "$combined_tracks" -c copy -map 0:v -map 0:a -map 0:s -map 1:s -metadata "description=wolf-converted" "$temp_output" && mv "$temp_output" "$this_file" #copy new subtitles to end of original file
rm "$combined_tracks"
}
function process_subtitle_track () {
local this_track="$1" #input track
local the_file="$2" #input file
local subtitle_mkv="$3" #output file
local subtitle_tmp=$(mktemp -up /tmp/ tmp-XXX.tmp)
local subtitle_srt=$(mktemp -up /tmp/ tmp-XXX.srt)
track_title=$(ffprobe -loglevel error -select_streams $this_track -show_entries stream_tags=title "$the_file" | sed 's/TAG://g' | grep "title"); : "${track_title:=title=}" #save the track title for later, set it if blank
track_language=$(ffprobe -loglevel error -select_streams $this_track -show_entries stream_tags=language "$the_file" | sed 's/TAG://g' | grep "language"); : "${track_language:=language=}" #save the track language for later, set it if blank
ffmpeg -loglevel error -i "$the_file" -map 0:$this_track -c:s srt "$subtitle_srt" #convert subtitle track to srt
sed 's/<[^>]*>//g' "$subtitle_srt" > "$subtitle_tmp" && mv "$subtitle_tmp" "$subtitle_srt" #remove any html formatting
ffmpeg -loglevel error -i "$subtitle_srt" -c copy -map 0 -metadata:s:0 "$track_title" -metadata:s:0 "$track_language" "$subtitle_mkv" && rm "$subtitle_srt" #create the mkv file from the srt file
echo "Converted track $this_track of $the_file" >> "$logfile"
}
#Main code
if [ -f "$sonarr_episodefile_path" ]; then #if sonarr file exists
logfile="/config/sonarr-script.log"
for input_file_path in "$sonarr_episodefile_path"; do # for each file from input
echo "Processing -- $sonarr_episodefile_path" >> "$logfile"
process_file "$input_file_path" &
if [[ $(jobs -r -p | wc -l) -ge $max_threads ]]; then #if number of background jobs is >= 1 wait for job to finish
wait -n
fi
done #done looping through files
else
logfile="/var/log/sonarr-script.log"
for input_file_path in "$@"; do # for each file from input
process_file "$input_file_path" &
if [[ $(jobs -r -p | wc -l) -ge $max_threads ]]; then #if number of background jobs is >= 1 wait for job to finish
wait -n
fi
done #done looping through files
fi
wait
rm -f /tmp/tmp-* #remove any leftover temp files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment