python - 来自 Python 的 Sonos 的 Unicode 播放列表
问题描述
我正在努力将一小部分音乐从我的 iTunes 库导出到外部驱动器,以用于 Sonos 扬声器(通过 Sonos 上的媒体库)。一切都很顺利,直到我在曲目、专辑和艺术家姓名中发现了一些 unicode 文本。
我正在从 Mac 上的 iTunes 转移到 Linux (Ubuntu) 上的文件夹结构,并且文件路径都包含原始的 Unicode 名称,并且这些都在艺术家/专辑视图中的 Sonos 中显示和播放。唯一的问题是播放列表,我是通过一些 Python3 代码生成的。
Sonos 似乎不支持 .m3u / .m3u8 播放列表中的 UTF-8 编码。Sonos 将字符 ÷ 解释为 ÷,经过一番谷歌搜索后,我发现显然混淆了 UTF-8 和 UTF-16(UTF-8 中的 ÷ 0xC3 0xB7,而 UTF-16 中的 à 是 U+00C3 和· 在 UTF-16 中是 U+00B7)。我尝试了许多不同的编码方式,但无法让它识别名称中包含非标准(非 ASCII?)字符的曲目。
然后我尝试了 .wpl 播放列表,并认为我已经解决了。路径中带有 ÷ 和 • 等字符的曲目现在可以完美运行,只需在播放列表文件本身中使用 unicode / UTF-8 形式的这些字符。
然而,就在我开始整理和完成代码时,我发现了一些其他字符没有得到正确处理:ö、å、á 和其他几个字符。我已经尝试将它们用作它们的原始 unicode 字符,也用作它们的编码 XML 标识符,例如,́
使用这种格式不会影响什么工作或不工作 - ÷ ( ÷
) 和 • ( •
) 很好,而 ö ( ö
)、å ( å
) 和 á ( á
) 不是。
我以前从未真正使用过 unicode / UTF-8,但在阅读了各种指南和操作方法后,我觉得我已经接近了,但可能只是缺少一些简单的东西。一些 unicode 字符现在可以工作,而另一些则不能,这一事实让我认为这一定很明显!我猜不同之处在于重音会修改前一个字符,而不是本身就是一个字符,但尝试删除前一个字母并没有奏效!
在 Python 本身中,我并没有做任何特别聪明的事情。我使用以下方法从 iTunes 的 XML 文件中读取数据:
with open(settings['itunes_path'], 'rb') as itunes_handle:
itunes_library = plistlib.load(itunes_handle)
对于导出,我尝试了几十种不同的选项,但通常如下所示(有时使用 encoding='utf-8' 和各种其他选项):
with open(dest_path, 'w') as playlist_file:
playlist_file.write(generated_playlist)
generated_playlist
从 iTunes_library 中提取和过滤数据的结果在哪里,urllib.parse.unquote()
在任何 iTunes XML 数据上运行。
任何关于在哪里看的想法或提示将不胜感激!我希望对于更了解 Unicode 的人来说,答案真的很明显!谢谢!
当前版本的代码在这里可用:https ://github.com/dwalker-uk/iTunesToSonos
解决方案
感谢@lenz 的上述建议,我现在确实拥有与Sonos 完全兼容的unicode 播放列表。
几个关键点应该可以为别人节省很多时间:
- 只有 .wpl 播放列表似乎有效。Unicode 不适用于 Sonos 上的 .m3u 或 .m3u8 播放列表。
- Sonos 需要将任何 unicode 文本规范化为 NFC 形式 - 我以前从未听说过,但本质上意味着任何重音字符都必须由单个字符表示,而不是作为具有单独重音的普通字符。
- .pls 播放列表是一种 XML 格式,需要有以 XML 格式编码的 unicode 字符,即
é
在 .pls 文件中表示为é
. - .pls 文件还需要转义形式的 XML 保留字符 (& < > ' "),
&
即&
.
在 Python 3 中,将 iTunes XML 格式的路径转换为适合 Sonos 上的 .pls 播放列表的路径,需要以下关键步骤:
left = len(itunes_library['Music Folder'])
path_relative = 'Media/' + itunes_library['Tracks'][track_id]['Location'][left:]
path_unquoted = urllib.parse.unquote(path_relative)
path_norm = unicodedata.normalize('NFC', path_unquoted)
path = path_norm.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"')
playlist_wpl += '<media src="%s"/>\n' % path
with open(pl_path, 'wb') as pl_file:
pl_file.write(playlist_wpl.encode('ascii', 'xmlcharrefreplace'))
此处提供了一个完整的工作演示,用于从 iTunes 导出以在 Sonos(或其他任何东西)中使用 .pls:https ://github.com/dwalker-uk/iTunesToSonos
希望对某人有所帮助!
推荐阅读
- react-native - 我需要将数据传递给场景并将我输入的内容显示到下一个屏幕
- angular - 查看销毁错误:尝试使用已销毁的视图:检测更改
- laravel - 具有多个中间件检查的路由组
- sql - 获取查询列的最大值
- python - py --version:如果在命令提示符下不是管理员,则拒绝访问
- java - Mono/Flux:如何暂停线程并等待事件或超时
- git - 我怎样才能让 GIT 中的两个不相关的分支有一个共同的根?
- mongodb - 使用 MongoDB 排除条件后的项目
- python - 使用 pandas 合并具有不同结构的两个数据框
- node.js - 如何使用 node-nlp 从句子中提取变量