Skip to content

yearth/SecondEar

Repository files navigation

SecondEar

SecondEar — 给 Agent 一双能听懂长视频的耳朵。

把一个 B 站公开视频链接交给 Agent,SecondEar 会先读取视频信息,再按需取得原生字幕或只下载音频并在本地转写。Agent 拿到带时间戳的字幕后,就能总结长视频、围绕某个时间点讨论,或直接交付字幕文件。

第一版只支持 B 站公开视频。它不使用 Cookie,也不绕过登录、大会员、充电、地区、DRM 或风控限制。

一次完整使用

在手机上的 Codex 或其他 Agent 中直接发送:

https://www.bilibili.com/video/BVxxxxxxxxx

Agent 先执行只读检查,不下载媒体:

second-ear inspect --json 'https://www.bilibili.com/video/BVxxxxxxxxx'

确认视频后,Agent 会问你想总结、讨论还是拿字幕。比如回复“总结前 10 分钟”,它会执行:

second-ear transcribe 'https://www.bilibili.com/video/BVxxxxxxxxx' \
  --range 00:00-10:00 --json

命令返回 transcript.txttranscript.srt 和本次运行记录的路径;同目录还会生成结构化的 transcript.json。再次处理同一分 P、范围、后端与模型时会复用已完成的字幕缓存。

它如何工作

B 站链接 → inspect 元数据 → 尝试原生字幕 → 仅下载所需音频 → 本地 ASR → 字幕缓存 → Agent 总结/讨论
  • 优先使用视频公开提供的原生字幕;没有可用字幕时才进入本地 ASR。
  • 只需要字幕时不下载视频画面;范围转写只请求所选时间段的音频。
  • 默认在成功后删除临时音频,只保留字幕文件和诊断日志;传入 --keep-audio 才保留音频。
  • 不把音频或字幕发送给外部 ASR 服务。首次准备模型需要联网下载模型,读取 B 站内容也需要联网。

安装与首次准备

当前只提供 GitHub 源码安装,暂不发布 PyPI。需要:

  • Python >=3.11,<3.13
  • ffmpegffprobe >=6.1
  • macOS Apple Silicon,或 Linux x86_64
  • uv(推荐安装方式)

跨平台支持的安装方式是检出源码并使用仓库 lockfile。这样 Linux x86_64 会保留 CPU-only PyTorch 索引和已锁定的依赖解析:

git clone https://github.com/yearth/SecondEar.git
cd SecondEar
uv sync --frozen --dev

先检查环境。doctor 只读,不会安装依赖或下载模型;首次运行时看到 model_cache: missing 属于正常现象。

uv run second-ear doctor --json

再完成一次冷启动:下载固定的本地模型快照,并用仓库自带的普通话短音频做真实 smoke test。

uv run second-ear prepare --json

后续在仓库目录内用 uv run second-ear ...。Agent 不在该目录时,可以固定调用:

uv run --project /absolute/path/to/SecondEar second-ear inspect --json URL

其中 /absolute/path/to/SecondEar 替换为实际检出路径。第一版不以直接 Git URL 的 uv tool install 作为跨平台安装方式,因为它不会采用本仓库的 [tool.uv.sources] 和 lockfile,Linux 上可能解析到非 CPU-only 的 PyTorch 包。

模型下载只发生在首次准备或本地模型缓存被清理后。之后 prepare 会复用模型,但仍会运行 smoke test;日常转写直接读取本地模型缓存,不会再经历首次下载等待。JSON 结果包含 model_cache_hitmodel_prepare_secondssmoke_test_secondstotal_secondsrecord,同一份脱敏记录会原子写入 ${SECONDEAR_HOME:-.secondear}/prepare.json,便于之后核对首次准备耗时。

本地 ASR 支持

  • macOS / Apple Silicon:已在本机实测。 使用 mlx-community/whisper-small-mlx-4bit,通过 MLX 在 Apple 芯片上本地运行。
  • Linux / x86_64 CPU:代码支持,尚未在真实 Linux 机器验收。 使用 FunASR iic/SenseVoiceSmall,并配套本地 VAD 与标点模型。现阶段不要把它理解为已验证的 Linux 承诺。
  • 其他平台:不支持。 doctor 会报告 unsupported

后端和模型由平台确定。第一版不提供运行时换模型,也不自动升级 yt-dlp

测试与验收

GitHub Actions 在 Ubuntu、Python 3.11/3.12 上执行固定 lockfile 的 lint 和离线测试;默认 CI 明确排除 live 标记,不访问 B 站,也不下载 ASR 模型。当前仓库配置可本地复现为:

uv sync --frozen --dev
uv run ruff check .
uv run pytest -m "not live" -v

真实 B 站集成测试是显式 opt-in 的本地验收,默认会被 pytest 跳过。准备好当前平台的模型后运行:

uv run second-ear prepare --json
SECONDEAR_LIVE_TEST=1 uv run pytest tests/test_live_bilibili.py -v

测试默认使用一个公开 B 站视频的 00:30-01:30;可通过 BILIBILI_TEST_PUBLIC_URL 覆盖链接。不要在自动 CI 中开启它。macOS Apple Silicon 已执行真实 doctorprepare、B 站范围测试和 10 分钟转写验收;Linux x86_64 仍是代码支持、尚未在真实 Linux 实机验收。

命令

检查链接及多 P 信息:

second-ear inspect --json URL

转写完整的已选视频或分 P:

second-ear transcribe URL --full --json

转写一个时间范围(支持秒、MM:SSHH:MM:SS):

second-ear transcribe URL --range 06:30-12:30 --json

附加选项:

  • --keep-audio:成功后保留本次下载的音频。
  • --force:忽略已完成的字幕缓存并重新处理。
  • --json:输出适合 Agent 消费的结构化结果。

Agent 交互约定

仓库根目录的 SKILL.md 定义了 Agent 应遵循的流程,核心边界是:

  • 只有链接时,先 second-ear inspect --json URL,再询问是总结、讨论还是拿字幕;inspect 阶段不下载、不转写。
  • 用户已说清总结、讨论、字幕或时间范围时,不重复询问意图;但 URL 没有 ?p=N 且本轮尚未确认元数据时,在首次转写前仍只读 inspect 一次,以识别多 P。
  • 多 P 视频未通过 ?p=N 选中分 P 时,列出分 P 并且只询问选择哪一 P,保留用户已经说清的意图;单 P、已有 ?p=N 或本轮已确认元数据时直接继续,不反复 inspect。
  • 总结默认处理完整的已选视频或分 P;围绕时间点讨论时默认取前后各 3 分钟;字幕可取完整内容或指定范围。
  • 仅在失败或用户追问耗时时读取运行日志,不主动发送冗余过程汇报。

缓存、日志与隐私

默认数据目录是执行命令时当前目录下的 .secondear/;设置 SECONDEAR_HOME 可以改到其他位置。

${SECONDEAR_HOME:-.secondear}/
├── prepare.json             # 模型缓存命中、准备、smoke 与总耗时
├── bilibili/<bvid>/p<n>/<range>/<backend-model>/
│   ├── transcript.txt
│   ├── transcript.srt
│   ├── transcript.json
│   └── complete.json
├── runs/run-*/
│   ├── run.json
│   ├── run.log
│   ├── commands.log
│   └── workspace/          # --keep-audio、原生字幕或失败产物可能留在这里
└── run.log                 # 独立 inspect 等命令的默认命令日志

transcribe --json 返回的 run 字段指向对应 run.json。转写失败或需要解释耗时时,先按这个返回路径读取 run.json,不要硬编码 .secondear,这样才能兼容自定义 SECONDEAR_HOME;同目录的 run.log 是阶段、耗时、缓存命中和稳定错误类别的摘要。只有需要定位命令级根因时,再读取同目录的 commands.log

首次模型准备与转写是两个独立流程:prepare.json 记录模型缓存命中、模型准备、smoke test 与准备总耗时;转写的 run.json 记录音频下载、本地 ASR、清理与转写总耗时。Agent 回答首次准备为何耗时时,应读取 prepare --json 返回的 record,而不是在转写日志中寻找冷启动阶段。

commands.log 和独立 inspect 使用的 ${SECONDEAR_HOME:-.secondear}/run.log 会记录已脱敏的命令、stdout 与 stderr。脱敏会处理已知凭证和 URL 查询串,但日志仍可能包含视频标题、元数据、字幕文本或转写工具输出;不要把日志当作绝对不含视频内容的文件,也不要未经检查就对外分享。

SecondEar 当前的安全边界是受信任的单用户、同 UID、本地 CLI。运行目录会采用受限权限并防护常见的路径替换,但恶意同 UID 进程与不受信任的进程内插件不属于当前威胁模型。不要在不受信任的共享运行环境里处理私有媒体。

B 站边界与故障排查

  • 仅支持 B 站标准视频链接,公开能力也只承诺 B 站公开视频。
  • 遇到多 P 且链接没有 ?p=N 时,inspect 会列出分 P 并要求选择;把 ?p=2 之类的参数加到链接后再处理。
  • 登录、大会员、充电、地区、DRM 或风控限制不会被绕过;SecondEar 不接收、提取或注入 Cookie。
  • MODEL_NOT_PREPARED:运行 second-ear prepare --json
  • DEPENDENCY_MISSINGdoctor 非 ready:确认 Python、ffmpeg/ffprobe 和平台依赖满足上面的版本要求。
  • transcribe 其他失败:先读取 JSON 返回的 run 路径,再按需查看同目录 run.logcommands.log;独立 inspect 失败则查看 ${SECONDEAR_HOME:-.secondear}/run.log。必要时用 --force 排除旧缓存,但不要自动升级 yt-dlp

其他视频网站支持不在第一版承诺范围。阿里云 ASR 只记录为未来可选方案,当前没有实现,也不会在本地流程中被调用。

许可证

项目代码使用 MIT License

smoke test 使用的 assets/smoke/mandarin.wav 来自 Google FLEURS,按 CC BY 4.0 单独再分发,不受 MIT License 覆盖;来源、署名、许可链接和 SHA-256 见 assets/smoke/NOTICE.md

About

Give AI agents a second ear for long-form Bilibili videos

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages