<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Music on ByteJog</title>
    <link>https://bytejog.com/tags/music/</link>
    <description>Recent content in Music on ByteJog</description>
    <image>
      <title>ByteJog</title>
      <url>https://bytejog.com/assets/bytejog32.png</url>
      <link>https://bytejog.com/assets/bytejog32.png</link>
    </image>
    <generator>Hugo -- 0.152.2</generator>
    <language>zh</language>
    <lastBuildDate>Sat, 08 Mar 2025 18:03:21 +0800</lastBuildDate>
    <atom:link href="https://bytejog.com/tags/music/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Tempo：为 Navidrome/Subsonic 打造的安卓原生音乐客户端新选择</title>
      <link>https://bytejog.com/posts/soft/app_tempo/</link>
      <pubDate>Sat, 08 Mar 2025 18:03:21 +0800</pubDate>
      <guid>https://bytejog.com/posts/soft/app_tempo/</guid>
      <description>&lt;p&gt;各位音乐爱好者和自托管服务器的同好们！今天我们来聊聊一个我心心念念的话题：如何在手机上&lt;em&gt;完美&lt;/em&gt;地享受我们精心整理的个人音乐库。如果你和我一样，可能已经花了不少时间搭建自己的音乐服务器（比如用了超棒的 Navidrome），那么接下来的挑战就是：找到一个真正配得上它的安卓客户端。&lt;/p&gt;
&lt;p&gt;坦白说，我之前在不同的 Subsonic 客户端之间反复横跳。用过 Ultrasonic，它确实能完成任务，但我个人在使用中遇到了一些小毛病和不顺畅的地方，这让我一直想寻找一个更顺滑、更……&lt;em&gt;原生&lt;/em&gt;的体验。&lt;/p&gt;
&lt;p&gt;然后，我发现了 &lt;strong&gt;&lt;a href=&#34;https://github.com/CappielloAntonio/tempo&#34;&gt;Tempo&lt;/a&gt;&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;tempo-是什么&#34;&gt;Tempo 是什么？&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&#34;Tempo&#34; loading=&#34;lazy&#34; src=&#34;https://bytejog.com/assets/post/tempo/horizontal_logo.svg&#34;&gt;&lt;/p&gt;
&lt;p&gt;Tempo 可以直接连接到你的 Subsonic 兼容服务器（是的，完美支持 Navidrome！），并提供一个设计精美、流线型的界面来浏览和播放你的音乐。让我印象最深的是它的理念：&lt;strong&gt;Tempo 不会试图用什么花哨的算法来决定你应该听什么&lt;/strong&gt;。相反，它的界面是围绕着你的听歌历史和一定的随机性来构建的，这种感觉非常清爽自然。
&lt;img alt=&#34;Tempo Feat.&#34; loading=&#34;lazy&#34; src=&#34;https://bytejog.com/assets/post/tempo/f_1_screenshot.png&#34; title=&#34;{width=&amp;#39;400px&amp;#39;}&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;为什么-tempo-成为了我的-navidrome-首选客户端&#34;&gt;为什么 Tempo 成为了我的 Navidrome 首选客户端&lt;/h3&gt;
&lt;p&gt;以下是为什么 Tempo &lt;em&gt;对我来说&lt;/em&gt;如此契合，并解决了我之前在其他应用中遇到的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;与 Navidrome 无缝集成:&lt;/strong&gt; 这是我的硬性要求。Tempo 连接我的 Navidrome 实例毫无障碍。浏览艺术家、专辑、流派、播放列表（甚至年代！）都快速且直观。一切都如你所期望的那样&lt;em&gt;正常工作&lt;/em&gt;。没有奇怪的同步问题，没有意外崩溃——只有对我的音乐库流畅的访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;需要 Scrobble（同步播放记录到 Last.fm）？没问题！&lt;/strong&gt; 作为一个会虔诚地在 Last.fm 上记录听歌历史的人，可靠的 Scrobble 功能是必不可少的。Tempo 可以直接与 Last.fm 集成（前提是你的服务器支持发送必要的“正在播放”信息，Navidrome 是支持的）。它能准确地捕捉我的播放记录，让我的 Last.fm 档案保持最新，无需任何额外操作。这一点是我之前在其他客户端上偶尔会觉得不稳定的地方。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;真正原生且流畅的体验:&lt;/strong&gt; 这就是 Tempo 相比我过去（比如播放列表错乱的 Ultrasonic）的体验，真正脱颖而出的地方！UI 干净、现代，在安卓上感觉&lt;em&gt;非常对味&lt;/em&gt;。导航如丝般顺滑，播放稳定，像无缝播放这样的功能也是开箱即用。它不像是把一个网页应用塞进手机壳里，而是感觉就像一个为音乐爱好者设计的、正儿八经的安卓应用。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;你会爱上的丰富功能&#34;&gt;你会爱上的丰富功能&lt;/h3&gt;
&lt;p&gt;除了解决我的特定需求外，Tempo 还带来了更多实用的功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;简洁直观的 UI:&lt;/strong&gt; 围绕&lt;em&gt;你的&lt;/em&gt;习惯定制，而非某种通用推荐。而且还有漂亮的浅色和深色主题！&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;强大的浏览与搜索:&lt;/strong&gt; 按你喜欢的方式深入探索你的音乐库。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流媒体与离线模式:&lt;/strong&gt; 轻松在线播放。离线模式目前正在积极开发中，令人期待！（注意：当前在使用多个服务器时可能有限制）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;播放列表管理:&lt;/strong&gt; 随时随地创建、编辑和管理你的播放列表。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无缝播放:&lt;/strong&gt; 对于那些概念专辑或现场录音来说至关重要。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chromecast 支持:&lt;/strong&gt; 将你的音乐投射到 Chromecast 设备（目前功能还比较基础，但已经有了！）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;播客与电台:&lt;/strong&gt; 如果你的服务器支持，Tempo 也能直接收听播客和电台节目。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;转码支持:&lt;/strong&gt; 需要节省流量？你可以在 App 内直接配置转码设置（需要服务器支持）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Android Auto 支持:&lt;/strong&gt; 这点超赞！完整的 Android Auto 集成意味着你可以在开车时通过车载屏幕轻松控制和收听音乐。&lt;strong&gt;重要提示：&lt;/strong&gt; 开发者建议使用 &lt;strong&gt;GitHub 版本&lt;/strong&gt; 以获得最佳的 Android Auto 和 Chromecast 支持。
&lt;img alt=&#34;Tempo 浅色主题截图&#34; loading=&#34;lazy&#34; src=&#34;https://bytejog.com/assets/post/tempo/l_1_screenshot.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&#34;Tempo 深色主题截图&#34; loading=&#34;lazy&#34; src=&#34;https://bytejog.com/assets/post/tempo/d_1_screenshot.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>音乐文件下载和元数据刮削思路</title>
      <link>https://bytejog.com/posts/music/music_meta/</link>
      <pubDate>Sun, 27 Oct 2024 17:00:13 +0800</pubDate>
      <guid>https://bytejog.com/posts/music/music_meta/</guid>
      <description>&lt;h3 id=&#34;前言&#34;&gt;前言&lt;/h3&gt;
&lt;p&gt;个人音乐服务&lt;a href=&#34;https://bytejog.com/posts/linux/navidrome/&#34;&gt;Navidrome搭建&lt;/a&gt;之后，必然会碰到高质量的音乐文件来源和歌曲元数据的问题，这里说一下个人解决办法。我是以腾讯音乐为基础，从腾讯下载mp3音乐文件，然后将腾讯音乐的元数据写入到mp3里，偶尔碰到在腾讯里没有版权的音乐，会在网易音乐里搜索有没有，使用网易音乐的音乐元数据，实在没有就没有办法了。&lt;br&gt;
过程中会使用的一些开源服务，两个已经都不更新，一直用得挺好就没有找其他替代了。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jsososo/QQMusicApi&#34;&gt;QQMusicApi&lt;/a&gt;: 腾讯音乐API服务，需要部署在自有的服务器或者本机都可以，需要的时候启动，使用之前需要设置账号信息和更新登陆的Cookie。 &lt;strong&gt;需要会员，不提供无会员下载320的音乐&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/Binaryify/neteasecloudmusicapi&#34;&gt;NeteaseCloudMusicApi&lt;/a&gt;: 网易音乐API服务，可以实现在Vercel部署使用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;请支持正版音乐！！！有需要更新音乐的时候，会购买一个的腾讯音乐会员，登陆后提取Cookie发送到QQMusicApi服务，后面使用到QQMusicApi的服务都是在登陆之后的操作。网易音乐我只是使用元数据，暂时没有购买过会员。&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;腾讯音乐会员可以官方购买，或者某些APP里兑换会员服务，或者是闲鱼、淘宝都可以的，哪个便宜搞哪个&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;整体使用Python代码实现的下面过程，因为不具备通用性，这里只说一下怎么使用的思路。
&lt;img alt=&#34;音乐刮削&#34; loading=&#34;lazy&#34; src=&#34;https://bytejog.com/assets/post/music.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;音乐来源&#34;&gt;音乐来源&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;专辑:&lt;br&gt;
如你在腾讯音乐找到周杰伦的《J III MP3 Player》，看到浏览器的URL：https://y.qq.com/n/ryqq/albumDetail/002MAeob3zLXwZ，最后的&lt;code&gt;002MAeob3zLXwZ&lt;/code&gt;就是专辑的&lt;code&gt;albummid&lt;/code&gt;，接下来调用QQMusicApi的&lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=_2%e3%80%81%e8%8e%b7%e5%8f%96%e4%b8%93%e8%be%91%e5%86%85%e7%9a%84%e6%ad%8c%e6%9b%b2&#34;&gt;获取专辑内的歌曲&lt;/a&gt;接口，可以获取到专辑歌曲清单的json数据。&lt;/li&gt;
&lt;li&gt;歌单：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;腾讯音乐提供了榜单和歌单，都可以QQMusicApi的&lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=_2%e3%80%81%e8%8e%b7%e5%8f%96%e6%a6%9c%e5%8d%95%e8%af%a6%e6%83%85&#34;&gt;获取榜单详情&lt;/a&gt;和&lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=_1%e3%80%81%e8%8e%b7%e5%8f%96%e6%ad%8c%e5%8d%95%e8%af%a6%e6%83%85&#34;&gt;获取歌单详情&lt;/a&gt;，根据个人喜好可以找对应的日常更新。&lt;/li&gt;
&lt;li&gt;网易音乐也有提供排行榜和歌单，可以调用NeteaseCloudMusicApi的&lt;a href=&#34;https://gitlab.com/Binaryify/neteasecloudmusicapi/-/blob/main/public/docs/home.md?ref_type=heads#%E8%8E%B7%E5%8F%96%E6%AD%8C%E5%8D%95%E6%89%80%E6%9C%89%E6%AD%8C%E6%9B%B2&#34;&gt;获取歌单所有歌曲&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;Apple Music有每周热门100首和城市排行榜的歌单，找到对应歌单返回歌曲链接，分析请求参数和header信息，后续需要更新音乐的时候，重新访问地址获取Cookie里的&lt;code&gt;authorization&lt;/code&gt;，更新到请求代码，处理返回的json数据就可以获取歌单信息了。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://charts.spotify.com/&#34;&gt;Spotify榜单&lt;/a&gt;，找自己想更新的对应榜单，同样也是看返回歌曲的链接，分析请求参数和header信息，处理返回的json数据就可以获取歌单信息，当然每次更新歌曲时候也需要更新&lt;code&gt;authorization&lt;/code&gt;参数。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;歌手：&lt;br&gt;
在腾讯音乐里找歌手的&lt;code&gt;singermid&lt;/code&gt;，调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=_2%e3%80%81%e8%8e%b7%e5%8f%96%e7%83%ad%e9%97%a8%e6%ad%8c%e6%9b%b2&#34;&gt;获取热门歌曲&lt;/a&gt;，修改参数&lt;code&gt;page&lt;/code&gt;能够获取歌手的歌曲清单。&lt;/li&gt;
&lt;li&gt;单曲：&lt;br&gt;
在腾讯音乐找对应单曲的&lt;code&gt;songmid&lt;/code&gt;，调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=%e5%8d%95%e4%b8%aa%e8%8e%b7%e5%8f%96&#34;&gt;单个获取&lt;/a&gt;，可以获取包含了很多的歌曲信息，包括歌手、专辑、语种、曲风等，但是不包含歌词。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;匹配歌曲&#34;&gt;匹配歌曲&lt;/h3&gt;
&lt;p&gt;腾讯音乐直接有对应的songmid字段，可以跳过这个步骤。&lt;br&gt;
对于网易、Apple Music、Spotify里获取歌曲清单，基本都会包含歌曲id(songmid)、歌名(songname)、歌手信息等，然后遍历歌单数据拼接查询关键词：歌手名称 - 歌名，如周杰伦 - 晴天，然后调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=%e6%90%9c%e7%b4%a2-1&#34;&gt;搜索&lt;/a&gt;接口获取返回搜索的数据，具体接口参数详细见链接。对返回的结果第一条数据进行，看歌名和歌手名称是否一致，如果一致就搜索成功，然后找到返回结果的&lt;code&gt;mid&lt;/code&gt;就是腾讯音乐的songmid，基本上成功率能达到90%以上，如果没有找到需要手动在浏览器里调用接口自己找一下返回的数据看看（推荐使用firefox，查看json数据方便）。&lt;br&gt;
举例：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;网易音乐: 周杰伦 - 晴天，songmid=186016
腾讯音乐：周杰伦 - 晴天，songmid=0039MnYb0qxYhV
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;根据找到的ID，可以放到一个ID对照文件里，每次搜索之前加载对应的对照表，先通过ID查找一下，是否存在，如果不存在则调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=%e6%90%9c%e7%b4%a2-1&#34;&gt;搜索&lt;/a&gt;接口，找到了对应的腾讯音乐的songmid，再把ID对应关系写会对照文件，可以加快歌单的更新速度，因为大量是已经下载好的歌曲。&lt;br&gt;
对照表文件示意：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;186016 0039MnYb0qxYhV
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2133271060 2133271060 nt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对照的文件，我做一个特殊处理，如果在腾讯音乐没有找到的音乐，可以在网易音乐里搜索，采用网易音乐的元数据文件。&lt;/p&gt;
&lt;p&gt;如果确实没有找到元数据，我可能就不会放到Navidrome里了。&lt;/p&gt;
&lt;h3 id=&#34;歌曲信息&#34;&gt;歌曲信息&lt;/h3&gt;
&lt;p&gt;腾讯音乐的歌曲信息调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=%e5%8d%95%e4%b8%aa%e8%8e%b7%e5%8f%96&#34;&gt;单个获取&lt;/a&gt;&lt;br&gt;
网易音乐的歌曲信息调用NeteaseCloudMusicApi的&lt;a href=&#34;https://gitlab.com/Binaryify/neteasecloudmusicapi/-/blob/main/public/docs/home.md?ref_type=heads#%E8%8E%B7%E5%8F%96%E6%AD%8C%E6%9B%B2%E8%AF%A6%E6%83%85&#34;&gt;获取歌曲详情&lt;/a&gt;&lt;br&gt;
同样这里把获取到的歌曲详情json文件保存到文件系统，按照一定的目录结构组织起来，加快歌曲信息获取速度，先找缓存，再调用接口。&lt;/p&gt;
&lt;h3 id=&#34;下载歌曲&#34;&gt;下载歌曲&lt;/h3&gt;
&lt;p&gt;只试过腾讯会员的下载音乐，网易音乐需要大家尝试。
下载之前，检查本地是否已经下载好了音乐文件，存在就可以跳过。&lt;br&gt;
调用调用QQMusicApi的  &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=%e4%b8%8b%e8%bd%bd%e9%93%be%e6%8e%a5&#34;&gt;下载链接&lt;/a&gt;接口获取音乐文件地址，可以传入音质的参数，获取不同音质的音乐文件。  请求音乐文件地址，保存到本地。由于有时会出错，可以在代码里加入重试下载的次数。&lt;/p&gt;
&lt;h3 id=&#34;歌曲专辑&#34;&gt;歌曲专辑&lt;/h3&gt;
&lt;p&gt;如果需要更新音乐文件元数据，一般包括：歌曲信息、专辑信息、封面、歌词。&lt;br&gt;
腾讯音乐的歌曲专辑调用QQMusicApi的 &lt;a href=&#34;https://jsososo.github.io/QQMusicApi/#/?id=_1%e3%80%81%e8%8e%b7%e5%8f%96%e4%b8%93%e8%be%91%e4%bf%a1%e6%81%af&#34;&gt;获取专辑信息&lt;/a&gt; &lt;br&gt;
网易音乐的歌曲专辑调用NeteaseCloudMusicApi的&lt;a href=&#34;https://gitlab.com/Binaryify/neteasecloudmusicapi/-/blob/main/public/docs/home.md?ref_type=heads#%E8%8E%B7%E5%8F%96%E4%B8%93%E8%BE%91%E5%86%85%E5%AE%B9&#34;&gt;获取专辑内容&lt;/a&gt;&lt;br&gt;
同样这里把获取到的歌曲专辑json文件保存到文件系统，按照一定的目录结构组织起来，加快歌曲专辑获取速度，先找缓存，再调用接口。&lt;/p&gt;
&lt;h3 id=&#34;歌曲封面&#34;&gt;歌曲封面&lt;/h3&gt;
&lt;p&gt;歌曲的封面，如果属于专辑的歌曲，获取专辑的封面，如果属于单曲，获取歌手的封面。
腾讯音乐：&lt;code&gt;https://y.gtimg.cn/music/photo_new/T002R300x300M000${mid}.jpg?max_age=2592000&lt;/code&gt;  mid参数替换为专辑的id或者歌手的id&lt;br&gt;
网易音乐，如果歌曲信息里&lt;code&gt;al.picUrl&lt;/code&gt;存在，直接使用里面的封面地址，否则需要调用NeteaseCloudMusicApi的&lt;a href=&#34;https://gitlab.com/Binaryify/neteasecloudmusicapi/-/blob/main/public/docs/home.md?ref_type=heads#%E8%8E%B7%E5%8F%96%E6%AD%8C%E6%89%8B%E8%AF%A6%E6%83%85&#34;&gt;获取歌手详情&lt;/a&gt;，使用&lt;code&gt;data.artist.cover&lt;/code&gt;里的歌手封面地址。&lt;br&gt;
下载的封面
对于获取的封面建议也做缓存，以专辑ID、歌手ID为文件名，按照一定的目录结构组织起来，加快歌曲封面获取速度，先找缓存，再调用接口。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
