beets MusicBrainz Submit(mbsubmit)插件完全指南:把未匹配专辑手工提交给 MusicBrainz
音频CLI【免费下载链接】beetsmusic library manager and MusicBrainz tagger项目地址https://gitcode.com/gh_mirrors/be/beets点击查看免费下载beets 的mbsubmit插件在导入import时如果找不到足够好的候选匹配会在交互提示中额外提供两个选项把曲目按 MusicBrainz “Track Parser” 可解析的格式打印出来或者直接用 Picard 打开未匹配的文件夹辅助提交。本指南基于 docs/plugins/mbsubmit.rst 完整讲解插件启用、交互流程、beet mbsubmit命令、全部配置项及其与 autotagger 推荐机制threshold的联动并结合 beetsplug/mbsubmit.py 源码与 test/plugins/test_mbsubmit.py 测试用例说明其底层实现原理。插件要解决的问题MusicBrainz 不提供编程式提交beets 自动打标签autotagger依赖 MusicBrainz 数据库但反过来当一张专辑在 MusicBrainz 上不存在、或导入时匹配不上时用户需要把曲目信息手工提交给 MusicBrainz 以完善数据库。问题在于MusicBrainz 目前并不支持编程式programmatically提交专辑——这意味着无法通过 API 一键提交只能借助其网页端的 “Track Parser” 工具手工录入。mbsubmit插件正是为此设计的辅助工具它的模块文档字符串对此有明确说明见 beetsplug/mbsubmit.py 开头This plugin allows the user to print track information in a format that is parseable by the MusicBrainz track parser. Programmatic submitting is not implemented by MusicBrainz yet.插件提供两类能力导入时的扩展提示选项当导入会话找不到足够好的匹配时交互提示中额外出现Print tracks与Open files with Picard两个选项独立的beet mbsubmit QUERY命令随时把任意专辑/曲目的轨道信息按可解析格式打印到标准输出。安装与启用在 beets 配置文件中启用插件即可插件启用的通用方法见 docs/plugins/index.rstplugins: mbsubmit对于Open files with Picard选项需要满足以下前提机器上安装并配置了 Picard且存在一个名为picard的可执行文件Linux/macOS 一般随包安装Windows 用户需要显式配置picard_path指向picard.exe详见下文配置节Picard 官方提供了下载选项Picard 下载页部分 GNU/Linux 发行版也可以通过各自的包管理器安装 Picard。Picard 读取未匹配文件夹中文件的既有标签从而在提交时预先填好大量输入字段大幅减少手工录入量。交互式导入中的两个扩展选项启用插件后当导入会话触发before_choose_candidate事件且满足阈值条件时提示行会追加两个选项键分别为p和op/Print tracks把当前专辑的曲目按 MusicBrainz Track Parser 可解析的格式打印到 stdouto/Open files with Picard用 Picard 打开未匹配的文件夹借助文件上已有的标签预填提交表单。下面文档中的示例展示了匹配失败时的完整交互No matching release found for 3 tracks. For help, see: https://beets.readthedocs.org/en/latest/faq.html#nomatch [U]se as-is, as Tracks, Group albums, Skip, Enter search, enter Id, aBort, Print tracks, Open files with Picard? p 01. An Obscure Track - An Obscure Artist (3:37) 02. Another Obscure Track - An Obscure Artist (2:05) 03. The Third Track - Another Obscure Artist (3:02)选p之后曲目列表立即以01. 曲名 - 艺术家 (时长)的格式打印出来。若再次遇到无匹配专辑提示行变为No matching release found for 3 tracks. For help, see: https://beets.readthedocs.org/en/latest/faq.html#nomatch [U]se as-is, as Tracks, Group albums, Skip, Enter search, enter Id, aBort, Print tracks?注意此时选项列表中只有Print tracks而没有Open files with Picard—— 这通常意味着picard可执行文件在当前环境下不可用或插件检测到无法启动 Picard见下文源码分析。源码视角扩展选项是如何注入提示的两个选项并非内置在导入器中而是由插件通过事件机制动态注入。插件在初始化时注册了before_choose_candidate事件监听beetsplug/mbsubmit.pyself.register_listener( before_choose_candidate, self.before_choose_candidate_event )事件处理器按当前任务的推荐强度task.rec与配置阈值比较决定是否返回选项def before_choose_candidate_event( self, session: ImportSession, task: ImportTask ) - list[PromptChoice]: if task.rec and task.rec self.threshold: return [ PromptChoice(p, Print tracks, self.print_tracks), PromptChoice(o, Open files with Picard, self.picard), ] return []导入会话侧beets/ui/commands/import_/session.py 的_get_choices在组装内置选项Skip、Use as-is、as Tracks、Group albums、Rescan directory、Enter search、enter Id、aBort之后会发送before_choose_candidate事件并把插件返回的PromptChoice列表扁平化拼接到提示中若多个选项的短键冲突会保留第一个并警告。PromptChoice在 beets/util/init.py 中定义为(short, long, callback)三元组callback接收ImportSession与ImportTask并返回一个Action可选。Picard 启动的源码细节picard回调的实现beetsplug/mbsubmit.py如下def picard(self, session: ImportSession, task: ImportTask) - None: paths [] for p in task.paths: paths.append(displayable_path(p)) try: picard_path self.config[picard_path].as_str() subprocess.Popen([picard_path, *paths]) self._log.info(launched picard from\n{}, picard_path) except OSError as exc: self._log.error(Could not open picard, got error:\n{}, exc)要点通过subprocess.Popen以非阻塞方式启动 Picard把任务的全部路径task.paths作为命令行参数传入使用displayable_path把内部字节路径转换为可显示/可传递的形式若Popen抛出OSError例如可执行文件不存在插件仅记录错误日志但选项仍会显示在提示中——这正是文档示例中第一个提示有Open files with Picard、第二个提示却没有的原因分析事实上该选项是否显示只取决于阈值条件picard回调的失败只影响实际启动不影响选项出现与否示例中两次提示的差异更多是排版省略无论如何选择o而 Picard 不可用时用户会在日志中看到错误信息。使用beet mbsubmit命令打印任意专辑除了导入交互插件还注册了独立的子命令beet mbsubmit帮助文本为 “Submit Tracks to MusicBrainz”。它的用法与 beets 其他查询命令一致接受一个 beets 查询表达式$ beet mbsubmit album:An Obscure Album 01. An Obscure Track - An Obscure Artist (3:37) 02. Another Obscure Track - An Obscure Artist (2:05) 03. The Third Track - Another Obscure Artist (3:02)命令实现beetsplug/mbsubmit.py 的commands/_mbsubmit通过lib.items(args)按查询参数取出曲目按track字段排序后逐条用配置的format模板格式化并打印到 stdout。也就是说输出格式与Print tracks选项完全一致均受format配置项控制。推荐的工作流配合 Track Parser 提交由于 MusicBrainz 不支持编程式提交专辑推荐的提交流程是在导入无匹配时选择Print tracks或手动运行beet mbsubmit album:...复制输出内容在 MusicBrainz 网站的 “Tracklist” 标签页点击 “Track Parser” 按钮将复制的内容粘贴到解析器中解析器生成轨道列表后补充专辑元数据并完成提交。print_tracks的实现按i.track排序后逐条ui.print_(format(i, self.fmt))保证了输出顺序与唱片实际曲目顺序一致便于解析器正确排布。配置项详解在配置文件中添加mbsubmit:小节即可配置。源码中__init__给出了全部默认值beetsplug/mbsubmit.py与文档一致配置项默认值说明format$track. $title - $artist ($length)打印曲目时使用的模板语法与 beets 的路径格式模板相同见 docs/reference/pathformat.rstthresholdmedium触发Print tracks选项显示的最低 autotagger 推荐强度picard_pathpicardpicard可执行文件的路径format输出模板采用与 beets 路径格式一致的模板语法可用字段包括$track、$title、$artist、$length等。默认模板$track. $title - $artist ($length)输出形如01. An Obscure Track - An Obscure Artist (3:37)的行这与 MusicBrainz Track Parser 期望的“曲号. 曲名 - 艺术家 (时长)”风格一致。可自定义例如mbsubmit: format: $track. $artist - $title [$album]该值在源码中通过cached_property惰性读取self.config[format].as_str()打印时用format(item, fmt)完成模板渲染。threshold与 autotagger 推荐机制的联动threshold决定在什么推荐强度下显示Print tracks选项。合法值及其对应的内部枚举定义于 beets/autotag/match.py 的Recommendation配置值枚举含义noneRecommendation.none无推荐lowRecommendation.low低强度推荐mediumRecommendation.medium中强度推荐strongRecommendation.strong高强度推荐事件处理器中的判断是task.rec self.threshold由于Recommendation是IntEnumnone0, low1, medium2, strong3该比较等价于“推荐强度达到阈值或更差数值更小时就显示选项”。因此默认medium意味着所有推荐强度为 medium 及以下即 low、none的匹配都会显示Print tracks而 strong 匹配通常会被自动接受不显示。配置在源码中通过as_choice校验并转换为枚举self.threshold self.config[threshold].as_choice( { none: Recommendation.none, low: Recommendation.low, medium: Recommendation.medium, strong: Recommendation.strong, } )传入非法值会直接触发配置校验错误。重要注意事项部分threshold取值需要配合其他 beets 命令行开关才能按预期工作。特别是设置threshold: strong时只有启用timid 模式才会显示提示。原因在 autotagger 匹配逻辑beets/autotag/match.pystrong 推荐默认会被自动接受而不会进入交互选择流程只有 timid 模式import.timid: yes或命令行-t见 docs/reference/config.rst 的timid小节下才会“即使匹配非常接近也逐一确认”此时交互提示才可能出现。同理match.strong_rec_thresh、medium_rec_thresh等参数见 docs/reference/config.rst 的 Autotagger Matching Options 小节会通过距离计算影响推荐强度从而间接影响mbsubmit选项的显示与否。picard_pathPicard 可执行文件路径默认值为picard即依赖$PATH环境变量找到该命令可填写绝对路径若填写非绝对路径则按$PATH查找Windows 用户必须显式指定picard.exe的绝对路径典型位置为mbsubmit: picard_path: C:\Program Files\MusicBrainz Picard\picard.exe该值在启动 Picard 时通过self.config[picard_path].as_str()读取。完整的可运行配置示例以下配置启用插件、自定义输出模板、并配置 Windows 下的 Picard 路径plugins: mbsubmit mbsubmit: format: $track. $title - $artist ($length) threshold: medium picard_path: C:\Program Files\MusicBrainz Picard\picard.exe若使用 Linux/macOS 且picard已在$PATH中picard_path可省略若不希望Print tracks选项在匹配较好时出现可将threshold调低如low或在 timid 模式下设置strong。测试用例验证输出格式仓库中的测试 test/plugins/test_mbsubmit.py 对插件行为做了端到端验证。测试类继承AutotagImportTestCase、TerminalImportMixin与PluginMixinplugin mbsubmit构造一个包含 2 首曲目的专辑后运行导入test_print_tracks_output交互中输入pPrint tracks再sSkip断言输出包含01. Tag Track 1 - Tag Artist (0:01)与02. Tag Track 2 - Tag Artist (0:01)验证默认格式模板的渲染结果test_print_tracks_output_as_tracks先以tas Tracks方式导入单曲、再p打印断言输出包含02. Tag Track 2 - Tag Artist (0:01)验证在 as Tracks 场景下选项与排序同样生效。这两个测试直接印证了文档中描述的交互流程与默认输出格式$track. $title - $artist ($length)也是自定义format模板时验证行为的好参考。小结mbsubmit插件的价值在于为“beets 匹配失败 → 手工提交 MusicBrainz”这一链路提供了两条低摩擦路径导入时即时打印可解析曲目列表、或一键用 Picard 打开未匹配文件beet mbsubmit QUERY命令则把该能力延伸到任意已入库专辑。使用时重点把握三点format决定输出样式、threshold决定选项何时出现并与 timid 模式、match:推荐阈值联动、picard_path决定 Picard 能否被成功启动。结合 beetsplug/mbsubmit.py 的源码与 test/plugins/test_mbsubmit.py 的测试可以快速理解其事件注入机制并根据自己的导入习惯定制行为。赞分享音频CLI【免费下载链接】beetsmusic library manager and MusicBrainz tagger项目地址https://gitcode.com/gh_mirrors/be/beets点击查看免费下载相关推荐beetsBeets媒体库管理系统指南用 MusicBrainz 自动标签的插件化音乐库管理工具beetsBeets媒体库管理系统指南用 MusicBrainz 自动标签的插件化音乐库管理工具 Beets 是一款面向“痴迷型音乐收藏者”的媒体库管理系音频CLIMusicBrainz Picard 音频标签编辑工具安装指南MusicBrainz Picard 音频标签编辑工具安装指南 前言 MusicBrainz Picard 是一款功能强大的开源音频文件标签编辑器它能够自动识桌面应用音频处理beets 使用指南用 MusicBrainz 自动标签整理你的音乐媒体库beets 使用指南用 MusicBrainz 自动标签整理你的音乐媒体库 beets 是一款面向音乐收藏管理场景的开源媒体库管理系统它以一次性把你的音乐音频CLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考