Skip to content

Instantly share code, notes, and snippets.

@hiroto-takatoshi
Created December 16, 2025 15:44
Show Gist options
  • Select an option

  • Save hiroto-takatoshi/2c2c1d3fe38a024015dfaa2b0117e53f to your computer and use it in GitHub Desktop.

Select an option

Save hiroto-takatoshi/2c2c1d3fe38a024015dfaa2b0117e53f to your computer and use it in GitHub Desktop.
Podcast Downloader Script
#!/bin/bash
# Podcast Downloader Script
# Downloads audio from Twitter/YouTube and uploads to Google Drive
set -e
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default values
URL=""
FILENAME=""
KEEP_FILE=false
INTERACTIVE=true
# Function to show usage
show_help() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Download podcast audio from Twitter/YouTube and upload to Google Drive"
echo ""
echo "Options:"
echo " -u, --url URL URL to download (Twitter/YouTube) [required]"
echo " -f, --filename NAME Custom filename (optional, auto-generated if not provided)"
echo " -k, --keep Keep local file after upload (default: delete)"
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0 -u https://x.com/user/status/123"
echo " $0 -u https://youtube.com/watch?v=abc -f my-podcast"
echo " $0 -u https://x.com/user/status/123 -f episode-1 -k"
exit 0
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-u|--url)
URL="$2"
INTERACTIVE=false
shift 2
;;
-f|--filename)
FILENAME="$2"
INTERACTIVE=false
shift 2
;;
-k|--keep)
KEEP_FILE=true
INTERACTIVE=false
shift
;;
-h|--help)
show_help
;;
*)
echo "Unknown option: $1"
show_help
;;
esac
done
echo -e "${BLUE}=== Podcast Downloader ===${NC}\n"
# Check for yt-dlp updates
echo -e "${YELLOW}Checking for yt-dlp updates...${NC}"
if command -v yt-dlp &> /dev/null; then
CURRENT_VERSION=$(yt-dlp --version 2>/dev/null || echo "unknown")
echo "Current version: $CURRENT_VERSION"
# Check if update is available and update
UPDATE_OUTPUT=$(yt-dlp -U 2>&1 || true)
if echo "$UPDATE_OUTPUT" | grep -q "Updating\|Updated"; then
echo -e "${GREEN}yt-dlp updated successfully${NC}\n"
else
echo -e "${GREEN}yt-dlp is up to date${NC}\n"
fi
else
echo -e "${YELLOW}Error: yt-dlp not found. Please install it first.${NC}"
exit 1
fi
# Get URL from user (if not provided via CLI)
if [ -z "$URL" ]; then
read -p "Enter URL (Twitter/YouTube): " URL
if [ -z "$URL" ]; then
echo "Error: URL cannot be empty"
exit 1
fi
fi
# Get optional filename (if not provided via CLI)
if [ -z "$FILENAME" ] && [ "$INTERACTIVE" = true ]; then
read -p "Enter filename (optional, press Enter to auto-generate): " FILENAME
fi
# Check if rclone is configured
if ! command -v rclone &> /dev/null; then
echo -e "${YELLOW}Error: rclone not found. Please install it first.${NC}"
exit 1
fi
# Check if gdrive remote exists
if ! rclone listremotes | grep -q "gdrive:"; then
echo -e "${YELLOW}Error: Google Drive remote not configured. Please run 'rclone config' first.${NC}"
exit 1
fi
# Check if podcasts folder exists, create if not
if ! rclone lsd gdrive: | grep -q "podcasts"; then
echo -e "${YELLOW}Creating podcasts folder in Google Drive...${NC}"
rclone mkdir gdrive:podcasts
fi
# Download audio
echo -e "\n${BLUE}Downloading audio at 128k bitrate...${NC}"
if [ -z "$FILENAME" ]; then
# Auto-generate filename
yt-dlp -x --audio-format m4a --audio-quality 128K "$URL"
# Get the downloaded filename (most recently modified audio file)
DOWNLOADED_FILE=$(ls -t *.m4a 2>/dev/null | head -1)
else
# Use custom filename - add extension if not provided
if [[ "$FILENAME" != *.* ]]; then
FILENAME="${FILENAME}.m4a"
fi
# Download to temp location first to get the actual format
TEMP_DIR=$(mktemp -d)
yt-dlp -x --audio-format m4a --audio-quality 128K -o "$TEMP_DIR/temp.%(ext)s" "$URL"
# Get the actual downloaded file
ACTUAL_FILE=$(find "$TEMP_DIR" -type f -name "*.m4a" | head -1)
if [ -n "$ACTUAL_FILE" ]; then
# Use user's filename with m4a extension
DOWNLOADED_FILE="${FILENAME%.*}.m4a"
mv "$ACTUAL_FILE" "$DOWNLOADED_FILE"
else
echo -e "${YELLOW}Error: Could not determine downloaded file format${NC}"
rm -rf "$TEMP_DIR"
exit 1
fi
rm -rf "$TEMP_DIR"
fi
if [ ! -f "$DOWNLOADED_FILE" ]; then
echo -e "${YELLOW}Error: Download failed or file not found${NC}"
exit 1
fi
echo -e "${GREEN}Download complete: $DOWNLOADED_FILE${NC}"
# Upload to Google Drive
echo -e "\n${BLUE}Uploading to Google Drive /podcasts...${NC}"
rclone copy "$DOWNLOADED_FILE" gdrive:podcasts/
echo -e "${GREEN}Upload complete!${NC}"
echo -e "\nFile location: gdrive:podcasts/$DOWNLOADED_FILE"
# Handle local file cleanup
if [ "$INTERACTIVE" = true ]; then
read -p "Keep local file? (y/n, default: n): " KEEP_FILE_INPUT
if [ "$KEEP_FILE_INPUT" = "y" ] || [ "$KEEP_FILE_INPUT" = "Y" ]; then
KEEP_FILE=true
fi
fi
if [ "$KEEP_FILE" = true ]; then
echo -e "${GREEN}Local file kept: $DOWNLOADED_FILE${NC}"
else
rm "$DOWNLOADED_FILE"
echo -e "${GREEN}Local file removed${NC}"
fi
echo -e "\n${GREEN}Done!${NC}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment