Skip to content

Instantly share code, notes, and snippets.

@maximelebastard
Last active December 30, 2024 19:53
Show Gist options
  • Save maximelebastard/5fe1720120c68de7641921b9803be212 to your computer and use it in GitHub Desktop.
Save maximelebastard/5fe1720120c68de7641921b9803be212 to your computer and use it in GitHub Desktop.
Sync Apple Music app and downloaded Apple Podcasts to Shockz OpenSwim MP3
#!/bin/bash
# SyncAudioToDevice.sh
# ===================
# Use case:
# ---------
# I just got a pair of Shockz OpenSwim Pro to swim, and this works like an old-school MP3 player.
# I want to sync my audio content (music and podcasts) from macOS to the device.
# So this script finds and copies downloaded podcasts and music from a specific playlist to the device.
#
# Be careful, it will NOT WORK with content with DRM (typically music from Apple Music)
# a workaround could be to use yt (to find the video on youtube) and yt-dlp (to download the audio) to replace songs with DRM
# feel free to fork !
#
# Description:
# ------------
# This script synchronizes audio content (music and podcasts) from macOS to an external device.
# It handles two main tasks:
# 1. Syncs MP3 files from Apple Podcasts cache to the device
# 2. Syncs music files from a specific Music.app playlist to the device
#
# Requirements:
# ------------
# - macOS system
# - External storage device mounted
# - Music.app with a playlist named "OpenSwim"
# - Apple Podcasts app with downloaded episodes
# - rsync installed (usually pre-installed on macOS)
#
# Usage:
# ------
# 1. Connect your external storage device
# 2. Make sure it is mounted as "SWIM PRO" (or modify DEST_VOLUME variable)
# 3. Run the script: ./SyncAudioToDevice.sh
#
# The script will:
# - Create necessary directories if they don't exist
# - Sync podcast episodes from Apple Podcasts cache
# - Sync music files from the specified playlist
# - Clean up destination directories before copying
# - Show detailed progress during operations
#
# Note:
# -----
# - The script assumes the external device is mounted as "SWIM PRO"
# - The Music playlist must be named "OpenSwim"
# - Modify the variables at the start of the script if needed
# Base directories and settings
DEST_VOLUME="/Volumes/SWIM PRO"
MUSIC_DEST_DIR="$DEST_VOLUME/music"
PODCASTS_DEST_DIR="$DEST_VOLUME/podcasts"
PLAYLIST_NAME="OpenSwim"
GROUP_CONTAINERS="$HOME/Library/Group Containers"
# Check if external volume is mounted
if [ ! -d "$DEST_VOLUME" ]; then
echo "Error: External volume not mounted. Please connect your device."
exit 1
fi
# Create destination directories if they don't exist
echo "Creating destination directories if needed..."
mkdir -p "$MUSIC_DEST_DIR"
mkdir -p "$PODCASTS_DEST_DIR"
# Part 1: Sync Podcasts
echo "=== Starting Podcasts Sync ==="
# Find Apple Podcasts container directory
PODCASTS_CONTAINER=$(find "$GROUP_CONTAINERS" -name "*.com.apple.podcasts" -type d 2>/dev/null)
if [ -z "$PODCASTS_CONTAINER" ]; then
echo "Error: Podcasts folder not found."
exit 1
fi
PODCASTS_CACHE="$PODCASTS_CONTAINER/Library/Cache"
# Sync podcasts using rsync
echo "Syncing podcast files..."
rsync -av --delete --include="*.mp3" --exclude="*" "$PODCASTS_CACHE/" "$PODCASTS_DEST_DIR"
echo "Podcasts sync completed."
# Part 2: Sync Music
echo "=== Starting Music Sync ==="
# Get file paths from Music playlist using AppleScript
echo "Retrieving file paths from playlist '$PLAYLIST_NAME'..."
FILES=$(osascript -e '
tell application "Music"
try
set thePlaylist to playlist "'"$PLAYLIST_NAME"'"
set theTracks to tracks of thePlaylist
set AppleScript'"'"'s text item delimiters to "###"
set theFilePaths to {}
repeat with aTrack in theTracks
try
set theLocation to location of aTrack
set thePath to POSIX path of theLocation
copy thePath to end of theFilePaths
on error
log "Missing file for: " & name of aTrack
end try
end repeat
return theFilePaths as text
on error
return "Playlist not found"
end try
end tell')
# Create array from file paths
IFS='###' read -r -a FILE_ARRAY <<< "$FILES"
# Clean up array entries
for i in "${!FILE_ARRAY[@]}"; do
FILE_ARRAY[$i]=$(echo "${FILE_ARRAY[$i]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
done
# Remove empty entries and clean up spaces
FILE_ARRAY=( "${FILE_ARRAY[@]}" )
FILE_ARRAY=( "${FILE_ARRAY[@]/#/}" )
FILE_ARRAY=( "${FILE_ARRAY[@]/%/}" )
# Display files to be copied
echo "Files to be copied from playlist:"
for i in "${!FILE_ARRAY[@]}"; do
echo " [$i] : ${FILE_ARRAY[$i]}"
done
# Clean destination directory
echo "Cleaning music destination directory..."
rm -rf "${MUSIC_DEST_DIR:?}"/*
# Copy music files
echo "Starting music files copy..."
for SOURCE_FILE in "${FILE_ARRAY[@]}"; do
if [[ -n "$SOURCE_FILE" ]] && [[ -f "$SOURCE_FILE" ]]; then
FILENAME=$(basename "$SOURCE_FILE")
DEST_FILE="$MUSIC_DEST_DIR/$FILENAME"
echo "Copying: $FILENAME"
cp "$SOURCE_FILE" "$DEST_FILE"
if [ $? -eq 0 ]; then
echo "Successfully copied"
else
echo "Error copying $SOURCE_FILE"
fi
fi
done
echo "=== Audio sync completed ==="
echo "Music files copied to: $MUSIC_DEST_DIR"
echo "Podcasts synced to: $PODCASTS_DEST_DIR"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment