Log

いろいろ

iOSのショートカットを利用してYoutube Musicのなうぷれをツイートする

なうぷれに曲名とアーティスト名を含めたいので、いろいろと調べた&試した作業ログです。

Youtbe Musicの普通の共有だとこんな感じ。

f:id:mtzml:20210313152101g:plain

ショートカットでなうぷれを作ってこうなった。

f:id:mtzml:20210313152005g:plain

ビミョー。だけど過程は楽しめた。

ショートカットについて

support.apple.com

ショートカットは、Appでの1つまたは複数の作業をすばやく完了するための機能です。「ショートカット」Appでは、複数の手順を組み合わせた独自のショートカットを作成できます。たとえば、海の波情報を取り込み、ビーチまでの所要時間をチェックし、サーフミュージックのプレイリストを再生する、という「サーフタイム」ショートカットを構築できます。

以下の形式でアクションを組み合わせて処理を作成する。図の左側にあるとおり、変数や制御フローは用意されているため、いろいろなことができる。

f:id:mtzml:20210313152640j:plain
作成したショートカットは、アプリから直接実行する以外にも、様々な方法で呼び出すことができる。冒頭のGifのように「共有シート」から呼び出したり、「iPhoneの背面タップ」で呼び出したり。背面タップは便利そう。

また、アプリごとに固有のアクションが提供されているが、純正アプリは特にそれが豊富。上記のフローにあるように、Apple Musicであれば再生中の楽曲情報をアクション一つで取得できる。

そのアクションを利用すると、実用的ななうぷれを作ることができる。

f:id:mtzml:20210313152707g:plain
Youtube Musicでは、これを自分で試行錯誤して作成する必要がある。

Youtube Musicのなうぷれショートカット

全体像はこの通り。

f:id:mtzml:20210313152739j:plain

再生中の楽曲をどうやって取得するか

Apple Musicとは異なり、Youtube Musicでは現在再生されている楽曲の情報を取得できない。

共有シートからショートカットを呼び出すと、楽曲のURLを受け取ることができるため、これを利用して再生中の楽曲情報を利用する。

URLからどうやって曲名とアーティスト名を取得するか

URLはこんな感じの形式。クエリパラメータvの値XXXXXが楽曲のIDである。

https://music.youtube.com/watch?v=XXXXX&feature=shar

「URLの内容を取得」というアクションがあったので、これでHTMLを取得できそう。

と思ったら、そもそもYoutube MusicのWebアプリがAjaxで楽曲の情報を取得するため、このHTTPリクエストでは目的の情報が取得できないことが判明。

URLからどうやって曲名とアーティスト名を取得するか2

f:id:mtzml:20210313152933j:plain
すばらしいアクション。

余談だけど、スクレイピングで似たようなことをやったなあと思い返した。単純なcurlではJavaScriptが評価されないため、Seleniumを使ったりと。

さて、早速試してみたところ、SafariYoutube MusicのWebアプリを開くとこんなメッセージが。

「Chromeで開いてください」

Oh, no...Google...。仲良くしてください。*1

User-Agentをなりすませば突破できそうだけど、Safariの「URLを開く」アクションではHTTPヘッダが指定できずに断念。ちなみに「URLの内容を取得」アクションではヘッダの指定が可能。

URLからどうやって曲名とアーティスト名を取得するか3

f:id:mtzml:20210313153337j:plain

最強のアクション。

任意のシェルスクリプトを実行できるため、実質何でもできる(?)

サーバ上に、エラーを恐れないワイルドな実装でスクリプトを作成。

フロー

  • 引数に楽曲のURLを渡す
  • 非公式のYoutube Musicライブラリを使用して楽曲の情報を取得する
  • 結果をprintする(標準出力が次のアクションへ返却される仕様っぽい)

スクリプト

import urllib.parse
from ytmusicapi import YTMusic

url = sys.argv[1]
music_id = urllib.parse.parse_qs(urllib.parse.urlparse(url).query)['v']
ytmusic = YTMusic()
song_info = ytmusic.get_song(music_id)

title = song_info['title']
artist = song_info['artists'][0]

print(title + ' / ' + artist)                                      

最後にもう一度全体像。

f:id:mtzml:20210313152739j:plain

スクリプトを実行するのであれば、TwitterAPIを使用してツイートもサーバ上で行えるのですが、手元で内容を確認するためにあえてこのフローにしています。

おわりに

「URLからどうやって曲名とアーティスト名を取得するか」の辺りから、ショートカットに拘ってムキになってしまいました。

結果としては楽しめたのでOKです。文字に起こしてみたら、いろいろな技術を少しは学んできたのだなあと自分の成長を感じました。

*1:ただし執筆段階では再現せず。どんな深刻なバグよりも、再現性のないバグが一番困ったりするよね。