81 lines
2.4 KiB
Bash
Executable File
81 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# scripts/convert.sh — strip video tracks out of audio files in
|
||
# ~/.config/obs-studio/playlist/ and re-encode to AAC m4a in place.
|
||
#
|
||
# WHY: yt-dlp .webm downloads include 1080p video. Chromium's <audio>
|
||
# element decodes the video stream too (just doesn't render it) — pegs
|
||
# CPU and stalls playback mid-track. Audio-only m4a is ~95% smaller
|
||
# and decodes ~20× faster.
|
||
#
|
||
# ./convert.sh — convert all video-bearing files
|
||
# ./convert.sh --dry-run — show what would happen, do nothing
|
||
#
|
||
# DO NOT run this while OBS has a playlist track open (between streams
|
||
# is fine; mid-stream you'll lock the file ffmpeg is reading from).
|
||
#
|
||
# After conversion, re-index: ./playlist.sh
|
||
set -euo pipefail
|
||
|
||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
OBS_DIR="$(cd "$DIR/.." && pwd)"
|
||
AUDIO_DIR="$OBS_DIR/playlist"
|
||
|
||
DRY=0
|
||
[[ "${1:-}" == "--dry-run" ]] && DRY=1
|
||
|
||
if [[ ! -d "$AUDIO_DIR" ]]; then
|
||
echo " ✗ $AUDIO_DIR does not exist" >&2
|
||
exit 1
|
||
fi
|
||
if ! command -v ffprobe >/dev/null 2>&1 || ! command -v ffmpeg >/dev/null 2>&1; then
|
||
echo " ✗ ffmpeg / ffprobe required" >&2
|
||
exit 1
|
||
fi
|
||
|
||
shopt -s nullglob nocaseglob
|
||
|
||
# Files that contain a video stream (and aren't already m4a)
|
||
declare -a TODO=()
|
||
for f in "$AUDIO_DIR"/*.{webm,mp4,mkv,mov,avi}; do
|
||
[[ -f "$f" ]] || continue
|
||
# Skip yt-dlp intermediate files
|
||
case "$(basename "$f")" in
|
||
*.f[0-9]*.*|*.temp.*|*.part) continue ;;
|
||
esac
|
||
# Only consider files that actually contain a video stream
|
||
if ffprobe -v error -select_streams v -show_entries stream=codec_type \
|
||
-of csv=p=0 "$f" 2>/dev/null | grep -q video; then
|
||
TODO+=("$f")
|
||
fi
|
||
done
|
||
|
||
if [[ ${#TODO[@]} -eq 0 ]]; then
|
||
echo " ✓ nothing to convert (no video-bearing files in $AUDIO_DIR)"
|
||
exit 0
|
||
fi
|
||
|
||
echo "── Converting ${#TODO[@]} file(s) → AAC m4a ──"
|
||
for f in "${TODO[@]}"; do
|
||
base="${f%.*}"
|
||
out="$base.m4a"
|
||
if [[ -f "$out" ]]; then
|
||
echo " ⊘ skip (m4a exists): $(basename "$f")"
|
||
continue
|
||
fi
|
||
echo " → $(basename "$f")"
|
||
if [[ $DRY -eq 1 ]]; then
|
||
echo " (dry-run: would write $(basename "$out") and remove the source)"
|
||
continue
|
||
fi
|
||
if ffmpeg -nostdin -loglevel error -i "$f" -vn -c:a aac -b:a 192k "$out"; then
|
||
rm -f "$f"
|
||
echo " ✓ ${out##*/} ($(du -h "$out" | cut -f1))"
|
||
else
|
||
echo " ✗ ffmpeg failed; leaving $(basename "$f") in place" >&2
|
||
rm -f "$out"
|
||
fi
|
||
done
|
||
|
||
echo
|
||
echo " → next: ./playlist.sh (re-index for the new filenames)"
|