mcpField
Y
youtube-to-bookplayer

youtube-to-bookplayer

github.com/terrylica创意与媒体173 次安装1 天前更新
代码仓库

关于 youtube-to-bookplayer

youtube-to-bookplayer 是一项将 YouTube 音频下载并添加元数据,再通过 USB 传到 iPhone 上 BookPlayer 的技能。分阶段流程会检查设备,并验证文件是否传输到位。

主要功能

  1. 01将 YouTube 音频下载为 M4A
  2. 02编辑音频元数据
  3. 03通过 USB 传输到 BookPlayer
  4. 04检查设备和应用是否可用
  5. 05验证传输后的文件

适用场景

  1. 01在 BookPlayer 中收听 YouTube 讲座
  2. 02将长篇 YouTube 音频传到 iPhone
  3. 03用标题和艺人元数据整理下载的音频

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/terrylica/cc-skills --skill youtube-to-bookplayer

安装后在 Claude Code 中输入/youtube-to-bookplayer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
evolution-log.md
tool-reference.md
troubleshooting.md

详细介绍

youtube-to-bookplayer

从 YouTube 视频下载音频、标记元数据,并通过 USB 推送到 iPhone 上的 BookPlayer。

BookPlayer 是一款 iOS 有声书播放器,可记住播放位置,适合收听较长的 YouTube 内容(讲座、有声书、播客)。推送到其 /Documents/ 目录的文件会在下次启动应用时自动导入。


自我迭代技能:此技能会在使用过程中不断改进。如果说明有误、参数发生偏移,或需要采用变通方法,请立即修复此文件,不要拖延。仅针对真实且可复现的问题进行更新。

任务模板

按顺序执行阶段 0–5。每个阶段都有 [Preflight]、[Ask]、[Execute] 或 [Verify] 标签,标明其性质。不要跳过阶段。


阶段 0:预检 [Preflight]

检查所有必需工具和设备连接。快速失败——如果任何检查失败,请勿继续。

# 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.14 --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)"

如果缺少工具:

工具安装命令
yt-dlpbrew install yt-dlp
ffmpegbrew install ffmpeg
exiftoolbrew install exiftool
pymobiledevice3uvx --python 3.14 --from pymobiledevice3 pymobiledevice3 --help

设备检查(仅在工具检查通过后进行):

# Check for connected iOS device
pymobiledevice3 usbmux list 2>/dev/null || uvx --python 3.14 --from pymobiledevice3 pymobiledevice3 usbmux list

# Check BookPlayer is installed
pymobiledevice3 apps list --no-color 2>/dev/null | grep -i "audiobookplayer\|bookplayer" || \
  uvx --python 3.14 --from pymobiledevice3 pymobiledevice3 apps list --no-color 2>/dev/null | grep -i "audiobookplayer\|bookplayer"

如果未找到设备:请用户通过 USB 连接 iPhone、解锁设备并轻点“信任此电脑”。 如果未找到 BookPlayer:请用户从 App Store 安装 BookPlayer。


阶段 1:接收 URL 并确认 [Ask]

如果提供了 $ARGUMENTS[0],将其用作 YouTube URL。否则,使用 AskUserQuestion 询问 URL。

继续之前预览元数据:

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')}\")
"

使用 AskUserQuestion 确认:

  • 标题、频道和时长是否正确
  • 是否要自定义元数据(标题/艺术家/专辑),还是使用 yt-dlp 提供的默认值

阶段 2:下载音频 [Execute]
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

说明:

  • --audio-quality 0 = 可用的最佳质量
  • %(title).100B 将文件名截断为 100 字节(避免文件系统问题)
  • --no-playlist 确保即使 URL 指向播放列表,也只下载单个视频
  • yt-dlp 会自动调用 ffmpeg 转换为 M4A

阶段 3:标记元数据 [Execute]

从 yt-dlp JSON 中提取元数据,并应用到 M4A 文件:

# 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"

变量(来自阶段 1 的确认):

  • $TITLE — 视频标题(或用户自定义的标题)
  • $ARTIST — 频道名称(或用户自定义的名称)
  • 专辑默认为“YouTube Audio”,除非用户另有指定

阶段 4:推送到 BookPlayer [Execute]

重要:使用 Python API,并设置 documents_only=True。CLI pymobiledevice3 apps push 使用 VendContainer 模式,无法用于 BookPlayer。

M4A_FILE=$(ls "$WORK_DIR"/*.m4a | head -1)
FILENAME=$(basename "$M4A_FILE")

uvx --python 3.14 --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

反面示例——不要使用:

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

阶段 5:验证 [Verify]

列出 BookPlayer 的 /Documents/ 目录,确认文件已传入:

uvx --python 3.14 --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

向用户报告:

  • BookPlayer 中的文件名和大小
  • 时长(来自阶段 1 的元数据)
  • 提醒用户:在 iPhone 上打开 BookPlayer 查看新文件(如果文件未显示,请强制退出并重新打开应用)

清理:

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

故障排除速查

问题快速修复
未找到设备解锁 iPhone,重新插拔 USB,轻点“信任”
文件未显示在 BookPlayer 中你使用了 CLI——必须使用设置了 documents_only=True 的 Python API
显示的元数据有误使用正确的 -Title/-Artist 值重新运行阶段 3

完整故障排除说明:references/troubleshooting.md


参考资料


变更后检查清单

修改此技能时,请确认:

  • Phase 0 预检能识别所有缺失的工具,并提供正确的安装命令
  • Phase 4 使用 Python API,并设置 documents_only=True(绝不使用 CLI apps push)
  • 不包含硬编码路径——使用 $HOME、mktemp、command -v、create_using_usbmux()
  • Python 命令使用 --python 3.14(遵循全局策略)
  • Phase 4 保留了反模式警告

执行后复盘

此技能运行完毕后,请在结束任务前进行复盘:

  1. 确认文件位置。 — 编辑前,通过 Glob 搜索此技能的名称,找到此 SKILL.md 的规范路径。所有修正都针对此文件及其同级的 references/——绝不修改其他文档。
  2. 出了什么问题? — 修复导致问题的指令。如果问题可能再次发生,将其列为反模式。
  3. 哪些做法比预期更有效? — 将其提升为推荐实践,并说明原因。
  4. 哪些内容已发生偏差? — 任何与实际情况不再一致的脚本、参考资料或外部依赖,都应立即修正。
  5. 记录下来。 — 每项变更都要在演进日志中记录触发原因、修复内容和证据。

不要推迟。下一次调用会继承你留下的一切

评论

支持 Markdown