Skip to content
Back to skills

Youtube To Bookplayer

ASecurity

Download YouTube audio and push to BookPlayer on iPhone via USB. TRIGGERS - youtube audio, bookplayer, download youtube

  • 75 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added May 27, 2026
toolspythonrustbashapidocumentation

Works with

  • cli
  • api

Security analysis

A93/100
  • highPerforms destructive filesystem operations

Pro scans all 4 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add terrylica/cc-skills --skill youtube-to-bookplayer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Youtube To Bookplayer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Youtube To Bookplayer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terrylica-youtube-to-bookplayer/badge)](https://www.skillsdirectory.com/skills/terrylica-youtube-to-bookplayer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: youtube-to-bookplayer
description: Download YouTube audio and push to BookPlayer on iPhone via USB. TRIGGERS - youtube audio, bookplayer, download youtube
allowed-tools: Bash, Read, AskUserQuestion
argument-hint: "[YouTube URL]"
---

# youtube-to-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.

## Task Template

Execute phases 0–5 sequentially. Each phase has a `[Preflight]`, `[Ask]`, `[Execute]`, or `[Verify]` tag indicating its nature. **Do not skip phases.**

---

### Phase 0: Preflight [Preflight]

Check all required tools and device connectivity. **Fail fast** — do not proceed if any check fails.

```bash
# 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):

```bash
# 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.

---

### Phase 1: Accept URL & Confirm [Ask]

**If `$ARGUMENTS[0]` is provided**, use it as the YouTube URL. Otherwise, use AskUserQuestion to ask for the URL.

**Preview metadata before proceeding:**

```bash
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:

- Title, channel, duration look correct
- Whether to customize the metadata (title/artist/album) or use defaults from yt-dlp

---

### Phase 2: Download Audio [Execute]

```bash
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 URLs
- ffmpeg is auto-invoked by yt-dlp for M4A conversion

---

### Phase 3: Tag Metadata [Execute]

Extract metadata from yt-dlp JSON and apply to the M4A file:

```bash
# 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)
- Album defaults to "YouTube Audio" unless user specifies otherwise

---

### Phase 4: Push to BookPlayer [Execute]

> **CRITICAL**: Use the Python API with `documents_only=True`. The CLI `pymobiledevice3 apps push` uses VendContainer mode and **will not work** with BookPlayer.

```bash
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:**

```bash
# WRONG: This uses VendContainer mode and fails silently on BookPlayer
pymobiledevice3 apps push com.tortugapower.audiobookplayer /path/to/file.m4a
```

---

### Phase 5: Verify [Verify]

List BookPlayer's `/Documents/` directory to confirm the file arrived:

```bash
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:**

- File name and size in BookPlayer
- Duration (from Phase 1 metadata)
- Remind: open BookPlayer on iPhone to see the new file (force-quit and reopen if it doesn't appear)

**Cleanup:**

```bash
# Remove temp working directory
rm -rf "$WORK_DIR"
echo "Cleaned up: $WORK_DIR"
```

---

## Troubleshooting Quick Reference

| 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](./references/troubleshooting.md)

---

## References

- [Tool Reference](./references/tool-reference.md) — yt-dlp flags, pymobiledevice3 API, exiftool tags
- [Troubleshooting](./references/troubleshooting.md) — Known issues, diagnostic commands
- [Evolution Log](./references/evolution-log.md) — Origin and key discoveries

---

## Post-Change Checklist

When modifying this skill, verify:

- [ ] Phase 0 preflight catches all missing tools with correct install commands
- [ ] Phase 4 uses Python API with `documents_only=True` (never CLI `apps push`)
- [ ] No hardcoded paths — uses `$HOME`, `mktemp`, `command -v`, `create_using_usbmux()`
- [ ] Python commands use `--python 3.13` (per global policy)
- [ ] Anti-pattern warning is preserved in Phase 4

## Post-Execution Reflection

After this skill completes, reflect before closing the task:

0. **Locate yourself.** — Find this SKILL.md's canonical path (Glob for this skill's name) before editing. All corrections target THIS file and its sibling references/ — never other documentation.
1. **What failed?** — Fix the instruction that caused it. If it could recur, add it as an anti-pattern.
2. **What worked better than expected?** — Promote it to recommended practice. Document why.
3. **What drifted?** — Any script, reference, or external dependency that no longer matches reality gets fixed now.
4. **Log it.** — Every change gets an evolution-log entry with trigger, fix, and evidence.

## Do NOT defer. The next invocation inherits whatever you leave behind

Files in this skill

  • SKILL.md9.6 KB
  • references/evolution-log.md1.7 KB
  • references/tool-reference.md3.9 KB
  • references/troubleshooting.md3.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.