aboutsummaryrefslogtreecommitdiffstats
path: root/burnsubs.sh
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2026-07-30 01:33:39 -0700
committerPinapelz <yukais@pinapelz.com>2026-07-30 01:37:51 -0700
commitc9e1ed68428b36b59a560bd411598c4c93de519a (patch)
treec199cd36f2a7922e573a6dc6d72afb2231dd186b /burnsubs.sh
parentfee46273ee845c8b04f9647d63c57c3f1c4df51d (diff)
add burnsubs.sh script
- pass in a directory to burn all subtitles to the appropriate video -> produces new video
Diffstat (limited to 'burnsubs.sh')
-rwxr-xr-xburnsubs.sh155
1 files changed, 155 insertions, 0 deletions
diff --git a/burnsubs.sh b/burnsubs.sh
new file mode 100755
index 0000000..0a17050
--- /dev/null
+++ b/burnsubs.sh
@@ -0,0 +1,155 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+DELETE_ORIGINALS=false
+MEDIA_EXTS=("mp4" "mkv" "mov" "avi" "webm" "m4v")
+SEARCH_DIR="."
+STYLE="FontName=Arial,FontSize=18,PrimaryColour=&HFFFFFF&,BackColour=&H000000&,BorderStyle=3,Outline=1,Shadow=0,MarginV=10,Alignment=2"
+
+usage() {
+cat <<EOF
+Usage:
+ $(basename "$0") [DIRECTORY] [options]
+
+Burn subtitles into every supported media file that has a matching
+.srt or .vtt file with the same basename.
+
+Examples:
+ $(basename "$0")
+ $(basename "$0") ~/Videos
+ $(basename "$0") /mnt/media --delete-originals
+ $(basename "$0") ~/Videos --style "FontName=Roboto,FontSize=30"
+
+Options:
+ --delete-originals
+ Delete original media and subtitle after successful conversion.
+
+ --style "ASS_STYLE"
+ Subtitle styling passed to FFmpeg's force_style.
+
+ --ext "mp4 mkv mov"
+ Space-separated list of media extensions.
+
+ -h, --help
+ Show this help.
+
+EOF
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --delete-originals)
+ DELETE_ORIGINALS=true
+ shift
+ ;;
+
+ --style)
+ STYLE="$2"
+ shift 2
+ ;;
+
+ --ext)
+ read -ra MEDIA_EXTS <<< "$2"
+ shift 2
+ ;;
+
+ -h|--help)
+ usage
+ exit 0
+ ;;
+
+ -*)
+ echo "Unknown option: $1"
+ exit 1
+ ;;
+
+ *)
+ if [[ "$SEARCH_DIR" != "." ]]; then
+ echo "Only one directory may be specified."
+ exit 1
+ fi
+ SEARCH_DIR="$1"
+ shift
+ ;;
+ esac
+done
+
+if [[ ! -d "$SEARCH_DIR" ]]; then
+ echo "Directory does not exist: $SEARCH_DIR"
+ exit 1
+fi
+
+command -v ffmpeg >/dev/null || {
+ echo "ffmpeg not found."
+ exit 1
+}
+
+escape_path() {
+ printf "%s" "$1" | sed "s/'/'\\\\''/g"
+}
+
+for ext in "${MEDIA_EXTS[@]}"; do
+ while IFS= read -r -d '' media; do
+
+ dir=$(dirname "$media")
+ filename=$(basename "$media")
+ base="${filename%.*}"
+ extension="${filename##*.}"
+
+ subtitle=""
+
+ shopt -s nullglob nocaseglob
+
+
+ for candidate in \
+ "$dir/$base.srt" \
+ "$dir/$base.vtt" \
+ "$dir/$base".*.srt \
+ "$dir/$base".*.vtt; do
+ [[ -e "$candidate" ]] || continue
+ subtitle="$candidate"
+ break
+ done
+
+ shopt -u nullglob nocaseglob
+
+ [[ -n "$subtitle" ]] || continue
+
+ output="$dir/${base}_subbed.${extension}"
+
+ echo
+ echo "=================================="
+ echo "Media: $media"
+ echo "Subtitle: $subtitle"
+ echo "Output: $output"
+ echo "=================================="
+
+ escaped_sub=$(escape_path "$subtitle")
+
+ ffmpeg \
+ -hide_banner \
+ -y \
+ -i "$media" \
+ -vf "subtitles='${escaped_sub}':force_style='${STYLE}'" \
+ -c:v libx264 \
+ -preset medium \
+ -crf 18 \
+ -c:a copy \
+ "$output"
+
+ if [[ $? -eq 0 ]]; then
+ echo "✓ Finished"
+
+ if $DELETE_ORIGINALS; then
+ rm -f "$media" "$subtitle"
+ echo "Deleted originals."
+ fi
+ else
+ echo "✗ Failed: $media"
+ fi
+
+ done < <(find "$SEARCH_DIR" -type f -iname "*.${ext}" -print0)
+done
+
+echo
+echo "Done."
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage