喜马拉雅音频助手 v2(固定脚本版)
这是什么
v1(旧 playbook,目录 ximalaya-assistant)是一份给 LLM 看的 playbook:
每次都要读 SKILL.md、手动 snapshot、用每次都变的 @ref 号去 click,
而且很多按钮 click @ref 对 React 合成事件静默失败,需要临时写 JS 兜底。
v2 把那套流程固化成一份可重复执行的脚本 ximalaya-audio-assistant.py(本技能,技能 ID:
ximalaya-audio-assistant):
不依赖任何易变 ref,用稳定的 CSS 选择器 + JS eval 直接驱动页面。
LLM 只需决定调哪个子命令、传什么参数,不再临场摸索 DOM。
前置依赖
- 已安装
agent-browser-core技能,且agent-browser在 PATH(可用环境变量
AGENT_BROWSER_CMD覆盖命令名)。 - 浏览器运行时已装:
agent-browser install。 - 首次运行会开浏览器扫码登录,登录态写入
--state指定的文件(默认
ximalaya-state.json),后续复用。
脚本位置
与本文同级:ximalaya-audio-assistant.py
运行(在本机终端,不在沙箱):
python "<技能目录>/ximalaya-audio-assistant.py" --help
子命令(增删改查 + 替换 + 登录)
| 命令 | 作用 | 关键参数 |
|---|---|---|
login |
扫码登录并自动保存登录态(无登录态时先跑这个) | --state --timeout |
upload |
上传并发布 | --album-id --file/--folder --title --intro --tags --topic --ai --discussion --yes |
edit |
编辑已发布音频元数据 | --track-id --title --intro --tags --topic --discussion |
replace |
替换音频文件(保留 ID/元数据) | --album-id --title --file |
replace-cover |
替换单集配图(封面图) | --album-name/--album-id --first/--title/--track-id --image |
delete |
删除音频(不可撤销) | --album-id --title --confirm |
list-albums |
列出我的专辑及 albumId | — |
query |
查专辑全部单集播放数/更新时间,或单集元数据 | --album-id / --track-id |
示例
# 无登录态:先跑 login(截图提示扫码 → 自动轮询 → 自动保存登录态)
python ximalaya-audio-assistant.py login --state "D:/xm-state.json"
# 上传发布一集
python ximalaya-audio-assistant.py upload \
--album-id 12345 --file "D:/a/第1集_最终.wav" \
--title "第一回 标题" --intro "简介" --tags "历史,儿童" \
--topic "历史" --ai --discussion "你更支持哪一方?"
# 查某专辑全部单集的播放数
python ximalaya-audio-assistant.py query --album-id 12345
# 替换某集音频文件
python ximalaya-audio-assistant.py replace --album-id 12345 --title "第1集" --file "D:/new.wav"
# 替换某专辑第一回的配图(封面图)
python ximalaya-audio-assistant.py replace-cover \
--album-name "新长城内外|新中国的诞生与崛起" --first --image "D:/cover.png" --yes
# 删除(必须 --confirm)
python ximalaya-audio-assistant.py delete --album-id 12345 --title "第1集" --confirm
无登录态的处理流程(重要)
运行任何子命令前先确认登录态:若 --state 指定的文件不存在、或上一次运行报
「未登录或会话已过期」,按以下步骤处理(脚本的 login 子命令已实现同一流程):
- 先截图给用户并提示扫码登录:运行
login(或让其它子命令走到未登录分支),
打开登录页(未登录访问创作中心会自动跳到 passport 二维码页),执行
agent-browser screenshot qrcode_login.png,把截图路径告诉用户,
提示用户用喜马拉雅 App 扫码。 - 提示的同时轮询登录状态:不阻塞等待,脚本每 5 秒检查一次
(get url回到studio.ximalaya.com且不再含passport/login即视为已登录),
每 30 秒打印一次等待进度,直到登录成功或超时(默认 5 分钟,可用--timeout调整)。 - 已登录则自动保存登录态:登录成功后执行
agent-browser state save <state文件>,
把 cookie 等登录态写入--state指定的文件(如D:/xm-state.json)。 - 重新用保存的登录态执行用户的要求:带上
--state <文件>重新执行用户原本的
上传/编辑/替换/删除/查询命令,不再要求扫码。
示例:login --state "D:/xm-state.json" 完成后,
upload --state "D:/xm-state.json" ... 即可直接复用登录态。
已固化的关键坑点(都在脚本里处理好了)
- 隐藏
input[name=file]三步上传(先 JS 显示再upload)。 - 「确认发布」「保存」按钮用
dispatchEvent(new MouseEvent('click')),不用click @ref。 - 编辑页简介用 Form API
setFieldsValue({richIntro: html}),且保存前检查是否为空防覆盖。 - 讨论卡片用 React Fiber 找父节点
onClick展开;问题文本用真实键盘事件(CLItype+ CSS 选择器)输入。 - 声音管理页「...」菜单(
manage-point-box)JS dispatchEvent 触发不了 React 弹层,必须真实 mouse 坐标点击
(新增mouse_click():agent-browser mouse move/down/up);菜单项「替换声音」是webuploader-pick,
同样真实点击;上传 input 是input[type=file].webuploader-element-invisible(accept 含 .mp3/.wav),
加临时 id#temp_replace_audio再upload;上传后弹 ant-modal「替换声音 <文件名>/取消/确定」,
用_js_click_modal_confirm()点「确定」。管理页分页(每页 10 条),replace 会自动翻页查找目标(最多 20 页)。
通用教训:React 弹层/菜单内按钮,JS dispatchEvent 都不可靠,优先真实 mouse 坐标点击。 - 标签用
input[placeholder*="回车"]+Enter键事件。 - 话题用 Form API 直写:先走
/reform-upload/upload/getTopicPage?keyword=...API 解析出
metadataId,再setFieldsValue({topicTags: '{"<metadataId>":["<话题名>"]}'}),与已发布单集
getFieldsValue().topicTags格式完全一致。不要用 UI 搜索 5 步法——实测编辑页/上传页的
「话题」搜索面板(.show-more-topic→ 输入框 → Enter)在本机触发不了 onSearch,结果永不渲染;
Form API 直写稳定生效(已实跑验证)。 - 查询统一走
/reform-upload/manage/album/tracksAPI,不爬脆弱的 DOM/截图。 - upload 发布后自动补简介:上传页的富文本简介经常填不进去(
NO_INTRO),脚本在发布拿到
trackId 后会自动打开编辑页检查简介(LEN:0则用 Form API 写回并保存),一条命令完成上传+简介。 - delete 流程(2026-08-23 实跑重写):行内「...」菜单与菜单项「删除」用真实 mouse 坐标点击;
确认弹窗是自定义组件.xmDeleteModal(按钮是span.xmButton.primary,文本「删除」,不是
<button>)——用_js_locate_modal_confirm("删除")定位坐标后真实点击;删除后脚本会重新拉
专辑单集列表验证目标已消失,防止「假成功」。
注意事项
- 脚本无法在 WorkBuddy 沙箱内端到端验证(依赖本机
agent-browser+ 喜马拉雅登录态),
只在真机跑过语法与 JS 片段生成校验。 - 已实跑验证:
upload(含标题/标签/AI 勾选/Form API 话题/发布后自动补简介)与edit --intro
在「新长城内外|新中国的诞生与崛起」专辑第 19/20/21 集上传成功;replace-cover已给该专辑全部
20 集成功换封面(第一回 trackId=1006549933 单测 + 其余 19 集批量 OK:19 FAIL:0)。 - 2026-08-23 完整闭环测试(第二十一回):upload(trackId=1008169793,自动补简介 LEN:0→260→SAVED)
→ edit(改简介 LEN:263→260→SAVED,重开编辑页确认新文本落库)→ replace(行菜单/替换声音/上传/弹窗
确定全流程 CONFIRM_OK,已提交转码)→ delete(自定义弹窗真实鼠标确认,删除后 API 验证专辑 21→20 集,
列表中已无目标)。四步全部通过,脚本定版。 - 替换配图(封面图):编辑页「节目配图」的 file input 没有 name/class,accept 是
.png, .jpg, .jpeg, .bmp(不含 "image" 字样)——脚本按图片扩展名匹配 + 加临时 id
#temp_cover_input上传;上传后必弹裁剪框(.anchor-cropper),必须点「确定」
(.anchor-cropper-bottom-surebtn)才真正提交,否则封面不生效(已验证:上传后不点确定,
保存了封面仍是旧图)。脚本已固化这两步。 - 删除操作不可撤销,脚本强制要求
--confirm;删除成功后脚本会验证专辑列表中已无目标(2026-08-23
实测发现旧版「无验证就报成功」的假成功 bug,已修复)。