在日常生活中, 我是一个比较喜爱听音乐的人, 因为我的电脑本地存储了上千首音乐文件, 但是绝大多数歌曲都没有歌词信息。因此, 每当我想要跟唱的时候, 往往需要手动地在互联网上进行查找, 再逐一下载LRC格式的歌词文本, 这个过程通常会耗费两三个小时也难以完成。
到了后来, 我经过思考之后认为,因为市面上的现有工具不是封闭式源码就是功能体验不好, 我自己决定去开发一个播放器。这个程序不仅具备自动扫描本地歌曲的功能, 还能够进行批量下载歌词的操作, 更可以把歌词同步显示出来供用户使用。
说干就干, 我挑选了PyQt5来构建界面, 因为这个库是非常成熟的, 而且网络上面有许多教程可以利用。在音频播放方面, 我使用了.mixer, 它支持MP3、FLAC这些常见格式, 既轻量又稳定。
歌词下载的主要功能依靠的是那个网站的API, 这个网站的数据数量很大, 匹配也比较精准, 如果元数据匹配失败了, 还可以利用音频指纹进行识别。把数据存储到了数据库里面, 这样方便以后进行查询操作。
第一步任务是编写歌曲扫描引擎。该引擎被设计成递归模式, 用来扫描指定的文件夹。它会通过识别文件的后缀名, 来筛选出.mp3格式和.flac格式的文件。接着, 利用提取ID3标签的功能, 获取标题、歌手以及专辑这类信息。
当扫描操作完成以后, 数据会被存入数据库中。同时也会标记每首歌的歌词状态, 具体包括是否有歌词存在, 以及判断是纯音乐还是带有同步歌词。在实现增量更新时, 只针对新产生的文件进行扫描, 因此速度极快。扫描五百首歌曲大概只需要半分钟即可完成。
最关键的部分在于批量歌词下载这一模块, 在该模块中, 我个人设计了双重引擎来处理相关任务, 第一个步骤会先进行元数据的匹配工作, 如果在标题与歌手方面完全对应, 则直接通过接口获取数据, 如果对应的结果不准确或者压根没有任何标签信息, 那么就会转而使用音频指纹技术来进一步核查, 为确保界面运行的流畅度, 防止出现卡顿现象, 所有的下载任务都会放在后台进程内去运行, 同时系统中还特别增加了进度条的功能, 用以直观地展示成功下载、下载失败、跳过以及纯音乐各占了多少首次的数量情况, 在涉及网络请求的部分, 采用了异步机制进行处理, 并且严格控制了每秒发起请求的次数, 以此避免账号或ip被封禁的情况发生。
我们特别加入了智能过滤功能, 针对那些已经存在LRC歌词文件的歌曲将会采取跳过处理策略, 同时系统能够自动识别纯音乐类型的音频文件, 这样可以有效避免在无效资源上浪费时间和精力。
不过, 在编写代码的过程当中, 确实是遇到了许许多多的麻烦事。最先出现的问题是音频格式的兼容性问题。有一些比较老的歌曲文件采用的是WMA格式, 而这个格式是不被支持的。所以我不得不使用pydub工具来进行转码操作, 并且还需要额外安装这个工具所依赖的一些东西。
其次是关于歌词匹配的准确程度问题。因为存放在元数据里面的括号以及标点符号经常存在不一致的情况, 这就致使匹配操作失败了。后来我引入了模糊匹配的策略, 通过这个办法, 匹配的准确率从之前的不到百分之八十提升到了超过百分之九十。
用户最为感到烦恼的事情就是, 在执行大规模的下载操作过程中, 程序界面会出现完全卡死的现象。后来通过将网络的请求处理与界面的更新这两部分逻辑彻底分离开来, 并且采用信号和槽这一技术机制来传递进度的相关信息, 终于把这个难题给解决了。
关于歌词同步显示这一部分功能, 我专门编写了一个自定义模块, 该模块会以100毫秒的固定频率去检查当前音频的播放进度, 一旦确认时间点对应到特定的歌词行, 就会对该行文本进行高亮处理。
除此之外, 我还集成了一款内置的文本编辑器, 用户可以通过这款编辑器来手动修改每一行歌词所关联的时间戳, 支持直接拖拽或点击微调等方式来进行操作, 经过测试这种调整方式的误差范围能够控制在0.1秒以内。
在最终导出文件的时候系统提供了两种选择, 一是可以生成符合标准格式的LRC歌词文件, 二是能够将歌词信息直接嵌入到音频文件内部。
根据测试的结果, 对五百首歌曲进行扫描, 每首只扫描三十秒的深度, 批量下载歌词这个过程花费了大约五六分钟的时间, 匹配的准确率最终达到了96%。界面上共有三种视图, 分别是按曲目查看、按专辑查看和按艺术家查看的。
歌词的状态使用的是图标来显示的, 其中绿色的图标表示已经同步完成黑色的图标表示这是一首纯音乐而红色的图标则表示还没有匹配上。程序还能够支持把文件直接拖拽到窗口里进行播放, 并且还设有迷你模式可以随时驻守在任务栏上。整个项目大约编写了三千行代码在里面没有使用任何需要付费的库。
坦白地讲, 在过去的一段时间里, 我认为这种类型的桌面应用程序必须得使用C++或者Rust来进行编写, 并且一直觉得这样的想法是肯定行不通的。
然而, 在经过实际完成开发之后才发现, 尽管该软件的启动速度稍微慢了一点, 内存占用的情况也相对高了一些, 但是它所具有的竞争优势在于开发效率非常高, 并且后续进行修改的时候也是非常方便的。
比如说, 在后来增加歌词翻译功能这一个环节的时候, 只需要调用相关的免费翻译API就可以完成了;如果想要实现车载音乐库批量导出这个功能的话, 也仅仅是修改几行代码就可以搞定, 整个过程是非常快捷且容易操作的。
相比于这种专业工具而言, 我的播放器在精致程度上肯定是不如它们的, 然而自己用来觉得很顺手, 并且能够在任何时候添加新的功能, 不受制于他人的那种感觉确实是非常不错的。
最后我想要说的是, 万一你这个人也特别喜欢鼓捣事情, 那就干脆试一试动手去制作一个属于自己的工具好了。即使最初做出来的东西看起来十分粗糙, 没有任何美感也好过什么都不要动, 因为里面每一行代码都是你自己亲自敲进去的。
这样一来, 往后不管你想要修改哪一部分内容, 都可以随心所欲地去改, 不像使用那些买来的现成产品那样束手束脚。那种能够完全控制住所有细节的感觉, 是外面那些早就做好的软件永远都给不到你的体验。
就比如现在, 我基本上每天都在晚上这个时候听着歌曲, 当看到歌词能够跟着音乐的节奏在屏幕上面一步一步同步跳动显现出来的时候, 内心深处就会产生一种相当强烈的满足感和成功的感觉。