MisskeyでListenBrainzなどを使ってなうぷれする

created_at

Misskeyでなうぷれがしたい!そういう時に何を使えばいいでしょうか?

よく、メディアの再生状態を取得して、なうぷれ用のテキストを生成してくれるアプリとかあると思うんですが、わざわざそれを開いて貼り付けてっていうのは少し面倒です。

今回はListenBrainzのAPIなどを使って、そこそこな感じでMisskeyになうぷれを投稿しようという話です。

ListenBrainz とは

再生した曲の履歴を記録しておくことができるサービスです。メタデータはMusicBrainzから取得していたりするので、有志が登録した豊富なメタデータの中から自分が聴いている曲の情報を良い感じに取得してくれます。また、OSSかつセルフホストで動かすことができるのが魅力ですね。

ちなみに似たサービスでLast.fmというのがあり、もともと自分はそれを使っていたのですが、タイムライン上でこういうのもあるよと教えてもらって使い始めました。Last.fmもListenBrainzもそこまで大きな差はないですが、ListenBrainz側がLast.fmの互換APIを持っていたりします。

https://listenbrainz.readthedocs.io/en/latest/users/api/core.html#get--1-user-(mb_username-user_name)-playing-now

ListenBrainzに再生ステータスを投げる(Scrobble)

再生している曲情報を取得する前に、まず何を聴いているのかListenBrainzに投げなくてはなりません。

方法はいろいろあるのですが、自分はWindowsとAndroidの端末でよく音楽を聴くので、ブラウザ拡張のWeb ScrobblerPano Scrobblerというアプリを使っています。

ListenBrainzの連携機能で各種サービスと連携する機能があるのですが、基本的にListenBrainz内で再生するときにそのサービスと再生状態を共有したりできる機能なので少し違います。また、Spotifyの連携機能で再生履歴を取得してくれる機能があるのですが、リアルタイムではないので今回のユースケースには合いませんでした。

ただ、Pano Scrobblerに関してはURLまで送っていないようなので、投稿内容にURLも含めたい場合、既存のものを使うのであればWeb Scrobblerが良いと思います。(PCのブラウザ限定になってしまいますが...)

APIのドキュメントを読んで、自前でどうにかしていくのもありかもしれません。下記リンク先に、どうやってScrobbleするかの選択肢が載っているので良かったら参考にしてください。

https://listenbrainz.org/add-data/

ListenBrainzから再生中の楽曲情報を取得する

端末から再生情報を投げることができるようになったら、APIのエンドポイントを叩いて情報を取得してみます。エンドポイントは /1/user/(mb_username: user_name)/playing-now です。特にトークンがなくても取得できるのでとりあえず自分のユーザー名を入れてリクエストしてみます。

あ、ちなみにURLは https://api.listenbrainz.org です。

{
  "payload": {
    "count": 1,
    "listens": [
      {
        "playing_now": true,
        "track_metadata": {
          "additional_info": {
            "duration": 120,
            "music_service_name": "SoundCloud",
            "origin_url": "https://soundcloud.com/undinesoundworks/fugue-vgen-october-2025",
            "submission_client": "Web Scrobbler",
            "submission_client_version": "3.18.0"
          },
          "artist_name": "Undine Soundworks",
          "track_name": "Fugue"
        }
      }
    ],
    "playing_now": true,
    "user_id": "snosph"
  }
}

叩くとこんな感じで返ってくるので、ここから必要な情報を抜き出してMisskeyで扱えるようにします。 今回はCloudflareのWorkersでAPIを定期的に叩いて取得するようにしました。

Misskeyに投稿する

データが取得できるようなったらMisskeyへどうやって投稿するかを考えないといけないのですが、どうすればいいのか少し迷いました。

というのも、投稿したい曲だけを投稿できるようにするには何かしらのUIが必要なります。そこで、Misskeyのウィジェットでのなうぷれ運用例がMisskeyのフォークにあるようだったので、自分もそれを参考にウィジェットでUIを用意するようにしてみました。

Misskeyのプラグインやウィジェットは、AiScriptという言語を用いて実装します。また、Misskeyではそれの拡張機能が提供されているのですが、残念ながら外部APIを叩くことができないんですよね。以前は Mk:apiExternal() という機能を呼び出せばできたらしいんですが、なんやかんやあって今はできないみたいですね。

今回は、Misskeyにある「ページ」機能を中継地点にして、APIから取得したものをページに書き込み、ウィジェットからはその中身を読み取るような感じにしてみました。この方法は下記の記事などで紹介されていました。

https://qiita.com/the_quick_fox/items/f765659d00f6eefe8b50

@renderView() {
  let pageData = Mk:api('pages/show', {
    pageId: 'YOUR_PAGE_ID'
  })

  let postText = pageData.content[0].text

  Ui:render([
    Ui:C:container({
      children: [
        Ui:C:text({ text: postText }),
        Ui:C:postFormButton({
          text: '投稿する'
          rounded: true
          primary: true
          form: {
            text: `{postText} #nowplaying`
          }
        }),
        Ui:C:button({
          text: "再取得",
          onClick: @() {
            renderView()
          }
        })
      ],
      align: 'center'
      padding: 1
      rounded: true
      borderRadius: 1
      hidden: false
    })
  ])
}

@main() {
  renderView()
}

main()

こんな感じのコードをウィジェットに追加して使ってます。このコードだと取得したテキストをそのまま投稿しているだけだし、再取得のたびにすべて再描画してるのが若干気になるので、また直せそうなら直したいですね。

最後に

定期的な取得とMisskeyのページへの書き込みはCloudflare Workersで動かしています。一応参考程度にリポジトリのリンクを置いておきます。

https://github.com/prismistim/nowplaying-gorilla

この機能、Misskeyのフォークの機能として実装されているものもあり、今回少し参考にさせてもらいました!標準的な機能として利用できるのであれば体験はだいぶ良さそうですね!

https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/packages/frontend/src/pages/user/index.listenbrainz.vue

https://github.com/lqvp/misskey-tempura/blob/develop/packages/frontend/src/widgets/WidgetListenBrainz.vue