macOS と Android での音楽ライブラリーのカスタムソート順

音楽ライブラリにおいてのカスタムソート順は、かなりまれなニーズだとされている。 ほとんどの主要言語は表音文字を使って、その自然な並べ替えが Unicode での順序とほぼ同じである(場合によっては正規化は必要)。一方、表意文字(主に漢字)を使う言語では、Unicode での並び方が自然な並び方(通常は読み順)と異なる。これにより、Unicode コードポイント順で並べ替えられたリストがおかしいな順番たと見られ、調べづらくなる。したがって、音楽ライブラリ中のタイトル、アーティスト、アルバム名などのカスタムソート順は、これら一つ、または複数の言語で構成している場合に役に立つ。

今までの現状

現在、各プラットフォームを使用する中国語と日本語の話者に向けて、この問題を解決する現存の方法も異なる。

【会員登録制のストリーミング・プラットフォーム】 これらのプラットフォームは、音楽ライブラリ内の名前ごとにソートキーを添付し、(おそらく独自の)方法を使ってソートキーを音楽ファイルに関連付け、Webまたはネイティブプラットフォームに適用する。「ソートキー」とは、タイトル、アーティスト、またはアルバムの代替名であり、元の名前の代わりに並べ替えに使用される。元の名前の表示には影響しない。

【中国製の音楽プレーヤーでローカル音楽ファイル】 一般的に、中国製の音楽プレーヤーにはピンイン変換ツールを内蔵し、音楽をインポートする度に名前をピンインに変換して、ソートする際に基準とする。この方法の欠点は、日本語のタイトルを変な所にされがちである。 これら一部のプレーヤーは、簡体字でもラテン文字でもない文字を無視してソートすることがある。日本語のタイトルを探したいときは、まずどの文字が簡体字にも入ることを考える必要がある。

【ローカライズ問題をよく扱う普通な音楽プレーヤーでローカル音楽ファイル】 (適切な言語に設定された最新の Android はこれに含まれる。) これらのプレーヤーは、ローカライズされた照合 (Collation) を使用してこの問題を解決しようとする。 通常、データベースには、International Components for Unicode (ICU) ライブラリのローカライズされた照合テーブルが含まれています。照合はほとんどの人には仮の解決策になれるが、複数の言語が音楽ライブラリーのなかで混ざっている場合はあまりにはよく機能しない。

中国語では、ほとんどの漢字の読み方は一つだけである。ICU のピンイン照合は、GB16386 中国語文字エンコーディングの順番に似ていて、各漢字の最もよく使われるピンインを元にアルファベット順にソートすることである。ほとんどの場合ではこれで十分です。

その一方、日本語では、ほぼすべての漢字には複数の読み方があり、複数の漢字を組み合わせてさらに新しい読み方が産んでしまう。日本語文字列の読み方を確定するのは簡単な作業ではなく、一般的には自然言語処理(NLP)技術を運用している。 ICU は、JIS X 4061 規格(日本語文字列照合順番)に準拠して、全ての漢字に最も一般的な音読みを基準として指定してソートする。(例えば、「初音ミク」の「初」は「しょ」と扱って、「し」の位置に配置すること。)Unicode の符号位置順よりは優れていますが、これもまた直観に反する順番である。

【その他の音楽プレーヤーでローカル音楽ファイル】 英語しか配慮してない他の音楽プレーヤーは、コンピューターにとって最も自然なソート順——Unicode 符号位置順——を利用してプレイリストをソートする傾向がある。 頻出漢字は Unicode のなかで、部首と画数を元に康熙字典こうきじてん順で並んでいた。この順序は日中韓越いずれの言語にも偏ってないが、どちらの言語の話者にとっても直感に反する順番である。

ソートキーの生成

これに関する今までの記事で提案されている通り、手動でタグ付けすることは最も簡単な方法である。大規模な音楽ライブラリにタグ付けするときに大量の作業になるのだが。 iTunes では、「プロパティー」メニューに読みがなを簡単に追加する機能を提供している。

音楽ライブラリが大きすぎて自分でタグ付けできない場合でも、半自動的にタグを付ける方法がある。 日本語も中国語も、同じ文字を文脈によって異なる読みかたになる場合が多くあり、コンピューターが生成した読みがなは、正しい文脈を検出できない場合、またはその文脈をまったく認識できない場合では、間違い読みがなをつけることがある。 したがって、正しいタグをつけようなら、人力で検査するのが必要である。

Pythonista として、Python でタグ付けと検査をするスクリプトを作った。中国語ピンインの生成は Python ライブラリの PyPinyin を使い、日本語の読みがなは実行時にはインタネットへの接続が必要な Yahoo の形態素解析 API を利用した。ローカルで読みがなを生成したいなら、MeCabmecab-mepad-ipadic-NEologd 辞書を合わせれば、Yahoo の API にも負けない良い結果が出せる。

プラスαとして、タグ付けをリモートで検査できるようにするための簡単な Web アプリを Flask + Vue + MongoDB で作成した。 ソースコードは GitHub に公開した。

音楽ファイルにタグをつける

マイナーなニーズだと見なされたが、主要な音楽タグ形式には、ありがたいことにカスタムソートキーのプロパティフィールドがある。 JAudiotagger のサイトには、ソートキーに対応したタグ形式で使用されるタグ名の網羅的一覧がある。

前述の Python スクリプトでは、ID3v2 タグ (MP3 ファイル)や Vorbis Comment (FLAC ファイル)など数多くのフォーマットをよく対応している Mutagen を利用した。 Java や Kotlin を使いたい場合は、 JAudiotagger も良いパッケージだと思う。後述の Android アプリにも JAudiotagger を使った。

macOS(と iOS)で付けたタグを利用する

強調すべきものはあまりない。 macOS の iTunes には、ソートキータグの対応が内蔵していたため、タグを編集や利用することが難なくできる。注意すべきことは、iTunes 以外でタグを編集した場合は、音楽ライブラリを再インポートして更新することが必要。

iOS も、iTunes プレーヤーがあるため、ソートタグも同じく認識できるだと思う。

* macOS の最新バージョンでは、「iTunes」が「Music」に名前が変更された。 使ったことはないが、タグを認識するには大きな影響はないと思う。

Android で付けたタグを利用する

Apple エコシステムのアプリとは違って、Android OS はカスタムソートキーのタグを全く認識しない。 Android の大抵の音楽プレーヤーは、OS が提供した Media Storage API を依頼する。 Media Storage コンポでは、音楽ファイルを含む、OS が検出したすべてのメディアファイルを記録するデータベースが管理している。title_keyartist_keyalbum_key などの列は確かにあるだが、タイトルの最初から “a”、“an”、“the” などのストップワードを外し、照合文字列に変換することしかしてない。システム言語と揃うローカライズされた照合を使用しますが、前で述べたように十分な解決策ではない。

以前、AOSP にソートタグを対応するようパッチを投稿してみたかったが、メディアメタデータ抽出するのコード(libstagefright)が C で書かれていて、僕にとって難しすぎてパッチすることを諦めた。その後、Xposed Framework を通して、Media Storage データベースの更新の Java 部分を Hook することも試してみたが、あいにく照合キーの生成とデータベースに書き込みは、同じメソッドに入った。その間に Hook するには、メソッド全体を書き直しなきゃいけないので、いい解決法だと思わない。

難儀の末、Android の Media Storage の並び替えは *_key の列に依頼することから手に入れ、Root 権限で音楽ファイルのソートキーを直接データベースに書き込むことにした。

そして、データベースを更新するアプリを作り始めた。 仕組みは難しくではない:

  1. Media Storage データベースの読み書きと音楽ファイルからのソートタグの読み取りをするため、Root 権限とストレージ権限を取得する。
  2. データベースファイルをアプリのデータフォルダーにコピーする。
  3. データベースから音楽ファイルのリストをロードする。
  4. JAudiotagger で音楽ファイルからソートキータグを抽出する。
  5. 適切な照合キーをデータベースに書きこむ。
  6. 更新されたデータベースを OS に書き戻す。

データベースを更新した後、音楽プレーヤーを強制的に再起動してから処理結果がでる。

この方法の欠点は、音楽ファイルが変更されるたびに手動的データベースを更新する必要があることである。

このアプリとソースコードは、全て GitHub に公開した。


Comments

“macOS と Android での音楽ライブラリーのカスタムソート順” への1件のコメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です