Archive for the ‘音楽配信’ Category

Spotifyの純正アプリがメモリーリークする件だが、どうしても直らず、自動で再起動する処理を追加したものの、ほぼ毎日再起動する感じで、いつ再起動したらいいか気を遣わされるという腐れ具合がどうにも嫌になくなってしまった。

それで、ダメ元でLinux用Spotifyアプリを検索してみたら、Nuvola(正確には、Nuvola Apps Runtime + Spotify script。以下、Nuvola Spotify)というプレーヤが出て来た。以前も試したことがあるのだが、GPMのプレーヤ同様、webページをアプリにしているだけなので、意味がないから止めた。ただ、今となっては、そういうしょうもないものでも、メモリーリークさえしなければ使う価値はあると思った。実際、検索する前は、(一見それなりに使えそうな)web版Spotifyを自作のミニプレーヤ(minisp)に繋げられないかと考えていたほどなので、もし、Nuvola SpotifyにDbusの機能があれば、純正アプリと同様に繋げられる可能性が高いので、再度試すことにした。

結論としては、機能は期待以上のものだった。Dbus(MPRIS2)に対応しているし、純正アプリが実装していなかった音量取得・設定機能すらある。あと、ウインドウを閉じても終わらないようにできるのがうれしい。更に、少し動かしてみてもメモリーリークする気配はなかった。

それで今日、Nuvola Spotifyをミニプレーヤとリモコンにくっつけてみた。が、いつものように予想外のことがいろいろあって、結構な作業になり、丸一日掛かった。それでも何とか動くようになった。

そして、いくつか問題点や気に入らないことがある。多くは元々のweb版Spotifyの欠点であるのだが・・・

  • Web版Spotifyの問題
    • ジャケットが表示されていると、ウインドウの背景の色が勝手にジャケットの系統の色に設定されて、趣味が悪いだけでなく、ものすごく見難い。しかも、変更できない。
    • プレイリストの曲操作が使いにくい(例: 複数曲の選択ができない)。 → とても不便。
    • 曲のジャンプができないことが多い(曲名をクリックしてジャンプできず、前か次にしか行けないことが多い)。 → とても不便。
    • クレジット(演奏者など)の表示機能がない・・・ → とても不便。ミニプレーヤに追加しようか?
    • プレイリスト(Daily mix)の再生が進んでも、表示が更新されない(現在再生中の曲が見えなくなる)。 → キューを表示すれば、再生中の曲が見える。
    • 純正アプリと同様、頑固に、検索などに日本語が入らない。NuvolaやNuvolaが使っているブラウザの問題なのかも知れない。
  • Nuvola Spotifyの問題
    • 表示をズームできるのはいいのだが、倍率を変えた時の品質が汚くて実用にならない。 → 結局、等倍で使っている。
    • Dbusで来るイベントの内容・タイミングが純正アプリと違う。 → なんとか対応した。
    • 動作が遅い・重い? → 要改善
      • 曲の切り替わり通知タイミングが純正アプリより遅い。そのため、音量正規化の音量設定タイミングが遅れて、一瞬大きな音が出ることがある。: GPMと似たようなもので、ブラウザを使っているから仕方ないのかも。
      • 子プロセス(ValacefSubprocess)が若干重い。
    • 音量の設定が謎
      • 以前も書いた、0..1あるいは%だけど、実態は対数のような感じ。 → 暫定対応したが、要調整(較正)。

こうして書くとさまざまな問題があって、作っている最中にも、何度か「あ”ー面倒臭い、止める!」と放り出して純正に戻したい気にもなったのだが、使用メモリ量に関しては、約6時間で10MB程度しか増えていないので(最初は全然増えていないと思っていたのだが、良く見たら増えていたので、ちょっとがっかりした。僕としては、この程度だって増えて欲しくなかった。時間が経てば解放処理が動いて減ることに期待している)、その点では充分に価値がある。しばらく使ってみて、どっちがいいか決めたい。ただ、今までの経過を見ると、純正アプリは今後も修正・改良される可能性はないので、Nuvola Spotifyに期待(、あるいは自分で改造)する方が良さそうな気はする。

まあ、「根はいい人なんだけど、雑なのよねえ」と言われる人と「美人だけど、素直じゃないし、何もしないのよねえ」と言われる人の選択だろうかw

(10/15 21:54追記) 今日もほとんど一日掛かりっきりで修正・改良し、タイミングずれを改善した。Dbusのイベントの仕様が違うために曲の切り替わりを落としていたのが大きかった。あと、音量の設定もdBから設定値(0..1)への式(結局、10のべき乗のようだ)を導けたと思ったのだが、なぜか期待する音量にならないことがある。どうも、Nuvola Spotifyの音量の式や曲線が違うのか、音量設定処理が不安定なのではないかと思う。仕方なく、純正アプリと同様にPulseAudio側の音量を変えるようにした。

が、そこまでしたにも関わらず、web版Spotifyのひどさに全く我慢できなくなり(あれはゴミとしか言いようがない。本当に使うことを考えていないし、メンテされてない)、純正アプリに戻ろうかと思っている。純正アプリの更新はないと思っていたが、以前出たsnap版とかいうののバージョン番号が更新されていたので、そっちを試している。が、若干の変更・修正はあるものの、やっぱりメモリ・リークは直ってなさそうだ。

賢くて性格は悪くないけど大食いでデブな人と、化粧が濃くて高い服を着ていて目をひくけど、実際にはセンスが悪く、スリムだけど頭も顔も性格も悪い人の、究極の選択かw

(10/16 7:24 若干追加・修正)

 

PS. 測定して比較した訳ではないから証拠はないのだが、どうも、Nuvola Spotifyは音質が悪いように思う。今、純正アプリで聴いていると、普通に「すっ」と聴けて、音は全然悪くないのだが、Nuvolaの時は何となく嫌な感じがしていた(明らかに変ということはない)。Nuvolaのベースはweb(ブラウザ)なので、音を出す仕組みも「それなり」のもの(Widevineというアドオンが関係している?)だろうから、音質(特に時間軸の精度(=ジッター)か?)が劣化しているのかも知れない。 (10/16 16:17)

  •   0
  •   0

先日、ニュースで、某国のグループが音楽配信サービスに不正にアクセスしてチャートの順位を上げている疑惑を読んだ。

それで思い付いた。SNSの友人とかいいねの数を水増しするように、音楽配信サービスの再生数を水増ししてお金を稼ぐことを。

  1. とりあえず、プロダクションとレーベルを作る。
  2. 架空のグループを作り、売れない作曲家や作詞家と売れないアーティストに依頼して曲を揃える。信ぴょう性を上げるため、ビデオをYouTubeにも入れ、SNSのアカウントも作り(ただし、メンバーの詳細は伏せ、顔も出さない)、曲をダウンロード販売するサイトも作る。
  3. 作った曲・アルバムを音楽配信サービスに配信する。
  4. 音楽配信サービスで指定した曲を連続して再生するプログラムを作り、複数のPCやスマフォにインストールする(マイニングマルウェアのように世界中にばらまくと、効率が良い)。
  5. そのプログラムに、でっち上げたグループの曲やアルバムを指定して実行する。

ウマー?w

ある日突然、無名のグループがチャートの上位になったという話題で持ち切りになって、本当に売れるかも知れないな。でも、結局、これは仮想アイドルとかYouTuberの水増しと同じことで、うまく行かないのか?

問題点は、曲を再生するにはサービスの会員になる必要があるから、自分たちだけで入会して水増しするのではコストがペイしないってことだろう。あと、曲は途中で停めずに全部再生しないとお金が減りそうだから、時間も掛かりそうだ(その点は、曲の使用料と月額会費との比が絡むが、きっと、高額をせしめるには時間が全く足らないだろう)。更に、電気代も掛かるな。。。そういう点ではマルウェアで大規模にやるしかない? あとは、無料会員でも聴けるサービスでアカウントを乱造?

(21:51追記) 別件で検索していたら、配信サービスの使用料が分かった。 : "What is the best alternative to Spotify?"のDeeser musicのCONSより:

Doesn't pay artists enough
Deezer pays artists significantly less than other similar services. As of March 2018 it was paying $0.0064 / play, less than Apple Music and Google Play, half as much as Tidal ($0.0125). Not as bad as Spotify or Pandora, but could certainly do better.

上の情報が正しくて、仮にSpotifyの使用料がDeezerと同じとすれば、156回再生してようやく1ドルのようだから、なかなか割に合わない。仮想通貨のマイニングとどっちが儲かるのだろうか・・・

一方、AIが高性能になったら、作曲家も作詞家もアーティストも不要になり、どんどん曲が作れそうだから、コストは節約できそうだ。

もちろん、あくまでも空想です。実行してはいけません。

 

まあ、上の1から3までなら本当の音楽制作で、お金にならなくたって、まじめにやれば、それで充分楽しそうではないか。僕はそっちでいいやw

  •   1
  •   0

昨日、Spotifyの音量正規化がようやく何とかなったと一息ついていたのだが、ふと気付いたら、なぜか空きメモリがほとんどなくなっていた。道理で近頃Spotifyが重いような気がした訳だ。実際、何がメモリを食っているか調べたら、そのSpotifyが10GB以上食っていた(こういうのを「メモリー・リーク」という)。それは重くなるわなあ。。。

まずは、アプリの最大使用メモリ量を数GBに制限したのだが、抜本的な解決方法を考えるために、原因を調べた。ミニプレーヤの関係(Dbusで繋げているため)かと思ったが、結局、アプリ自体が悪いようで、既知の問題("Massive memory leak under Ubuntu 16.04 LTS" (2018/6/14))だった。そして、その投稿へのSpotifyからの回答はなし・・・

仕方ないので、どうにかして解決あるいは緩和できないか調べている。再生したりプレイリストを開くと増えるし、そもそも、何もしなくても増える。今は、アプリの内部情報を消さずにいて溜まっているせいではないかと考えて、起動時のオプションに"--trace-file=/dev/null"を指定して試しているが、半日も経たないうちに使用メモリ量は200MB近く増えて1.3倍になっており、期待できない。

"--trace-file=/dev/null"を指定しないと、起動直後の使用メモリ量が2倍近くになるようなので、指定した方がいいようだ。 (15:10)

(10/13 6時、6:43追記) Spotifyアプリのキャッシュ(~/.cache/spotify)と設定(~/.config/spotify)を削除すると(設定の削除は不要かも知れない)、使用メモリ量の増加速度が小さくなるようだ。1/3くらい(12MB/時)に遅くなった。それでも、メモリー・リークが直った訳ではない。キャッシュのデータ量は10GBにもなっていたので、定期的な削除が要りそうだ。というか、して欲しい・・・ ← 削除しなかったらもっと大きくなるはずだし、自分でも自動削除するようにしていて忘れていた。予想よりデータ量が多かったので、もっと頻繁に削除が要るのかも知れない。

どうしても駄目なら、アプリの使用メモリ量がとても多くなった場合には、長時間アイドル時にアプリを再起動しようかと思っている。以前はミニプレーヤで音量正規化の切替時に再起動していたから(今まで気付かなかったのは、これで頻繁に再起動していたからだろう)、実現するのは簡単だ。が、どうにも気分が悪い。(それに、ミニプレーヤのプログラムがどんどん肥大化するのも嫌だw)

→ つまらない機能を作るのが面倒なので、定期的にSpotifyアプリの使用メモリ量をチェックして、大きくなり過ぎていたらメールで通知するようにした。メールが来たら、自分で再起動すればいい。急激に大きくなる訳ではないから、それで充分だ。何でも作ればいいってもんじゃないw

→ 使用メモリ量の変化を見ていたら、毎日再起動したくなりそうな速さ(数MB/分 → 1GB/日以上)で、そんなに毎日手で再起動するのは面倒なので、自動再起動機能を作った。 まったく手が掛かる奴だw なお、使用メモリ量が多くなってアイドル時に自動再起動する時は、メニューボタンの背景色を変えて分かるようにした。あと、メモリ量のチェックを2段階にして、2番目のしきい値を超えたら即座に再起動するようにした。つい、遊んでしまう。こういうのを「芸は身を滅ぼす」というのだろうかw (19:15)

気になるのは、その問題自体よりSpotifyの対応なり動向だ。他にも問題や変なところが放置されているから、そのうち手に負えなくなって、「Linuxアプリは止めまーす!」とか言い出しそうな気がしている。それはとてもまずい。。。 まあ、その時でもWeb APIは継続するだろうから、それを使って自分でプレーヤーを作るか、他の対応プレーヤーを使うかだろうか。あとは、ミニプレーヤを純正のwebプレーヤーに繋げることができれば、それが一番いい。

でも、それよりも、Spotify自体が終わりになることが一番怖い。その時はどこへ移ろうか? 消去法でAmazonしかない気はするw あとはDeezer(ここは高いからないけど)などの新手のものかな。

  •   0
  •   1

Spotifyの音量正規化機能は大抵はうまく動いているのだが、曲によっては音量や音自体がおかしくなることがある。特に、Pink Floydの"Speak to me"(1973)の先頭のように音量がとても小さい時に破綻する。それでも、Google Play Musicのように、ないよりはずっといいのは確かだ。

が、近頃、SpotifyのWeb APIが使えるようになり、その中に曲の(音的な)特徴を取得する機能があるのに気付き、それを使って音量正規化ができないかと思っていた。具体的には、"Get Audio Analysis for a Track"(以下、Analysis)や"Get Audio Features for a Track"(以下、Features)が使えそうなので、調べてみた。

すると、どちらでも音量正規化に必要となる特徴量(曲の音量)が取れそうなことが分かった。具体的には、それらで取得できる"loudness"や"energy"である。なお、Analysisは取得できる情報は多いものの、上記の値程度しか使わないし、毎回分析するのか処理が遅いので、Featuresを使うことにした。

新しい音量正規化の処理として、以下のような手順を考えた。

  1. 新しい曲の再生開始時に、Features APIを実行し、音量の特徴量を取得する。(→ L)
  2. Lから、音量を正規化するための音量調整量を求める。(→ G)
  3. GをSpotifyの音量値に変換し(→ V)、設定する。

いくつかの曲で試したところ、音量の特徴量Lとしては、loudnessが良さそうだった。定義(概要)は以下のようなので、理論上はそのまま使えそうだ。

The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks.

なお、energyの定義(概要)は以下のようなので、うまくLに変換できれば、(数値でなく)聴感的な音量の正規化ができそうなのだが、いい方法が思い付かなかったので、今回は見送った。

Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity.

GMB(gmusicbrowser)での音量正規化の結果と比較して検討し、loudnessをそのままLとして使う場合、LからGへの変換式は以下とした。

G= X - L

Xは目標とする(一定にしたあとの)再生音量(dB)で、試行錯誤の結果、-13(dB)が最もGMBの音量に近くなったので採用した。

(10/12 6:26追記) 後から気付いたのだが、上のXは正確には2つの要素からなる。一つは、目標とする音量Yであり、これが仮想的な0dBとなる。もう一つは、正規化した音のシステムの最大音量(0dB)からの余裕Zであり、Yの音量は実際のシステムでは-Zとなる。音量をYに正規化したあと、音量(振幅)はZまで大きくなることが可能である。XはYとZの和であり、通常はY= Z= X/2と設定するので、上のように書いても大きな問題ではないが、動作の調整・確認をしている時に「何かおかしい」と思ったので書いた。

ただ、これは考え過ぎとか誤解だと思う。今、書いたあとに気付いたのだが、Yは実際には「平均」音量であり、もしYを「最大」音量(0dB)とすれば、Z= 0となる(それで充分)だから、Y= Xとなり、上の変換式はそのままで正しい。最初は最大音量と考えてその式を書いたのに、実際の動作を見ているうちに誤解したのだろう。 (だから、この節は書かなくても全く問題ないのだが、忘れるために書いておくw)

が、更に気付いたのは、Lはloudnessであって最大音量ではないので、やはりYは平均音量と考えるべきで、やっぱり上の節は要る。別の考えをすれば、Lに係数が要るのかも知れないということだ。その係数は、その曲の振幅の変化量(= ダイナミックレンジ)を示す値だろう(が、それはSpotifyでは分からない)。

Spotifyの音量を調整するには、アプリの音量そのものを変更する以外に、Spotifyアプリのあとにアンプやミキサーを入れてそれで調整する手がある。しかし、外部プログラムから手軽にゲインを変更可能なものが見つからなかった(MIDIを使えば制御できそうではあった)のと、できるとしても結構大げさになるので、今回は見送った。

Spotifyアプリの音量を変更するには、(現在のSpotifyアプリはDbusでは音量が調整できないため、)Spotifyアプリにウインドウシステム(X11)経由でイベント(キーやマウスホイール)を送ってボリュームを操作する方法と、PulseAudioのSpotifyアプリのボリュームを設定する方法がある。後者は音量値にdBや相対値が指定でき、pactlコマンドで簡単に実行できるので採用した。

上記のように、音量値にdBが指定できるので、基本的に、GがそのままSpotifyの音量値として使える。ただし、Gが大き過ぎる(例: 0よりかなり大きい)と音質が劣化するので、上限(Vmax)を設けることにした。今回はLは6(dB)とした。結局、Spotifyの音量設定値V(dB)は以下のようになる。

V= G (G < Vmaxの時),
     Vmax (G >= Vmaxの時)

ただし、pactlコマンドの仕様により、符号付きの値は現在値からの相対値になってしまい、負のdBは相対値とみなされるために(、結局全然)使えないので(どういうつもりなのか、作者に聞きたい)、pactlに指定する時に0..1の数値(R)に変換している。これはdBから数(比率)への変換で、以下のとおりである。

R= 10(V/20)

ここで不思議だったのは、Rをpactlに指定すると期待どおりの結果にはなったのだが、設定後に取得した音量の%の値が想定と異なるのである。例えば、"0.5"を指定すると、結果は"50%"でなく"79%"となる。dBの値は"-6.02dB"と正しいが、%はどうもおかしい気がする。本来は50%になるべきと思うのだが、%の値も対数なのだろうか。謎ではあるが、実際の音量や聴感的には期待どおりなので、深くは考えないことにした。ただ、将来的に、バージョンアップなどでこの動作が変わってしまうリスクはある。

pactlコマンドでSpotifyアプリの音量を設定するには、以下の手順で行う。

  1. Spotifyアプリのsink-inputのIDを得る。→ siid
    • pactl list sink-inputsの出力を解析する。
  2. Spotifyアプリの音量をRに設定する。
    • pactl set-sink-input-volume siid Rを実行する。

上記の処理を実装して聴いてみたところ、概ね期待通り動いている(→ 曲が変わるとボリューム(画面中央下部)が動くデモ)。ただし、以下のような問題がある。

  • 曲の切り替わりの検出に時間ズレが生じることがあるので、音量設定タイミングがずれることがある。
    • 音量の小さい曲の後に大きい曲が掛かる場合、音量を下げるのが遅れる場合があって、その時には、次の曲の先頭が(一瞬)大音量で再生されてしまう。
    • 逆に、音量の大きい曲の後に小さい曲が掛かる場合、音量を上げるのが早過ぎる場合があって、その時にも、次の曲の先頭が(一瞬)大音量で再生されてしまう。
  • 曲によっては少し大きく感じることがある。
    • 例: Commodores "Easy", CHIC "Le Freak"

曲の切り替わりの検出精度は、Spotify API自体にズレがあるので、容易には向上できず、本質的な解決は難しいのだが、音量を一気に変えずに、1回の変更量に上限を持たせて少しずつ変えるようにして(ただし、音量を下げる時は2倍の速さにする)緩和を試みた。また、変更前の音量が0dBを超えている場合は、超過分を一度に下げるようにした。この修正の都合で、pactlへの音量設定値を、比率(R)でなく現在の音量とVの差分にした(結局、符号付きのdB指定(相対値)だけでも良くなった)。

(10/3 12:23追記) 曲の頭が一瞬大音量になることがある問題は、JACKのエフェクタを使えば緩和できるかも知れない。Spotifyの出力を、瞬間的な大音量を抑えるようなエフェクタ(リミッター?)につなぎ、音量正規化がonの時だけそのエフェクタをonにすれば良さそうだ。エフェクタの制御は本アプリ(Spotifyミニプレーヤー)からMIDIで行う。おもしろそうだが、パラメタの設定は難しそうだ。余りにも気になるようなら、やってみたい。

この場合は、音量正規化もJACKでできる。Spotifyの出力をミキサーのSpotify用入力につなぎ、その音量を本アプリから行えばいい。上記エフェクタの入力レベルが変えられるなら、それでも可能だ。ただ、これ自体の価値はそれほどない。あくまでも、大音量を抑えるついでにできるということだ。

大きく聴こえる曲は、今のところどうしようもない。数値で正規化する限界なのかと思い、採用を見送ったenergyがうまく使えないものかと思っている。ただ、GMBの正規化でも同様なことはあるし、自分や周囲の状態によっても音量は違って聴こえる(要は「気のせい」)から、あまり深追いしても仕方ないのかも知れない。

(10/6 21:22追記) 音量で気になっていることの一つは、静かな曲の音量が大きくなり過ぎることなので、それを解消するのに上記のenergy(以下、E)を使って音量設定値Vを調整してみた。

静かな曲はloudness(L)が小さいためにVが大きくなるので、音量が大きくなりやすい。一方、そういう曲はEも小さいので、Eの大きさ(小ささ)でVを調整することを考えた。Eが小さい時は、その分Vを減らすのである。

Eがどういう単位・仕様の値なのか不明(0..1ということだけ明らか)なのだが、試行錯誤して、Eの値をdBに変換してVに加える(Eは0より小さいので、実際には引かれる)ようにした。Eで調整した音量設定値V'は、次の式で求められる。

V'= V + k * 20 * log10(E) (E >= Eminの時)
      V + k * 20 * log10(Emin) (E < Eminの時)

kはEの強さを調整するための定数で、0.05から0.3程度が良さそうであるが、いろいろな曲で試したところ、0.15辺りが最も適当だった。ただ、曲によって変わるので、更に調整が要りそうだ。Eminは想定する最小のEで、0.0001とした(log(0)はエラーになるので、それを防ぐために定義している)。

この式は全くの思い付き(と誤り)から出て来たものである。Eの詳細が不明なので、そのままdBに変換していいのか怪しいが、VはdBなので、VをEで調整するのなら、少なくとも、EをdBに変換した値を使うのは適切だと思う。

残念ながら、この方式は、元々音量が小さくなくて更に大きく聞こえる曲(例: 上記の"Easy"や"Le Freak")には効果がない。それらはEが大きいため(だから、うるさく聞こえるのだろう)、ほとんどVが減らないからである。それらには別の特徴量が使えるのかも知れない。

(10/9 11:09追記) 音量でもう一つ気になっていることは、クラシックの曲の正規化がうまく行かないことだ。クラシックの曲はポップ音楽と違ってダイナミックレンジ(音量の幅)が広く、平均音量が小さいことが多いため、ポップ音楽と同じように正規化すると音量設定値Vが10dB前後ととても大きくなってしまう。一方、DACは0dB以上の音は再生できないので、音質が劣化する。

これに対処するには、まず、目標音量Xを下げて(例: -20dB)、(形式的な)増幅の余地を増やす必要がある。また、10/6の追記とは逆に、energy(E)に応じて音量設定値Vを増やす方が良さそうだ。そこで、E(のdB値)に応じてloudness(L)を増やすことにした。ただし、LがXより大きい場合に更にLを増やすと、Vが減って逆に音量が下がってしまうので、Lを増すのはLが小さい場合だけにした。クラシック音楽用の音量設定値V''は、次の式とした。

V''= X' - L''
  X': クラシック音楽用の目標音量 (dB)
  
  L''= L' (L' < X'の時)
        L (L' >= X'の時)
  
    L'= L + m * 20*log10(1 - E) (E >= Eminの時)
         L + m * 20*log10(1 - Emin) (E < Eminの時)

mはEの強さを調整するための定数で、いろいろな曲で試したところ、0.05辺りが最も適当だった。また、X'は-24dBとした。これらも継続して調整が要りそうである。

なお、目標音量をかなり下げるために音質の劣化が心配だが、まず、ほとんどの場合に実際の設定音量は0dB付近になるため、大きな問題はない。なお、仮に設定音量が目標音量と同じくらいになった場合には音の有効ビット数が減るため、音質が劣化する。その有効ビット数は、元の音を16ビット相当(ダイナミックレンジ: 約100dB)とした場合に設定音量を-24dBに落とした場合には、概ね (100-24)/6= 12.7ビット程度になる。この場合でも、有効なダイナミックレンジは76dB程度あるはずだ。

実際に、いろいろな音量の曲に対してこの方式で音量正規化を行った場合と音量正規化を行わない場合の音量を比較したところ(どちらも、アンプの音量は最初に調整した後は変えないものとする)、音量が適正だと感じることがほとんどだった。数値的にも、それらの曲に対して約9dB(= 2.8倍)の幅で調整を行っていたので、効果はありそうだ(→ クラシック音楽でも、異なる曲を混ぜて聴く時には音量正規化はあった方がいい)。なお、この方式ではポップ音楽も正規化できるが、方式やパラメタが最適でないうえに、ポップ音楽はダイナミックレンジが狭い場合が多いため設定音量が目標音量(-24dB)付近になることが多いので、音量と音質の点で得策でない。そのため、この方式をクラシック音楽用のモードにし、従来のをポップ音楽用にした。

クラシック音楽用の音量正規化モードを追加したため、ミニプレーヤのUIを変更し、音量正規化のon/offでなく、off("-")またはモード(ポップ("P")/クラシック("C"))で表示するようにした。

それから、音量正規化のモードを切り替える際に音量が大きく増加することがある(例: クラシック → off)ので、安全のため、再生中にそのような切り替えを行った場合は一時停止するようにした。

最後に、気になっていた、静かな曲での正規化結果を比較してみる。以下は、"Speak to me"の先頭約20秒(鼓動)の部分の右チャネルの波形(上から順に、GMB (正規化off), Spotify(正規化off), GMB (正規化on), Spotify(正規化on), Spotify(今回の正規化))である。なお、それぞれの開始時刻は合わせていないので、波形の位置は異なる。

Pink Floyd "Speak to me"の先頭約20秒の右チャネルの波形比較

正規化した波形(最後の3つ)を見ると、明らかに、Spotifyの正規化は「やりすぎ」であり、そのためにおかしく聴こえていたことが分かる。一方、今回の正規化(一番下)は小さ目ではあるが、GMB(上から3番目)と同様の振幅になっている。聴いた感じでも問題なく、今回の方式が有効であることが確認できた。

なお、今回の正規化の振幅が小さ目なのは、この曲の音量がとても小さく、本来の音量設定値が上限(6dB)を超えているために、充分に音量を上げられないためである。

→ 音量制限の上限を解除して試したところ、振幅がSpotify以上に大きくなってしまった(フルスケールを超えた)。パラメタの調整(あるいは、上記のenergyの利用など)が要るようだ・・・ そして、Spotifyの正規化の処理は正しかったようだ。この点はがっかりした。

→ 音量設定値の上限を7.5dBにしたら振幅がGMBと同等になったので、当面はこれで試してみたい。

→ (19:40追記) どうやら、(当たり前ではあるが、)0dB(100%)より大きく増幅するのは良くないようで、少し長くクラシック(0dB超えの曲ばかり)を聴いたあとにポップに切り替えたら違和感が生じた(耳がずっと圧迫されていたような感じ)。また、当たり前だが、たまに音量がオーバーレンジ(0dBを超える)するのも余りいい気分でない(ただし、瞬間的なので聴いていても分からない)。それで、上限を0dBにすることにした。それで音量が小さくなってしまう曲はもともと小さく作っていると考えて、諦めることにする。

馴染みのない方のために説明すると、0dBを超えて増幅するというのは、デジカメのデジタルズームとかISO感度を高くするようなもので、確かにそれらしい画像は写って便利なのだが、無理してデータを作ってるから画質は期待できないということだ。

あと、"Speak to me"の冒頭の音がおかしく聴こえるので、Spotifyアプリの正規化は動的に処理(例: 現在までの音量などで現在の音量を調整する)しているのかと思っていたが、波形はそうでもないので、音量を上げ過ぎているだけなのかも知れない。ただ、目標音量を小にすると音量が下がり過ぎてしまうので、Spotifyアプリは今一つなことは確かだ。

副次的な効果として、今までは、音量正規化をon/offする際はSpotifyアプリを再起動する必要があるので、再生が停まり画面が変わってしまうなど、ちょっとしたストレスだったが、今回の方式では気軽にいつでも(まさに"on the fly")切り替えられるようになり、大変便利になった。実際には、このイライラを解消したいということが、今回の作業に着手する大きな動機になった。

(10/6 21:22, 21:39 変数名の重複を修正、設定値を更新)

 

PS. その後、調整・修正・改良しながら使っていて(というか、そればっかりしているがw)、上記の曲間のタイミングずれによる不意の大音量を解消したいと思っている。が、それは難しいことも分かった。今のところ、以下のようなことを考えている。

  • コンプレッサーやリミッターで大音量を制限する。
    • 大音量がほんの一瞬に抑えられるが、通常の曲(特に、クラシックは音量レベル(上記L)が小さいと認識されるため、大抵、音量(上記V)が最大に設定される)の大音量も制限してしまうので、(聴感上は分からないが、)常時は使いたくない。必要な時だけonにする必要がある。
  • コンプレッサーなどを使わないで回避する。
    • Spotify web APIのタイミングズレを補償する。
      • (無音で?)曲間を検知して、曲間と認識する。
      • 「スマート」な処理を作る?
      • 次の曲の先読み?
    • 我慢する。

切り替えて使うにしても、コンプレッサーなどはどうも気に入らない(onにしている時は妥協していることになる)ので、使わない方法を考えている。でも、できるかどうかは不明だ。まあ、あまり頻繁に起こらない(実際、昨日確実に起こっていた曲で今日は起こらない)ので、我慢するのが一番効率的なのかも知れないw

その他、以下のような改良をした。

  • 音量設定処理の遅延を防ぐ。
    • 曲間にSpotify web APIの認証トークン(有効期限がある)を更新すると音量設定処理が遅くなる可能性があるので、可能な限り、「忙しくない」時にトークンの更新をし、曲間での更新を抑えるするようにした。
      • 具体的には、再生中に一定間隔(例: 2分)で(無駄に)web APIをアクセスする。この時、トークンの有効期限を短め(例: -5分)に見て早目に更新しておく。一方、曲の切り替わり時のアクセスでは、有効期限ギリギリまで(例: -10秒)トークンの更新をしないように指示する。
  • 自動的に音量をリセットする。
    • 再生を停止してある程度(例: 20秒)時間が経ったら音量をデフォルト値(例: -10dB)に戻すようにして、(小音量の曲の再生後、)次に再生する曲の頭が不意に大音量にならないようにした。
      • ただ、次に再生する曲の頭が小さくなってしまうことがあるという弊害はある。

(10/5 10:50)

PS2. PSに書いた、Spotify web APIの曲の切り替わり通知タイミングずれによる意図しない大音量を防ぐ方法について考えた。曲の切り替わりを正確に検出して、その切り替わった時点で音量を設定すればいい。そのためには、まだ曲間になっていない場合にはそれまで待てばいいが、既に曲間が過ぎている場合には時間を戻して、出た音の音量を変える必要がある。果たして、そんなことはできるのか?

まず、曲の切り替わりを正確に検出するのが難しい。 一番簡単なのは無音検出だろうか。現在の再生位置が曲の終わり付近になった場合やSpotifyアプリから来る「曲が変わった」イベントの付近で(これらはある程度正確と考えられる)無音になったら「切り替わり」と判定するか。曲の中には終わったと見せかけて再度始まるものもあるが、さすがに終わりの数秒間ではなさそうだ。だが、今と次の曲がどちらもメドレーとかライブとか雑音が多くて、無音部分がなかったら駄目だ。。。

無音を検出すること自体は可能だが、ちょっと重い。そもそもそういうプログラムが要る(探せばあるだろう)。無音がない場合にも対応するには、音の特徴を分析するのだろうか。それは結構重い・・・

時間を戻すのは、不可能に思えて実は可能だw 戻す期間を数秒間に制限すれば、再生する波形をその時間分格納し、古いものから順に再生するようにすれば(ところてんのような感じ)、その数秒間は戻すことができる(正確には、Spotifyが再生したと思っている音はまだ再生されていないから、出てしまったはずの音(= 過去の音)を操作することができる)。問題は、再生に常にその数秒間の遅延が生じることだ。再生ボタンを押してから数秒待たないと音が出ないし、停めても数秒間は音が出る(こっちは何とかできる気がする)。それが許容できるだろうか。

一方、今日は問題が全然起こらなくなってしまって、「もしかしたら、いじっているうちに直ったのか?」と、淡い期待をするのだが、実際にはそんなことはないのは、今までの経験から明らかだw でも、滅多に起こらないことは確かなので、わざわざ上に書いたような大掛かりなものを作って苦労しなくてもいいような気がしている。ただ、技術的な興味から、やってみたい気分はある。

そして思ったのは、(昔の)日本にはこういう物好きな技術者が多く、それだけならまだいいが、お客や経営者が無理難題を吹っかけたにも関わらず、(24時間戦うw)彼らによって実現されてしまった製品を素直に販売してしまったから、ガラパゴス化してしまったのかも知れないということだ。

(10/5 21:28)

  •   0
  •   2

今回もSpotifyの功績である。

結構前から、Blue Öyster Cultという得体の知れないグループの曲(例: "Burnin' for You"(1981))が良く掛かる。最初は(曲もグループも知らないので、)「しつこいなぁ」と、鬱陶しく感じていたのだが、恐ろしいことに、近頃は結構好きになってしまった・・・ "Burnin' for You"なんて、結構かっこいいと思う。(Spotifyは、自分でも気付いていない僕の好みを分かっているのか?? それとも、単なる洗脳?w)

調べたら、かなり歴史あるようで、1960年代から始まったようだ。以前、「いいと思う曲で、初めて聞く曲はほとんどない」とか書いたが、そうでもなかった。音楽の世界は広い。

余談だが、"Burnin' for You"のアルバム"Fire of Unknown Origin"(1981)のジャケットはかなり印象的で、一度見たら忘れられない気がする。ただ、僕は、例によって、しばらく誤解していた。それは、、、

グループ名を"Blue Öyster Cat"と思い込んでいた。そして、ジャケットの絵も、(表示があまり大きくなかったので)「なんか不気味だけど、猫が並んでいるのかな」と思い込んで、妙な不思議さや親しみを感じていた。

でも、今、彼らのことをWikipediaで読んだら、歴史はあるし、最初は深遠な思想に立脚していたようなので、全く不謹慎の限りだw

  •   0
  •   1

気付いたら、音楽配信サービス(Google Play Music → Spotify)に加入してから1年経っていた。それで、ちょっと思い付いてCDなどの購入数を調べてみたら、変化がすごかった。加入後に買ったのはたった1組(サイ 「春の祭典」)だった(これにしたって、Google Play Musicでは曲間が切れるから仕方なく買ったのだ。Spotifyでは切れないので、最初からSpotifyだったら買わなかったから、「実質0組」だ)。ちなみに、その前の1年間(2016/8-2017/8)に購入したのは39組(ダウンロード購入も含む)だった。

期待以上だ。お金(月額料金: 約千円)の点では充分元が取れている。概算で1/8(2500円/組の場合)〜1/3(千円/組の場合)にコストダウンできた。音楽はお金に比することはできないが、使えるお金には限りがあるので、少ない出費で満足できるのなら、すごくいいことだ。しかも、音をPCに取り込んだりファイルを整理したりメディアを保管する手間がないのもいい。聴くのに徹することができる(実際には、補助ソフトを作っていたがw)。

それまでは、販売サイトでの短い試聴(これはほとんど役に立たないから、もっと考えてほしい)かYouTubeにあれば試聴して買っていたが、気になったものは試聴すらせずに手当たり次第に買うフシもあったから、失敗も多かった。それどころか、特定の曲(例: ラフマニノフやモーツァルトのピアノ協奏曲)はもっと試したい気すらしていた。それが、音楽配信サービスのおかげで、本当に手当たり次第聴く(試す)ことができるようになったのだ。

そういえば、この、「好きな曲を手当り次第試す」のは、なぜか一段落している。かなり聴いたし、細かく聴き過ぎてちょっと疲れたのはあるのだろうが、(当時は意識していなかったが、)会社で溜まったストレス解消とか現実逃避にやっていた面もありそうだ。実際、昼休みの短い時間に(全曲は聴けないのに・・・)すらやっていた。それと、今は時間が充分あるので、いつでも聴けるという安心感があるのかも知れない。

もちろん、気になった演奏の中には配信されていないものもあるが、今までで数組(例: アムランとアンスネス 「春の祭典」(2台ピアノ版)(2018))しかない(それ以前に、発売されていない(= 配信されようがない)演奏が多い)。他に、全く配信されない演奏者(例: 吉幾三、キャンディーズ、小泉今日子)は結構居る。前者はもう少し待って出なければ買うし(それ以前に試すべき演奏は多い・・・)、後者は大体手持ちにあるので、聴くという点では実害がない。どちらも、今後配信される可能性は0ではないだろう。そういうのをリクエストする機能があるといいと思う(が、検索してレパートリーにないのを集計して、契約プッシュ候補にしているのではないかと、勝手に期待している)。

あと、今までにも書いているように、Spotifyのリコメンド機能(Daily mix)で、知らなかった演奏者・曲や、名前は知っていても聴かなかった演奏者・曲を(再)発見できるのがいい。同様に、昔耳にしたが曲名も演奏者名も分からなかった曲の正体が分かるのもいい(例: Rupert Holmes "Him"(1979))。

配信サービスには関係ないが、曲の正体を知るにはShazamが便利だ。昨日、中学時代にFMから録音した古いテープに入っているけど曲名が不明なのの数曲が分かった。同様のサービスは他にもあるが、どれを試しても分からなかった。ただ、このアプリはOFFにしていても勝手にONになるので、今一つ嫌いだ。

その他に、(今までに書いているが、)Daily mixが優秀で、以下のように、♥(like= 「好き」にした印)がずらっと並ぶことがあって、「分かってるね!」と、うれしくなる。

SpotifyのDaily mixでずらっと並ぶ♥(like)

ただ、これには良くない面もあって、毎回同じ曲・演奏者が掛かって飽きてしまうことがある。何回聴いてもいいグループ・演奏(例: ELO、ボストン)は多いが、そうでないのも多い。他に、嫌いではないけど大好きでもないからlikeを押してない(スキップすらしている!)のにしつこく聞かされてうんざりしているグループ・演奏も多い(例: プリテンダーズ、10cc、メン・アット・ワーク、"Layla"(1971))。まあ、「好き嫌いは良くないよ」って言ってるのかも知れないがw、改良に期待したい。

他にも細かい要望はあるが、充分満足している。

  •   0
  •   1

Spotifyのリコメンド(Daily mixなど)も大分落ち着いて、曲目に♥が連続する状態が頻発するようになってしまったので、新しいものを聴きたくなって新作を見ていたら、例の、妙に惹かれる「逆立ちお嬢さん」のアルバムが目に入ってしまった。正直言って、曲には全然期待できなかったから聴きたくはなかったのだが、暇だったしw、惹かれた(一種のジャケ買いだろう)のは確かだったので、試しに聴いてみた(以前もテイラー・スウィフトを試した気がする。そういうことが簡単にできるのが、Spotifyのいいところだろう)。すると、意外なことが起こり、大きな疑問が湧いた。

ちゃんと書くと、アリアナ・グランデの新作、"Sweetener"(2018)を聴いた。

想像通り、良くある現代の歌(いわゆる「ヒップホップ」なのだろうか)って感じだ。(こう書くと、年寄りの的外れな形容になりそうだが)浜崎あゆみとかUtada(海外向けの曲)とかテイラー・スウィフトと同じ系統に思えた。でも、声は悪くなく、乗りも良かった(だから、曲も良かったのだろう)。

(8/18 13:20追記) 彼女のジャンルを調べたのだが、ヒップホップ(≒ラップ)とは違うが、検索しても、どうもピンと来る表現がなく、コンテンポラリーR&Bとかポップなどと書いてある。まあ、ポップで外れてはいないが、広過ぎる気がする。ちなみにテイラー・スウィフトは、カントリー(これには背景があるらしい)とかポップらしい。今のポップ音楽は、ああいう感じの曲が主流だってことだろうか?

そして、信じられないことに、結局、最後まで聴いてしまった。正直言って、好きな音楽ではないが、(何度も試してくじけた)スウィフトと違って、途中で止める気にならなかったのがすごく不思議だ。Utadaがギリギリで受け入れられたのと似たようなものかも知れない。人気があるのは、こういうところにも関係しているのかも知れない。

そして、大きな疑問は、

こういう歌は口ずさめるものなのか?

だ。どの曲も乗りはいいけど、ああいう、ドコドコした連続性に欠ける曲では、口ずさめるメロディーがないような気がする。そもそも口ずさむ歌ではないのか。あるいは、僕が現代に追いついていないだけなのだろうか。若い子たちは普通にカラオケで歌っているのだろうか? 是非聞いてみたいw

一方、ロックなら、かなりすごいパンクでも口ずさめる(→ : 今日、グランデとは別に聴いたバンド、Duncan's Divas。Spotifyにはないので、手持ちで聴いた。初めて映像を見て、バンドに女性が居たのを知ったw 可愛いと思っていたコーラスは、彼女たちだったのだ)ので、妙な感じがする。どうせだったら口ずさめる方がいいと思うが、まあ、好みの問題だろう。

(8/18 0:57追記) 口ずさめるという点では、宇多田の歌はヒップホップ的なものでもできることに気付いた。例えば、"Automatic"や"time will tell"(どちらも1998)だ。やっぱり彼女には才能があったのか、あるいは、詞が日本語だからできたのだろうか? だから大ヒットしたのかも知れないし、僕が気に入ったのも、そういうところが良かったのかも知れない。

 

PS. 細かい話だが、曲名がほとんど小文字なのは結構意外だった。なんか、日本で言えば昔のギャル文字みたいで、逆に古い気がするが、今でも小文字は「いい」のだろうか? それとも、もう、すっかり普通になってしまったのか?

PS2. 新作と言えば、ポールのは全然聴く気になれない。ジャケットもつまらないし、シングルで出た1曲だけちょっと聞いたが、良くある彼の近頃の曲といった感じで、「で?」って感じだった。さすがに彼は「最新」ではないのだろうし、僕の中ではグランデに負けたw

  •   0
  •   1

先日から渡辺真知子を見直している。今朝も、彼女の歌が掛かったら、「やっぱりいい!」と思った。他の「うまそうに」歌うポップス系の人たち(個人的な印象なので、例示は止めておく)と違って、本当にいいのだ。どういうことかというと、本物(≒ ちゃんとしたクラシック系の人)だと思えるということだ。具体的には、声の質と量が豊かで深みがあって魅力的なのだ。別の言い方をすれば、「お腹の底から声を出している」かも知れない。あと、(下品でなく)明るく色っぽい感じに歌うのもいい。

そして、今はどういう歌を歌っているのか気になった。が、その先が問題で、今はSpotifyでいくらでも聴けるのに聴いてはいないし、これからも聴く気は起こらないだろう。

というのは、確かに彼女の歌唱は手放しで褒めたいくらいいいのだが、近頃の曲が僕の好みかは疑問で、おそらくそうでないからだ。実際、昔のアルバムを聴いても、ヒット曲以外はグッと来なかった。(そういえば、大好きな「かもめ―」の「スタジアムバージョン」とかいうのだって、イントロだけで「いい曲に余計なことすんな!」と思ったくらいだ)

ピアニストに例えれば、技術も表現もすごくいいんだけど、僕が好きな曲を弾いてくれない人のようなものだろうか。本人は弾きたい(歌いたい)から選んで(作曲して)おり、それはその人の表現(まあ、営業的なものもあるかも知れないがw)そのものだから、いかんともし難しい。

まあ、今後、Spotifyでリコメンドされて掛かることはあるだろうし、その時に気に入る可能性もあるから、気長に構えることにする。

  •   1
  •   0

拙作のSpotifyミニプレーヤー(minisp)の話である。

僕は外国の音楽を聴くことが多いので、Spotifyアプリの言語設定を英語にしている。それでminispもそのまま英語表記にしていたのだが、演奏者の名前については、日本のポップ音楽の時は、日本語で書いた方が見やすい気がしていた(なお、英語モードにしていても、日本のポップ音楽の曲名やアルバム名は日本語で出る)。例えば、前の稿で書いた渡辺真知子は"Machiko Watanabe"じゃなくて、やっぱり「渡辺真知子」の方が見やすいし適切だろうと思って、何とかしようとしていた。

が、その「日本のポップ音楽の演奏者だけは、名前を日本語で書く」という機能を実現するのは結構難しかった。どうやって日本のポップ音楽の演奏者を判別するかが問題だった。最初はMusicBrainz(フリーの音楽情報DB)の演奏者情報を使おうとしていたのだが、フリーのためか、登録されている情報が使いにくい(英語圏以外の人名が現地語で書かれている(例: ルガンスキーは"Николай Луганский"): DBの情報としてはすごく正しいことだが、使いにくい)とか一貫性がない(例: 抜けがある)などの問題があって、うまく使えなさそうだった。仮にそこが何とかなっても、そもそも「日本の演奏者」を判定するのが困難だったので、ずっと保留にしていた。

が、先日、SpotifyのWeb APIが使えるようになり、それで取得できる演奏者情報の中にジャンルがあり(なぜか、曲にはない)、運のいいことに、日本のポップ音楽の演奏者のジャンルには"japanese"とか"enka"とか"kayokyoku"とかいう単語が含まれていることが分かったので、それで判別することにした。なお、ISRC(曲の録音の識別記号)の先頭の2文字で「日本の録音」であることが判別可能なので、それを使うことも可能なのだが、仮に外国の演奏者の日本録音盤があった場合(ないとは思うが・・・)に誤判定になるので止めた。

少し苦労したが、うまく行った。が、思わぬ伏兵が居た。日本人のクラシック音楽の演奏者だ。その人たちのジャンルにも"japanese"が入っているので、名前が日本語で表記される。例えば、内田光子だ。それも一貫性があっていいのだが、個人的には、世界的なクラシック演奏者は英語で書く方が適切だと思っているし、オリジナルCDでも英語なので、ここは英語にしたい。

幸い(というか、どういう訳か)、日本人のクラシック音楽の演奏者には"japanese"とともに"classical"という単語が入っているので(例: "japanese classical performance")、その場合には英語表記にすることにした。

余談: (日本の曲だけを演奏している訳でない)クラシック音楽の演奏者のジャンルに国の情報を入れるのは、ちょっと差別的(昔の、「日本人のクラシックだよ()」という嘲笑を感じる)な気がするが、まあ、Spotifyはそういうポリシーなのだから仕方ないし、今は便利だから良しとする。でも、個人的には、入れるのであれば、「出身地域」などのようなフィールドの方が適切だと思う。が、いろいろな問題や文句が出そうなので、無理そうだ。

更に調べたら、ユジャ・ワンやチョ・ソンジンのジャンルには、国籍を示す単語は入ってなかった。どういうことなのか理解に苦しむが、考えても仕方ない。まあ、Spotifyでなく、レーベルがデータを作ってSpotifyに渡していて、その作り方の違いなのかも知れない。実際、ソン・ヨルムのジャンルは空だった。

という訳で、とりあえずできたが、(僕のわがままのせいで)いろいろな判定が多くなってプログラムが複雑(正確には「肥大化」)になっているのが気に入らない。あと、上の判定はやっぱりいい加減なので、今後、思わぬ落とし穴が見つかりそうだ(例えば、日本のポップ音楽だけを演奏する外国の演奏者が居たら、一体どうなるのか?? あと、宇多田ヒカルはどうなんだ? → ジャンルに"japanese r&b"が入っているので、日本語で出るはず)。

技術情報: SpotifyのWeb APIで、例えば曲情報の言語(例: 日本語/英語)を指定して取得する方法はあまり資料には書いてないが、可能だ。カテゴリーのブラウズにならって、要求のURLにlocale引数を追加すればいい。例えば、Spotify IDがxxxxの曲のトラック情報を日本語で取得するには、URLを以下のようにする(太字部分を追加)。

GET https://api.spotify.com/v1/tracks/xxxx?locale=ja_JP

これは公開情報でないので、いつまで使えるかは不明だが、単に資料の記載漏れと思うので、大丈夫だろうと思う。

  •   0
  •   0

先日、Spotifyが仕様変更(ローカルなhttpでのSpotifyアプリの制御・情報取得機能の廃止)したために、対応に追われていた。というほどまじめにやっていた訳ではなかったが、それまで動いていた機能(再生位置の表示)が、ある日(7/21頃)アプリを再起動したら、突如として駄目になって慌てたのは確かだ。検索してみたら、他にも引っ掛かった方が居て、フォーラムの投稿がいくつか見つかった(例:  "[IMPORTANT] SpotifyLocalAPI not working #254")。

実は、今回のことは最初から予想していたので、「勝手なことをしやがって! ク○が!」などとは全く思っていないw 「意外に早かったな・・・」程度だ。そもそも、非公開の機能を勝手に使っていたこっちが悪いので、それを彼らが予告なしに無効にしたって、文句を言う筋合いはない。

が、再生位置の表示がないとどうにも不便なので、何とかしなければならなかった。根本的な解決策(公式のWeb APIを使うこと)は既に分かっていたのだが、資料を見るとどうにも面倒な感じなので、できれば避けたかった(前もって書くが、こういう手抜きが後々どうにもならなくなることが多い)。

それで、とっつきにくいWeb APIは後回しにして、まずは、小手先(あるいは、子供だまし)の対処をした。再生位置(時間)は分からないが、新しい曲の再生が開始されたことは分かるので、開始した時からの経過時間を表示する(要は、1秒ずつカウントアップする)ようにしてみた。見た目はそれらしいが、中身は誤魔化しもいいところだ。

それにする前に他の案も検討したのだが、どれも駄目な(手軽にはできない)感じだった。例えば以下である。

  • アプリのウインドウに表示される再生位置の数字を(プログラムで)「読む」。: 検索してもそんな便利な物はなく、無理っぽかった。やるなら、画像認識が要りそうだ。ちゃんとできればいいが、さすがに毎秒やるのは重そうだ。
  • アプリとウインドウシステム(X Window System)のサーバ間の通信を傍受する。: どれが何か判別不能だった。どうも、数字は文字でなく画像として表示している感じだった。
  • アプリのログやメモリを読む。デバッガ(gdb)でアプリの変数を読む。: やっぱりできなかった。ログには書かれていなかった。デバッガなんて、使い方を思い出せなかった・・・
  •  ブラウザでwebプレーヤーを表示して、その数字を読む。: メモリが無駄になるので、却下した。
  • アプリとSpitifyのサーバとの通信を傍受する。: やっぱり判別不能だった。TLSで暗号化しているだろうから、そもそも無理だろう。

誤魔化し策は結構簡単そうな気がしたが、実際に作ってみると意外に大変だった。まず、再生を一時停止してもカウントアップが停まらなかったしw、アプリで再生位置を変えても(プログレスバーでのジャンプ)反映されないし、アプリの起動時に曲の先頭でなければ、その曲の最後までずっとズレたままだ。

かなり試行錯誤して、一時停止とジャンプについては何とか対処できた。後者は、アプリのコンソール出力やログに情報が出る("Flush driver"の行)ので、それを使った。しかし、起動時の再生位置の反映は無理だった。そうでなくても、どうしても1-2秒の微妙なズレが出て、気分が悪い。そればかりか、この対処を入れたら、アプリどころかシステムまで不安定になってしまった。ウインドウシステムが不意に落ちてしてしまうのだ。ログを読むのにFIFOを使ったのが良くなかったのだろうか?

さすがに観念して、Web APIを使うことにして、調べた。やっぱり、認証(OAuth)が面倒だった。資料の書き方が今一つ分かりにくいのか(例えば、認証の方式が3つもある)、僕が慣れていないだけなのか、最初はどうすればいいかさっぱり分からなかったが、試行錯誤するうちに分かってきた。

確かに、Spotifyアプリの再生位置は、Web APIの"Get Information About The User's Current Playback"で取得できる。APIを使うこと自体は簡単なのだが、認証が大変だった。"Authorization Guide"を読んで、途方に暮れた。。。 が、ここで引き下がる訳にも行かないので、何とかした。もちろん、APIを使うための既存のプログラムもいくつかあるのだが、この認証が特殊なために簡単には使えなそうだったので、自分で作った。

何が特殊かというと、「古き良き」パスワードが全く使えないのだ。Spotifyにアクセスするアプリを最初に使う時は、必ず、ブラウザでSpotifyのサーバで認証(ログインやアプリのアクセスの許可)をしなければ、アクセスするための情報(トークン)が取得できないのだ。Googleのアプリパスワードような逃げ道すらない。ユーザにとっては安全でありがたいのだが、こっちの身にもなって欲しいw

ブラウザを使うこと以外に、Spotifyでの認証後に、指定したサーバにリダイレクトされる(ページがジャンプする)ので、それも何とかしなければならない。なぜかというと、そのページのURLにAPIアクセスのためのトークン(正確にはトークンを得るための情報)が入っているので、アプリはそれを取得しなくてはならないのだ。アプリを動かすのにサーバも要るのかって話で、全くやれやれだった。

更に試行錯誤するうちに、以下のことが分かった。

  • リダイレクトはPC内でローカルに済ませられる(Spotify社からアクセスされる訳ではない)ので、サーバは外部になくてもいい("localhost"は駄目なようだが、正しいドメイン名があればいいようだ)。
  • リダイレクト先のページの内容は何でもいい。ブラウザに表示されるが、(Spotifyの人でなく)自分が見るので、綺麗でなくても良く、空白だっていい。アプリがそのURLが取得できればいい。
  • そのため、リダイレクト先のページを出すサーバは、まともなwebサーバである必要はない。リダイレクト先のURLを取得できればいい。

それで、以下のように実現した。

  • リダイレクト先のURLは、自分のドメインに架空のサブドメインを付けたものにする。(例: dummy.piulento.net)
  • その架空サーバのIPアドレスは、ドメインに関係なく、宅内LANのローカルなアドレスになるようにPCに設定する(この前の宅内サーバの経験が役だった)。
  • ページを出すサーバは、認証をする時だけsocatというコマンドででっち上げる。ブラウザがトークンを含んだURLを要求して(送って)来るので、それを読んでアプリに渡し、ブラウザには、適当な応答(例: "HTTP/1.1 200 OK"と「認証に成功した」っていうメッセージ)を返す(この程度ならPHP自体でもできるが、最初から作るのも面倒なので、socatを使った。なお、ncコマンドも使えるが、ブラウザに表示できないので見苦しい)。
  • 一度認証を通せば、あとはそのトークンの有効期限が切れる頃に更新用情報を使って更新できる(この時はブラウザ不要)ので、そのための情報を保存しておく。
  • また、APIへのアクセスにはアプリ自体の認証情報(あらかじめ、Spotifyのサイトで作っておく)も必要なので、ファイルに保存しておく。
  • この処理は、本体とは別のプログラムで実現した。そのプログラムは、従来の再生情報取得処理が作るのと同じ形式(ローカルhttpでアプリから取得した情報の形式)の情報ファイルを作成するようにして、本体の変更がなるべく少なくなるようにした。

おそらく、上を読んだ方の99.9%は理解できないと思う。そんな、死ぬほど面倒なSpotifyの(OAuthの)認証ではあったが、そこを突破したら、あとはスルッと動いた。そして、結果は以下のとおりで、見た目は何も変わらないが、以前のように再生位置が表示できている。

Spotifyの仕様変更(廃止)に対処して、再び再生位置を表示できるようにした。

なお、今回作った再生情報取得プログラムは、bashでなくPHPで作った。さすがに、あの七面倒な認証をbashでやれるとは思えなかったので、テストプログラムを作る時からPHPにした。PHPにしたら、すごく作りやすかった。追って本体も書き換え(作り直し)たいが、現状の動作に大きな問題がある訳ではないので、あまりやる気が出ないw

ついでに、Web APIでは再生位置をジャンプさせることも可能なので、それを利用して、Dbusではできなかった再生停止機能(全く普通の「停止」です)も実現した。一時停止の後に曲の先頭にジャンプするだけだが、昔から欲しかったので気分がいい。

SpotifyのWeb APIにはいろいろ機能があるので、暇つぶしに遊ぶのには良さそうだ。ただ、以前も書いたように、Thumbs up/downする機能がないなど、どうも詰めが甘い感じで、そこがちょっと残念ではある。でも、GoogleやAmazonなんて、APIを公開してすらいないから、千倍はまともだと言えようw

あと、問題だと思っているのは、アプリに固有の認証情報が要るため、アプリを配布する時にはその情報が外部に取り出せないようにしなければならないが、それは至難の技なので、アプリ流通の妨げになるのではないかということだ。例えば、インストール時にブラウザでユーザに登録してもらうとかがいいのか? それもかなり面倒だが、Electronのような、ブラウザをアプリ化する仕組みなら、ユーザー登録処理に統合できそうだ。あとは、やはりアプリとブラウザが混ざっている状態を使って、アプリのインストール時にバックグラウンドで勝手に登録してしまうとかか(これは禁止されそうだが・・・)。

Spotifyだけ特別なことをしている訳ではないが、やっぱり面倒だ。

 

PS. ふと思ったが、アプリの認証情報をどうやって隠すかという問題は、アプリを配布しなければいいのだろう。Web APIはブラウザなどで動くアプリでの利用を主な対象にしているのではないか。今はそういうのが当たり前だし。ただ、僕のようにちょっと作ってみた人が配布しようとすると、かなり大変だ。

PS2. Spotifyアプリの再生状態取得APIにはどうしても気に入らない点がある。どうして、同じコンピュータの中で動いているSpotifyアプリの状態を知るのに、数千kmも先にあるであろう、Spotifyのサーバにアクセスする必要があるのだろうか?? 1回だけならまだ許せるが、再生位置をリアルタイムで知ろうとすれば、少なくとも毎秒アクセスしなくてはならない。

データ量は微々たるものだが、情報取得のために、毎回、(通信プログラムを起動して、)サーバに接続しなおすなんてオーバヘッドが大きくて、センスが悪過ぎる。しかも、アプリも状態をリアルタイムにサーバに送っているのだろうから、2倍の距離を行き来している。確かに、今は回線や機器が高速だから効率の悪さに気付くことはないが(逆に、これでまともに使えているのが不思議なくらいだ)、本質的にひどい仕様だと思う。廃止されたローカルなhttpの方がずっと良かった。この点は大いに文句を言いたい。 (21:38)

気になったので少し調べたら、Spotify自体も再生位置(時間)は「誤魔化し方式」を採用しているようだ。というのは、SpotifyアプリからSpotifyサーバへの通信が頻繁でなく間欠的だからだ(再生開始時に大量にアクセスがあるが、その後は時々ちょっと通信する程度)。もし、リアルタイムに現在の状態(再生位置など)を送信しているなら、間欠的ではおかしい。確かに、一時停止や再開した時にその情報を送信していれば、再生位置はサーバ側で適宜計算(推測)できる。

ただし、再生中に通信が途絶えたら、サーバに状態を送信できないので、再生位置はおかしくなるだろう。だが、Spotifyは基本的に、ネットに接続された状態(オンライン)での再生を前提としているので大きな問題はない。けれど、オフラインでローカルに保存された曲を再生する時は状態が送信できないから、再生位置を取得できなさそうだ。が、今はオフラインのことは考えていないから問題ない。

そうすると、最初に諦めた「誤魔化し方式」も全く駄目ではなかったようで、改良すればNW効率を改善できそうだ。具体的には、Web APIと併用すれば、問題点(起動時の位置が0でない場合)が克服できそうだ。ただ、再生位置をジャンプさせたことの検出はできるだろうか? いつものようにしつこいが、考えるのはおもしろい。 (7/25 5:55)

ちなみにSpotifyのwebプレーヤーも誤魔化し方式で、アプリでのジャンプや一時停止など、再生状態の同期には対応していない。意外にザルだったw (7/25 6:02)

上に書いたように、誤魔化し方式の改良版を実装した。再生開始時や定期的(10秒ごと)にWeb APIを使って再生位置を取得し、その後は1秒ずつ再生位置を加算していく。また、再生位置をジャンプさせた時には、再生開始時と同様にDbusにメッセージが来るので、それを契機にWeb APIでSpotifyサーバから再生位置を取得して修正する。

これにより、Spotifyサーバと通信する頻度を約1/10に減らすことができた。なお、理論的には定期的な再生位置の調整は不要なのだが、実際には誤差が蓄積して、本当の再生位置からずれることがあるので、した方がいい感じだ。ただ、Web APIで取得できる再生位置も本当に正しい保証がないので、余り意味がないのかもしれない。 (11:25) → 誤差の蓄積と思ったのはバグだったようで、定期的な再生位置の調整が不要になって、Spotifyサーバとの通信を最小限にできた。 (7/26 13:08)

  •   0
  •   0