Created
January 24, 2025 13:28
-
-
Save henrycunh/9f48d177032e0201f34ca28461d63b64 to your computer and use it in GitHub Desktop.
Download YT Clip
This file contains hidden or 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
#!/usr/bin/env bash | |
# | |
# ytclip: Download and clip a portion of a YouTube video into MP4. | |
# | |
# Usage: | |
# ytclip <YOUTUBE_URL> --from <TIME> --to <TIME> | |
# | |
# <TIME> can be: | |
# - S (e.g. "75") | |
# - M:S (e.g. "2:38") | |
# - H:M:S (e.g. "01:02:03") | |
# | |
# Example: | |
# ytclip "https://www.youtube.com/watch?v=7DV9SZgxegA" --from 2:38 --to 2:41 | |
# | |
# Dependencies: | |
# - yt-dlp (https://github.com/yt-dlp/yt-dlp) | |
# - ffmpeg (https://ffmpeg.org/) | |
# ---------------------- | |
# 1. Parse Arguments | |
# ---------------------- | |
if [[ $# -lt 5 ]]; then | |
echo "Usage: $0 <YOUTUBE_URL> --from <TIME> --to <TIME>" | |
echo "Example: $0 \"https://youtu.be/XYZ\" --from 2:38 --to 2:41" | |
exit 1 | |
fi | |
YOUTUBE_URL="$1" | |
shift | |
FROM_TIME="" | |
TO_TIME="" | |
while [[ $# -gt 0 ]]; do | |
case "$1" in | |
--from) | |
FROM_TIME="$2" | |
shift 2 | |
;; | |
--to) | |
TO_TIME="$2" | |
shift 2 | |
;; | |
*) | |
echo "Unknown option: $1" | |
exit 1 | |
;; | |
esac | |
done | |
# Ensure all required fields are present | |
if [[ -z "$YOUTUBE_URL" || -z "$FROM_TIME" || -z "$TO_TIME" ]]; then | |
echo "Error: Missing required arguments." | |
echo "Usage: $0 <YOUTUBE_URL> --from <TIME> --to <TIME>" | |
exit 1 | |
fi | |
# --------------------------------------- | |
# 2. Convert Time Strings to Seconds | |
# --------------------------------------- | |
# This function accepts S, M:S, or H:M:S and converts to total integer seconds. | |
function hms_to_seconds() { | |
local timestr="$1" | |
local IFS=':' | |
local parts=($timestr) # Split on ':' | |
local len=${#parts[@]} | |
case $len in | |
1) # S | |
echo "$((10#${parts[0]}))" | |
;; | |
2) # M:S | |
echo "$((10#${parts[0]} * 60 + 10#${parts[1]}))" | |
;; | |
3) # H:M:S | |
echo "$((10#${parts[0]} * 3600 + 10#${parts[1]} * 60 + 10#${parts[2]}))" | |
;; | |
*) | |
echo "Invalid time format: $timestr" >&2 | |
exit 1 | |
;; | |
esac | |
} | |
START_SEC=$(hms_to_seconds "$FROM_TIME") | |
END_SEC=$(hms_to_seconds "$TO_TIME") | |
# --------------------------------------- | |
# 3. Calculate Duration & Validate | |
# --------------------------------------- | |
if (( END_SEC <= START_SEC )); then | |
echo "Error: End time must be greater than start time!" | |
exit 1 | |
fi | |
DURATION_SEC=$((END_SEC - START_SEC)) | |
# ----------------------- | |
# 4. Prepare Output | |
# ----------------------- | |
CLIPS_DIR="$HOME/clips" | |
mkdir -p "$CLIPS_DIR" | |
TIMESTAMP="$(date +'%Y%m%d_%H%M%S')" | |
TEMP_FILE="$CLIPS_DIR/temp_${TIMESTAMP}.mp4" | |
OUTPUT_FILE="$CLIPS_DIR/clip_${TIMESTAMP}.mp4" | |
# ----------------------- | |
# 5. Download via yt-dlp | |
# ----------------------- | |
echo "Downloading video to $TEMP_FILE..." | |
yt-dlp --merge-output-format mp4 "$YOUTUBE_URL" -o "$TEMP_FILE" | |
if [[ $? -ne 0 ]]; then | |
echo "Error: Download failed." | |
exit 1 | |
fi | |
# ----------------------- | |
# 6. Use ffmpeg to Clip | |
# ----------------------- | |
echo "Clipping from $FROM_TIME to $TO_TIME (duration: ${DURATION_SEC}s)..." | |
# Notice we put -ss AFTER -i for more accurate seeking | |
ffmpeg -hide_banner -loglevel error \ | |
-i "$TEMP_FILE" \ | |
-ss "$START_SEC" \ | |
-t "$DURATION_SEC" \ | |
-c copy \ | |
"$OUTPUT_FILE" | |
if [[ $? -ne 0 ]]; then | |
echo "Error: ffmpeg clipping failed." | |
exit 1 | |
fi | |
# Remove the large downloaded video, keep only the clip | |
rm -f "$TEMP_FILE" | |
# ----------------------- | |
# 7. Open Finder & Done | |
# ----------------------- | |
open "$CLIPS_DIR" | |
echo "Done! Your clip is at: $OUTPUT_FILE" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment