从音频或视频文件中识别鸟叫声对应的鸟种,基于康奈尔实验室 BirdNET v2.4 声学模型。自动抽取音轨(无需系统 ffmpeg),采用动态地理/物候权重表(非硬性白名单)做地理校正,并内置节律/颤音检测补齐模型对夜鹰、啄木鸟敲击等连续发声鸟类的识别盲区。支持对整个文件夹的批量识别(如声纹监测设备连续采样数据),输出标准化优先级分级报告,可直接用于指导人工标注排序。可生成语谱图核验。首次使用需联网下载约50MB模型。 Identify bird species from an audio OR vid
birdsong-recognizer · 音视频鸟鸣种类识别是一项面向实际任务的技能,主要用于通过康奈尔实验室的 BirdNET v2.4 声学模型,从音频或视频中识别鸟叫声对应的鸟种;💰 省 token 提示(给执行 Agent) :识别本身(神经网络推理)在本地脚本完成、零 token;
它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。
通过康奈尔实验室的 BirdNET v2.4 声学模型,从音频或视频中识别鸟叫声对应的鸟种。
💰 省 token 提示(给执行 Agent):识别本身(神经网络推理)在本地脚本完成、零 token。 token 主要花在 Agent 读取长输出并二次加工。默认请加
--report参数,让脚本直接 输出成品结论,Agent 几乎只需转述,单次成本可降一个数量级。仅当用户要求深度分析 (逐段明细、调试)时才用非 report 模式。
⚠️ 首次使用必读(给执行 Agent 的强制前置) 本技能需要一个独立 Python 环境 + 联网下载约 50MB 模型,不是开箱即用的纯脚本技能。 在第一次运行 infer.py / spectro.py 之前,Agent 必须先完成下方「Setup」一次性安装; 安装通常需 1–3 分钟(装 tensorflow 等依赖)。请直接执行,不要询问用户是否安装。 后续调用若检测到 venv 已存在则跳过安装。
本技能依赖一个独立 Python 环境。Agent 首次调用前自动执行,无需征求用户同意。
先判断 venv 是否已就绪(幂等):
SKILL_DIR="$(dirname "$(realpath SKILL.md)")" # 或技能实际所在目录 VENV="$SKILL_DIR/.venv" if [ -x "$VENV/bin/python" ] && "$VENV/bin/python" -c "import birdnet, soundfile, imageio_ffmpeg" 2>/dev/null; then echo "环境已就绪,跳过安装" else bash "$SKILL_DIR/scripts/setup.sh" # 自动创建 venv 并装好依赖(1–3 分钟) fi
手动等价方式:
python3 -m venv .venv .venv/bin/pip install -r scripts/requirements.txt
依赖:birdnet(含 tensorflow/scipy/soundfile/pandas)、imageio-ffmpeg(自带静态 ffmpeg,无需系统安装)、matplotlib、requests(v1.4.1 起 calibrate_weights.py / xc_download.py 需要,已加入 requirements.txt 显式声明,此前只是 tensorflow 间接依赖带进来的,未来 tensorflow 版本变化可能导致其消失,故显式声明)。
网络要求:首次运行 infer.py 会从网络下载 BirdNET 模型(约 50MB)到 BIRDNET_APP_DATA 目录。离线环境请提前准备好该目录。识别/批量推理本身(infer.py / batch.py)全程零网络依赖;calibrate_weights.py(GBIF 校准)与 xc_download.py(Xeno-canto 下载)是独立的离线辅助工具,仅在主动调用时才联网,不影响识别流程的离线特性。
确定 Python 解释器:使用上面 setup 出的 venv,例如 VENV=.venv,解释器 $VENV/bin/python。
设定数据目录(避免某些系统对默认目录无写权限):
export BIRDNET_APP_DATA="$PWD/birdnet_data"
首次运行 infer.py 会自动把模型下载到这里(约 50MB),含
acoustic-models/v2.4/tf/model-fp32.tflite 与中文标签 labels/zh.txt(格式 学名_中文名,6522 种)。
直接对音频或视频运行识别(脚本自动抽音轨、无硬编码路径):
$VENV/bin/python scripts/infer.py INPUT.mp4 --region cn --lang zh --keep-audio out.wav
--region cn 启用中国地理/物候动态权重表(scripts/data/region_weights.csv)做地理校正;
--region none 关闭过滤。v1.4.0 起不再是硬性白名单——每个属有一个 [0,1] 权重,
未登记的属给低权重压制(而非直接剔除),保留极小概率真实迷鸟被看到的机会。--month 1-12:传入录制月份可触发候鸟季节性权重折扣(如夏候鸟在冬季出现会被打折)。
建议尽量传入,能进一步压制候鸟在非活跃季节的误判。--bandpass none(或 300,9000):识别夜鹰/鸮/鸠鸽等低频鸟时关闭/放宽带通。--rhythm:开启节律/颤音检测(见下,补 BirdNET 盲区)。--silence-rms:静音过滤阈值,默认自适应(取各段 RMS 中位数 ×0.35)。--report:省 token 首选。脚本内部完成属级归并+置信度分级+节律提示,
直接输出一段成品结论(自动隐含开启地理过滤与节律检测)。Agent 拿到即终稿,
无需读长输出二次加工,token 消耗最低。日常识别/批量强烈建议加此参数。省 token 标准用法(推荐默认这样跑):
$VENV/bin/python scripts/infer.py INPUT.m4a --region cn --bandpass none --report
生成语谱图核验:
$VENV/bin/python scripts/spectro.py INPUT.mp4 spectrogram.png
读图核对鸣声的频段与音节结构是否与模型猜测一致(鸟鸣多在 2–8kHz)。
节律/颤音检测(BirdNET 盲区补充):对夜行性/连续发声的鸟,加 --rhythm:
$VENV/bin/python scripts/infer.py INPUT.m4a --region cn --bandpass none --rhythm
它用「带通→希尔伯特包络→自相关」找持续稳定的脉冲节律,输出疑似时间段
地理校正:BirdNET 训练数据偏向常见/南方种。把 Top 物种与该地点/季节实际分布交叉核对;属级置信通常很高,种级给"最可能"判断并指明本地常见种。
呈现结论:用 present_files 展示 spectrogram.png 与音频,结论用 show_widget 或文字给出。
批量场景(一个文件夹几十~上千条录音,如声纹监测设备连续采样数据):不要循环调用 infer.py——每次调用都要重新加载 TensorFlow + 模型(约1.3-2秒固定开销/次),文件数一多耗时会线性放大。改用 scripts/batch.py,只加载一次模型,逐文件复用同一个 Interpreter:
$VENV/bin/python scripts/batch.py <文件夹> --region cn --month 4 --out results.csv --summary
..._YYYYMMDD_HHMMSS... 模式,如声纹监测设备的标准命名)。priority_tier 字段(high/medium/
rhythm_only/low/corrupted),可直接对接人工标注任务分发——不用再让标注员盲选文件,
按这个字段排队即可(high优先建库确认,rhythm_only提示标注员优先用耳听而非只信模型分数,
low可降低优先级,corrupted直接反馈给采集方不进队列)。--summary:额外输出 .summary.csv ,按小时聚合各优先级占比,一眼看出"哪几个小时段
值得优先人工标注"(如晨昏鸣叫高峰 vs 夜间大概率环境噪声)。geo_mismatch_flag:全量最高分≥0.5 但加权后最高分<0.15 且该物种所属属为低权重,
即"模型给高分但地理不合理"信号,值得整体复核该时段/该模式的录音。--pattern 默认 *.WAV(大小写敏感),文件名后缀不同(如 .wav/.mp3)需显式传入。--month 建议按月分批调用,而非传入单一月份笼统处理。noise_confusable_flag 字段与 needs_spectro_review 优先级分级:
命中 data/noise_confusable_species.csv 里登记的物种时,即使加权后置信度≥0.5,也不会
直接标 high,而是标 needs_spectro_review——这类结果必须先看语谱图人工确认是离散音节
还是无差别环境噪声,确认后才能升级为可信建库记录。权重表校准(用真实分布数据核对 region_weights.csv 是否准确):权重表最初是凭经验手写的,
建议定期用 scripts/calibrate_weights.py 核对:
$VENV/bin/python scripts/calibrate_weights.py --out calibration_report.md
会用 GBIF 免费公开 API(无需 Key,10万次/天额度)查询每个属在中国的真实分布记录数与月份
分布,生成对比报告标出"权重值明显不合理"的条目,供人工审核后手动更新 CSV(不会自动改写)。
务必用全国范围跑(不传 --province)——权重表是 region=cn 全国尺度的配置,用某个省的
数据去校准会把"该省无分布"错误地当成"全国权重该调低"。若要核对具体监测点位周边的物种更
贴近实际,可加 --province Guangdong 单独看一份省级参考报告,但不要拿它去改 CSV。
这一步是纯离线校准工具,不会让 infer.py/batch.py 的推理流程产生任何网络依赖。
9b. 权重表覆盖缺口批量填补(scripts/fill_missing_genera.py,与 calibrate_weights.py 职责不同):
calibrate_weights.py 核对的是"已登记的属,权重值是否准确";本工具解决的是更根本的问题——
"还有哪些属模型认识、中国确有分布,但权重表完全没登记"。实测发现这才是本技能反复遇到
"换一批新数据又要临时补一个属"的根因:v1.4.2 之前权重表只登记了 96 个属,但 BirdNET
v2.4 认识的 1842 个属里,中国有真实 GBIF 分布记录的有 486 个——覆盖率约 20%,缺口 390 个属
(其中 191 个中国记录数≥1000,是明确的常见种,不是冷门边缘案例)。这不是"每次针对特定
物种/特定数据调整",是通用的结构性覆盖不足,每次新地点的录音都会撞见不同的缺口子集。
$VENV/bin/python scripts/fill_missing_genera.py --out fill_missing_new_rows.csv # 人工审核后追加进权重表: cat fill_missing_new_rows.csv >> data/region_weights.csv
Locustella/Batrachostomus/Ammodramus 等真鸟属,它们的俗名或近似词恰好
含 warbler/frogmouth/grasshopper 等误导性词根,实测验证关键词法会产生 12 个假阳性)。all——月份分布在样本不足时不具统计意义,
窄化反而会引入新的季节性误判。data/non_bird_labels.csv,v1.4.4 新增,第四个独立机制):
BirdNET v2.4 的 6522 个标签里混入了 36 个非鸟类"属"(两栖类/昆虫/哺乳类,如青蛙
Lithobates、蟋蟀螽斯 Amblycorypha/Oecanthus、松鼠 Sciurus/Tamias)+ 11 个
特殊类别标签(Dog/Engine/Environmental/Fireworks/Gun/Noise/Siren/Human vocal 等)——
这是训练集里专门用来教模型识别"这不是鸟叫"的负样本类别,不是缺陷。此前这些标签走的
是和"未登记但确实是鸟类的属"完全相同的兜底逻辑(默认权重 0.05 压制),导致一个真实
问题:若某段录音的非鸟类候选原始置信度很高(如美洲牛蛙 0.9),加权后会跌破结论阈值,
最终静默变成"未识别到可靠鸟种"——用户不知道模型其实识别出了什么;更麻烦的是,若同段
还有一个本身不可靠的低分鸟类候选(如白头翁 0.3),系统会把这个存疑猜测当结论端出来,
反而掩盖了"这其实是青蛙"这个更接近真相的判断。--report 模式现在会检测原始(未加权)分数里置信度>=0.5 的非鸟类候选,并区分两种场景
正面提示:① 无可信鸟类候选时,直接说明"检测到疑似 XX(类别),非鸟类候选";
② 有鸟类候选但置信度低于非鸟类候选时,在鸟类候选后追加提示"这段声音也可能根本不是
鸟叫"。真实高置信度鸟类候选(>=0.5)不受此机制干扰。batch.py 新增 non_bird_hint 字段与 likely_non_bird 优先级分级——加权后最高分
不构成可信鸟种结论、但原始分数里有高置信度非鸟类候选时打此标记,提示标注员可直接
跳过或标记来源类别,不必按鸟类逐条核实。class=Aves(ACCEPTED
或 DOUBTFUL),而不是只看第一条模糊匹配结果——否则会把 Buteo(鵟属)/Monticola
(矶鸫属)/Chloris(金翅雀属)/Prunella(岩鹨属) 等无争议的真实鸟类误判为植物/真菌/
昆虫(GBIF 里存在同名的其他生物条目,若不筛选 class 直接取第一条会踩坑)。同理,
taxonomicStatus=SYNONYM(过时同义词)不应采信为鸟类判据,只信 ACCEPTED/DOUBTFUL。补充训练/听音参考样本(Xeno-canto 下载器,与地理校准完全独立的另一条数据源):
$VENV/bin/python scripts/xc_download.py --genus Eudynamys --species scolopaceus --area china --key YOUR_KEY --out ./xc_samples --dry-run
--key 参数或环境变量 XC_API_KEY 传入。--dry-run 只查询元数据不下载音频,确认 key 有效、查询标签正确后再正式下载。calibrate_weights.py 的职责),两者是独立的两条路径。和地理权重表是两个独立机制,职责不同,不要混用:
--report 结论里追加强制人工复核警告。species(学名_中文名,须与 BirdNET 标签格式完全一致)+ reason(说明触发场景与证据)。Porzana porzana_斑胸秧雞——SZYG03 红树林点位实测,宽频环境噪声在无地理
过滤时被判定为该种,置信度可达0.9+;该种中国确有分布,不应靠压低地理权重掩盖,只能靠这份
清单提示人工核验语谱图。model.predict():它的多进程 producer 在受限/沙箱环境会卡死或 fork 风暴(模块级代码被子进程重复执行)。本技能用 tf.lite.Interpreter 直接推理(见 scripts/infer.py)。tf(不是 tflite);版本是 2.4(不带 v)。~/Library/Application Support(macOS)等位置,部分环境无写权限 → 务必设置 BIRDNET_APP_DATA 到可写目录。~/.matplotlib 可能无写权限 → spectro.py 已自动设 MPLCONFIGDIR 到临时目录;如仍报错可手动 export MPLCONFIGDIR=/tmp/mplcache。(idx, prob) 元组,取标签时务必解包为 labels[i](曾因直接用元组索引报 TypeError)。--bandpass 300,9000 或 --bandpass none。注意:即便如此夜鹰仍可能识别不出,属模型固有短板,需结合语谱图人工判断。--silence-rms 默认负数=自适应),静音段在输出里标 ⚠ 且不计入 Top 榜;仍须结合录制场景人工把关。--rhythm 只补「连续发声」盲区(夜鹰churring/啄木鸟敲击/部分鸮),给类群线索而非种级定名;它无法做声源分离,重叠声源(如夜鹰叠在鹰鹃上)时脉冲率会被前景纯音干扰,须结合语谱图与现场聆听确认。脉冲率参考:20-50Hz≈夜鹰churring,3-10Hz≈啄木鸟敲击。~/.keras、~/.matplotlib,受限环境可能被拦截但不影响识别结果;如需消除可设 KERAS_HOME / MPLCONFIGDIR 到临时目录。scripts/batch.py,一次加载模型复用,实测提速可达数倍。--region none 时约28.6%的文件会给出"高置信度但地理不合理"的物种(如把宽频环境噪声/潮汐风声误判成欧洲/古北界物种,置信度可达0.9+),且这类误判高度集中在夜间低信息量时段。批量识别自动入库场景务必开 --region cn(或对应地区权重表),否则会产生系统性的"幽灵物种"记录污染数据。scripts/data/region_weights.csv 定义每个(地区,属)的权重,
推理时用权重去调制原始置信度(乘法),而非硬性剔除不在名单里的候选。若 data/region_weights.csv
缺失(如复制技能目录时遗漏),会自动回退到 infer.py 里 REGION_GENERA 的旧版二元白名单,
不影响可移植性。DEFAULT_UNLISTED_WEIGHT(0.05) 压制,跟它在当地
有多常见无关。核查发现 v1.4.2 时权重表只覆盖了模型认识、且中国有真实分布的属的约 20%
(96/486),缺口 390 个,其中 191 个是中国记录数≥1000 的明确常见种。v1.4.3 用
scripts/fill_missing_genera.py 一次性批量核准并补齐 313 个属(96→409),系统性解决
覆盖率问题,而非逐个补丁。以后若继续用特定测试数据撞出新的缺失属,应先怀疑"是否只是
未登记",而不是默认信任模型或权重表给出的地理过滤结果。Porzana
(斑胸秧鸡所在属)压到 0.15 权重,理由写的是"该属欧洲种常被模型误判为噪声"——这是把"地理是否
合理"和"声学上是否容易被误判"两件不同的事,混进了同一个数值里。用 GBIF 校准
(scripts/calibrate_weights.py)核实后发现:斑胸秧鸡在中国全国有 1854 条真实分布记录(不是
"境外种"),压低地理权重的做法本身没有依据。修复后权重已改回 1.0,但这样一来"模型确实会把
环境噪声误判成这个物种"的真实问题又失去了压制手段——因此拆分出一个独立的
scripts/data/noise_confusable_species.csv:只登记"哪些 label 历史上出现过噪声误判",
不改变任何分数(保持地理权重的诚实性),而是在 --report 结论里追加一条强制人工复核警告
(见下方"噪声易混淆物种清单"小节)。以后新增权重表条目时,判断依据必须是"这个物种在这个
地区/季节是否真的可能出现",不能因为"模型容易在噪声上误报这个名字"而压低地理权重——
这两个问题要用两个不同的机制分别解决。Cuculus rochii 同属 Cuculus,权重表会同等对待,跨大陆种
可能被误判为高分且不受权重压制。这是属级过滤的天花板,下一步升级方向是种级过滤(需要更精细
的地区物种分布数据,如中国观鸟记录中心的分布清单),本次未实现。--month 触发的季节性折扣是"活跃月份内 1.0,月份外 ×0.3"的
简单规则,不是连续的物候曲线,对候鸟迁徙前后的过渡期不够精确,够用但不精细。scripts/calibrate_weights.py)的查询方式选型踩坑记录:初版用
species/match 解析属名拿 taxonKey 再查询,属名跨界撞名严重(Pica/Troglodytes/Passer
等鸟类属名恰好和其他生物学名词根撞车),模糊匹配退化到门/界级别导致查询全部落空;改用
species/search 限定 GBIF Backbone Taxonomy 数据集后属名能解析,但发现属级 taxonKey/
genusKey 在部分属上无法自动展开匹配到下属物种的真实记录(如 Cettia fortipes 已被重新
分类到 Horornis 属,taxonKey 查询对不上);最终改用 q=<属名> 全文检索,不依赖 taxonKey
匹配是否命中分类树,抽样验证过检索结果的 genus 字段 100% 精确匹配。这不是随便选的实现
细节——如果只信任 taxonKey 查询返回的"0条记录",会把大量真实分布的物种误判为"境外种",
这正是本次修复前的错误根源。region=cn(全国尺度)的权重表,导致像 Nucifraga(星鸦,广东确实无分布但全国有 3905+ 条
记录)这类物种被错误地建议压低权重——省级数据只能验证"该省是否有分布",不能反过来证明
"全国范围权重该调低"。校准全国权重表时必须用全国范围数据(不传 --province),省级数据
只用于核对具体监测点位的合理性,不应用来改全国配置。本技能可对外分发,详见 README.md 与 LICENSE(MIT)。模型权重归 BirdNET / 康奈尔鸟类学实验室所有,按其授权使用。
相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134万人学习
共49课时 | 82.5万人学习
最新文章