Last active
December 30, 2024 19:53
-
-
Save maximelebastard/5fe1720120c68de7641921b9803be212 to your computer and use it in GitHub Desktop.
Sync Apple Music app and downloaded Apple Podcasts to Shockz OpenSwim MP3
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
#!/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