Created
July 16, 2023 21:17
-
-
Save Vftdan/b2e9cb242316f3587ddebb6afa9a4a6c to your computer and use it in GitHub Desktop.
Owncast chat log to ASS/SSA subtitles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/sh | |
# owncast-chat2ass.sh | |
# Copyright (c) 2023 vftdan (https://github.com/Vftdan) | |
TimeToSeconds() { | |
date -d "$1" +'%s.%N' | |
} | |
TimespanSeconds() { | |
printf '%s\n' "$(TimeToSeconds "$2") - $(TimeToSeconds "$1")" | bc | |
} | |
SecondsToTimeWithCS() { | |
# CS = centisecond | |
# Wraps at 24h!!! | |
date -ud "@$1" +'%T.%N' | sed -E 's/^0?//; s/[0-9]{7}$//' | |
} | |
EscapeRtf() { | |
sed -E 's/[\\{}]/\\\0/g; s/$/\\n/g' | tr -d '\n' | head -c -2 | |
echo | |
} | |
HtmlToRtf() { | |
sed -E 's/<(em|i)>/{\\i1}/g; s/<\/(em|i)>/{\\i0}/g; s/<(b|strong)>/{\\b1}/g; s/<\/(b|strong)>/{\\b0}/g; s/\>/>/g; s/\</</g; s/\&\#39;/'"'"'/g; s/\"/"/g; s/\&/\&/g' | |
} | |
SanitizeSSACSVValue() { | |
tr -d ',\n' | |
} | |
PrintSSACSVSanitizedValue() { | |
printf '%s,' "$(printf '%s\n' "$1" | SanitizeSSACSVValue)" | |
} | |
ExtractMessages() { | |
jq -c '.[] | select(.type == "CHAT") | {"timestamp": .timestamp, "user": .user.displayName, "text": .body}' | |
} | |
PrintSSAINISection() { | |
printf '[%s]\n' "$1" | |
} | |
PrintSSAINIKeyPrefix() { | |
printf '%s: ' "$1" | |
} | |
PrependLinesSSAINIKey() { | |
while read -r line; do \ | |
PrintSSAINIKeyPrefix "$1" | |
printf '%s\n' "$line" | |
done | |
} | |
MessageToSSAEventCSV() { | |
local timestamp="$(printf "%s" "$2" | jq -r '.timestamp')" | |
local user="$(printf '%s' "$2" | jq -r '.user')" | |
local text="$(printf '%s' "$2" | jq -r '.text')" | |
local secfromstart="$(TimespanSeconds "$vodstart" "$timestamp")" | |
local endsecfromstart="$(printf '%s\n' "$secfromstart + $1" | bc)" | |
# Layer: | |
PrintSSACSVSanitizedValue 0 | |
# Start: | |
PrintSSACSVSanitizedValue "$(SecondsToTimeWithCS "$secfromstart")" | |
# End: | |
PrintSSACSVSanitizedValue "$(SecondsToTimeWithCS "$endsecfromstart")" | |
# Style: | |
PrintSSACSVSanitizedValue Default | |
# Name: | |
PrintSSACSVSanitizedValue "$user" | |
# MarginL: | |
PrintSSACSVSanitizedValue 0 | |
# MarginR: | |
PrintSSACSVSanitizedValue 0 | |
# MarginV: | |
PrintSSACSVSanitizedValue 0 | |
# Effect: | |
PrintSSACSVSanitizedValue 'Scroll up;300;200;25' | |
# Text: | |
printf '%s: %s\n' "$user" "$text" | EscapeRtf | HtmlToRtf | |
} | |
FlatMapLines() { | |
while read -r line; do \ | |
"$@" "$line" | |
done | |
} | |
Main() { | |
PrintSSAINISection "Script Info" | |
echo '; Script generated by owncast-chat2ass.sh' | |
echo '; Shellscript author: https://github.com/Vftdan' | |
PrintSSAINIKeyPrefix Title | |
echo 'Default Aegisub file' | |
PrintSSAINIKeyPrefix ScriptType | |
echo 'v4.00+' | |
echo | |
PrintSSAINISection Events | |
PrintSSAINIKeyPrefix Format | |
echo 'Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text' | |
ExtractMessages | FlatMapLines MessageToSSAEventCSV 2 | PrependLinesSSAINIKey Dialogue | |
} | |
PrintUsage() { | |
echo "Usage: $0 <vod_start_timestamp>" | |
echo 'VOD start timestamp must be provided in the format understood by date(1)' | |
echo 'JSON file in the format like returned by https://${OWNCAST_SERVER}/api/chat?accessToken=${YOUR_ACCESS_TOKEN} must be piped into the standard input' | |
echo 'Minimal SSA/ASS subtitle file will be printed to the standard output' | |
} | |
if [ $# -ne 1 ]; then \ | |
PrintUsage >&2 | |
exit 1 | |
fi | |
case "$1" in | |
-h|--help) | |
PrintUsage | |
exit 0 | |
;; | |
esac | |
export vodstart="$1" | |
Main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment