Download YouTube audio and push to BookPlayer on iPhone via USB. TRIGGERS - youtube audio, bookplayer, download youtube, push to iphone, youtube to bookplayer, audiobook from youtube, youtube bookplayer
Download audio from a YouTube video, tag metadata, and push to BookPlayer on iPhone via USB.
BookPlayer is an iOS audiobook player that resumes playback position — ideal for long-form YouTube content (lectures, audiobooks, podcasts). Files pushed to its /Documents/ directory are auto-imported on next app launch.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Execute phases 0–5 sequentially. Each phase has a [Preflight], [Ask], [Execute], or [Verify] tag indicating its nature. Do not skip phases.
Check all required tools and device connectivity. Fail fast — do not proceed if any check fails.
# Tool availability
TOOLS_OK=true
for tool in yt-dlp ffmpeg exiftool; do
if command -v "$tool" &>/dev/null; then
echo "$tool: OK ($(command -v "$tool"))"
else
echo "$tool: MISSING"
TOOLS_OK=false
fi
done
# pymobiledevice3 (may only be available via uvx)
if command -v pymobiledevice3 &>/dev/null; then
echo "pymobiledevice3: OK ($(command -v pymobiledevice3))"
else
if uvx --python 3.13 --from pymobiledevice3 pymobiledevice3 --help &>/dev/null 2>&1; then
echo "pymobiledevice3: OK (via uvx)"
else
echo "pymobiledevice3: MISSING"
TOOLS_OK=false
fi
fi
echo "---"
[ "$TOOLS_OK" = true ] && echo "All tools OK" || echo "BLOCKED: Install missing tools (see table below)"
If tools are missing:
| Tool | Install Command |
|---|---|
yt-dlp | brew install yt-dlp |
ffmpeg | brew install ffmpeg |
exiftool | brew install exiftool |
pymobiledevice3 | uvx --python 3.13 --from pymobiledevice3 pymobiledevice3 --help |
Device check (only after tools pass):
# Check for connected iOS device
pymobiledevice3 usbmux list 2>/dev/null || uvx --python 3.13 --from pymobiledevice3 pymobiledevice3 usbmux list
# Check BookPlayer is installed
pymobiledevice3 apps list --no-color 2>/dev/null | grep -i "audiobookplayer\|bookplayer" || \
uvx --python 3.13 --from pymobiledevice3 pymobiledevice3 apps list --no-color 2>/dev/null | grep -i "audiobookplayer\|bookplayer"
If no device found: ask user to connect iPhone via USB, unlock it, and tap "Trust This Computer". If BookPlayer not found: ask user to install BookPlayer from the App Store.
If $ARGUMENTS[0] is provided, use it as the YouTube URL. Otherwise, use AskUserQuestion to ask for the URL.
Preview metadata before proceeding:
yt-dlp --dump-json --no-download "$URL" 2>/dev/null | python3 -c "
import json, sys
d = json.load(sys.stdin)
hrs, rem = divmod(int(d.get('duration', 0)), 3600)
mins, secs = divmod(rem, 60)
print(f\"Title: {d.get('title', 'Unknown')}\")
print(f\"Channel: {d.get('channel', 'Unknown')}\")
print(f\"Duration: {hrs}h {mins}m {secs}s\")
print(f\"Upload: {d.get('upload_date', 'Unknown')}\")
"
Use AskUserQuestion to confirm:
WORK_DIR=$(mktemp -d)
echo "Working directory: $WORK_DIR"
yt-dlp -x --audio-format m4a --audio-quality 0 --no-playlist \
-o "$WORK_DIR/%(title).100B.%(ext)s" \
"$URL"
# Show result
ls -lh "$WORK_DIR"/*.m4a
Notes:
--audio-quality 0 = best available quality%(title).100B truncates filename to 100 bytes (prevents filesystem issues)--no-playlist ensures single video download even from playlist URLsExtract metadata from yt-dlp JSON and apply to the M4A file:
# Get the downloaded file path
M4A_FILE=$(ls "$WORK_DIR"/*.m4a | head -1)
# Apply metadata (use values confirmed in Phase 1, or yt-dlp defaults)
exiftool -overwrite_original \
-Title="$TITLE" \
-Artist="$ARTIST" \
-Album="YouTube Audio" \
"$M4A_FILE"
# Verify tags
exiftool -Title -Artist -Album "$M4A_FILE"
Variables (from Phase 1 confirmation):
$TITLE — Video title (or user-customized)$ARTIST — Channel name (or user-customized)CRITICAL: Use the Python API with
documents_only=True. The CLIpymobiledevice3 apps pushuses VendContainer mode and will not work with BookPlayer.
M4A_FILE=$(ls "$WORK_DIR"/*.m4a | head -1)
FILENAME=$(basename "$M4A_FILE")
uvx --python 3.13 --from pymobiledevice3 python3 << 'PYEOF'
import sys
from pathlib import Path
from pymobiledevice3.lockdown import create_using_usbmux
from pymobiledevice3.services.house_arrest import HouseArrestService
local_path = sys.argv[1] if len(sys.argv) > 1 else None
if not local_path:
# Find the m4a file from environment
import glob, os
work_dir = os.environ.get("WORK_DIR", "/tmp")
files = glob.glob(os.path.join(work_dir, "*.m4a"))
if not files:
print("ERROR: No .m4a file found in work directory")
sys.exit(1)
local_path = files[0]
file_path = Path(local_path)
filename = file_path.name
file_data = file_path.read_bytes()
size_mb = len(file_data) / (1024 * 1024)
print(f"Pushing: {filename} ({size_mb:.1f} MB)")
lockdown = create_using_usbmux()
service = HouseArrestService(
lockdown=lockdown,
bundle_id="com.tortugapower.audiobookplayer",
documents_only=True # CRITICAL: VendDocuments mode
)
service.set_file_contents(f"/Documents/{filename}", file_data)
print(f"SUCCESS: {filename} pushed to BookPlayer /Documents/")
PYEOF
Anti-pattern — DO NOT USE:
# WRONG: This uses VendContainer mode and fails silently on BookPlayer
pymobiledevice3 apps push com.tortugapower.audiobookplayer /path/to/file.m4a
List BookPlayer's /Documents/ directory to confirm the file arrived:
uvx --python 3.13 --from pymobiledevice3 python3 << 'PYEOF'
from pymobiledevice3.lockdown import create_using_usbmux
from pymobiledevice3.services.house_arrest import HouseArrestService
lockdown = create_using_usbmux()
service = HouseArrestService(
lockdown=lockdown,
bundle_id="com.tortugapower.audiobookplayer",
documents_only=True
)
files = service.listdir("/Documents/")
print("BookPlayer /Documents/ contents:")
for f in sorted(files):
if f.startswith('.'):
continue
try:
info = service.stat(f"/Documents/{f}")
size_mb = info.get('st_size', 0) / (1024 * 1024)
print(f" {f} ({size_mb:.1f} MB)")
except Exception:
print(f" {f}")
PYEOF
Report to user:
Cleanup:
# Remove temp working directory
rm -rf "$WORK_DIR"
echo "Cleaned up: $WORK_DIR"
| Problem | Quick Fix |
|---|---|
| No device found | Unlock iPhone, re-plug USB, tap "Trust" |
| File not in BookPlayer | You used the CLI — must use Python API with documents_only=True |
| Wrong metadata shown | Re-run Phase 3 with correct -Title/-Artist values |
Full troubleshooting: references/troubleshooting.md
When modifying this skill, verify:
documents_only=True (never CLI apps push)$HOME, mktemp, command -v, create_using_usbmux()--python 3.13 (per global policy)After this skill completes, reflect before closing the task: