macOSでミュージックライブラリの曲情報をJS(JXA)でいじる
はじめに
macOSではアプリケーションをスクリプトから制御する仕組みとしてAppleScriptがありますが、JavaScriptでも記述できてJXAと呼ぶようです。
で、長年Windows PCのiTunesで管理していたライブラリを、macOSのミュージックに移行したところ、評価(5段階の星印)や曲のチェックボックスやボリューム調整などの曲情報が移行されませんでした。
ということでJavaScript(JXA)を使って曲情報を移行した話です。
スクリプトからミュージックアプリを制御
macOSの「ミュージック」アプリはApplication('Music')
経由で色々できるらしい。実行にはosascript
コマンドを使います。
まずは試しにミュージックライブラリに登録済みの曲名とアルバム名を全部表示してみるのが、このスクリプト。(曲数が多いと表示にすごく時間がかかるので注意)
#!/usr/bin/env osascript -l JavaScript
var app = Application('Music');
var tracks = app.playlists[1].tracks;
for (var i = 0; i < tracks.length; i++) {
console.log(tracks[i].name(), tracks[i].album());
}
先頭に#!
のshebangが書けて、こうするとコマンドラインから直接実行できます。
app.playlists[1]
は標準で全曲を含むプレイリストになっているっぽい。これに.tracks
で全曲情報が取得できます。各曲の.name()
と.album()
が曲名、アルバム名取得です。
どんなプロパティがあるのかは、アプリケーションの「スクリプトエディタ」から見ることができます。
「スクリプトエディタ」を立ち上げて「ファイル」メニューから「用語説明を開く」を選んで、表示されたウィンドウの一覧から「ミュージック」を選択するとドキュメントのウィンドウが開きます。
ここで「Music Suite」-「track」とかを選ぶと、下側にプロパティ一覧が確認できます。
(用語説明ってメニュー名はわかりにくいですね…)
↓こんな画面が出ます。
今回、自分が参照したい情報とプロパティは以下でした。
情報 | プロパティ |
---|---|
曲名 | name |
アルバム名 | album |
評価 | rating |
チェックボックス | enabled |
再生回数 | playedCount |
前回の再生日時 | playedDate |
音量調整 | volumeAdjustment |
各プロパティは普通に track[i].rating = 100;
みたいに変更できます。
あと、評価(rating)はミュージックアプリ上では星印の0〜5個の表示ですが、上記のドキュメントには以下のようにあります。
rating (integer) : the rating of this track (0 to 100)
0〜100の整数で、星印0〜5個がそれぞれ0, 20, 40, 60, 80, 100の数値に対応しているようです。(それ以外の数値を設定したらどうなるかは試してません)
WindowsのiTunesから情報を取ってくる
iTunesのライブラリディレクトリにはiTunes Music Library.xml
というファイルがあって全曲情報が含まれています。
このXMLファイルから情報を取って、スクリプトで設定してやれば情報の移行ができそうです。
Javascript(JXA)でXMLを読むのには $.NSXMLDocument
あたりを使えば良いらしいとのことで、色々調べて
let app = Application.currentApplication();
app.includeStandardAdditions = true;
let xmldata = $.NSString.stringWithContentsOfFileEncodingError(
$(filename).stringByStandardizingPath,
$.NSUTF8StringEncoding,
$()
).js
let xmlDoc = $.NSXMLDocument.alloc.initWithXMLStringOptionsError(xmldata, 0, null);
let xmlRoot = xmlDoc.rootElement;
let xmlBody = ObjC.unwrap(xmlRoot.children)[0];
let xmlList = ObjC.unwrap(xmlBody.children);
みたいな感じでXMLを解釈して情報を取得していきました。(ここでは詳細割愛)
曲情報の移行!
こんな感じでできたのが↓
(1回しか使わないスクリプトなので、かなりやっつけ仕事なコード…)
一応これで曲情報の移行はできたんですが、うまくいかなかったのが再生回数と前回の再生日時。
自分はミュージックの設定で「ライブラリを同期」をONにしているのと、Apple Musicのサブスク契約しているのですが、この状態だと再生回数と前回の再生日時はクラウド側の値が優先されてしまうようです。
スクリプトからこれらの情報を変更すると、直後は期待通りに変更されたように見えるのですが、しばらくするとクラウドと同期されて、変更前の情報に戻ってしまいます。
この現象は、自分が確認した限りでは再生回数と前回の再生日時のみで起きました。勝手な想像ですが、再生回数などはサブスクの収益に関わる部分なのでクラウド側で管理してるのかな、と思います。
まとめ
過去ウン年の再生回数情報が移行できなかったのは残念ですが、その他の情報が移行できたので、それは良かったです。
特にスマートプレイリストで評価は多用していたので助かりました。
JavaScript(JXA)でのアプリケーション制御は便利だったので、また何かあったら使える気がしました。
Discussion