SpotifyのDaily Mixでは物足りないあなたへ送るサービス

# 背景

以下のQiitaの記事を読み、私もSpotify APIを使ってみたくなりました😃

- [Spotify Web APIで明るい楽曲のみのプレイリストを作成する](https://qiita.com/oekaki0v0/items/c8a7084b28f7943b70b2)

# Spotify-Extension-A
完成したサービスがこちらです。
`たった3step`で、あなただけのプレイリストが作成可能です😏

- https://spotify-extension.shijimi.work/

<blockquote class="twitter-tweet"><p lang="es" dir="ltr">demo <a href="https://t.co/05rj7TRLwq">pic.twitter.com/05rj7TRLwq</a></p>&mdash; playtag551 (@playtag551) <a href="https://twitter.com/playtag551/status/1364196708872114176?ref_src=twsrc%5Etfw">February 23, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 実装したかった機能

Spotifyは素晴らしいサービスです！！私も愛用しています😊
ただ、私が思うSpotifyのかゆい所、それは、

- `大好きなアーティストだけでプレイリストを作って欲しい♫`
- `アップテンポな曲ばかりでプレイリストを作って欲しい♫`

ということです。

Spotifyではユーザーにおすすめのプレイリストが自動的に作成されます。( Daily MixやDiscover Weekly ) これは、ユーザが過去に試聴したトラック情報を用いて作成されていると思われます。個人的な感想としては、`大好きな曲から、まぁまぁ好き、チャレンジ枠と曲が分散しているな`、といった印象です。好きな曲ばかりを聞きたい私としては、`探索的な効果`はあまり必要ではないのです。

ということで、前述した機能を実装しました。

# 動作フロー

上記のデモ動画の場合の、大まかな動作フローは以下の図のようになっています。

お気に入りのアーティストから、プレイリストを作る場合であれば、
最終的に対象となる曲数は`1,500程度`となります。（API制限に引っかからないうちであれば。）
そこから、ユーザが選択した曲調に応じたロジックを走らせて曲を厳選し、プレイリスト上限数(たぶん100)を超えるようであれば、`ランダムに80曲`を抽出するようにしています。

![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/b1b3df1f-5fd7-5e85-6287-18210ba40990.jpeg)


# 苦労した点

- 非同期処理
    - APIを叩きまくるので、非同期処理が必須でした。`Promise.all`を利用しているのですが、リクエストが一つでもエラーになると失敗判定になってしまいます。特に、API制限で結構エラーが出てしまうので、エラー時でも{}のレスポンスを返却して、成功しているように見せかけることで、処理が継続するようにしました。また、リクエストにはランダムに`sleep`を仕込んで負荷を分散させるようにしました。
- ランダム性を持たせる
    - 固定値でアーティストの曲を取得してしまうと、毎回同じ曲が候補として選ばれてしまいます。それではつまらないので、`offset`(何番目から取得するか)を`ランダム`にずらすようにしています。（ユーザのフォローしているアーティストを取得するAPIだけこのパラメータがない...）また、リクエストの順番もシャッフルすることで、アーティストが偏りづらくなるようにしています。（これは特に、リクエストエラーが多発する場合に効果を発揮します）
- ロジック
    - 初めは、`曲の重複排除`をidベースで行っていたのですが、マーケットの違いなのか、同じ曲でも違うidが与えられている場合が多かったです。現在は曲名&アーティスト名をkeyにして重複排除を行っています。また、ある曲の`なんとかバージョン`とか`Instrumental版`とかSpotifyだと多いので、正規表現で排除しています。（個人的好みです。）
    - 思ったより、`曲の特徴成分`が微妙だなっていうのがありました。結局、ロジックで利用しているのは`energy`, `tempo`, `valence`の3つだけです。(なんでワンパンマンのOPよりサイレントマジョリティーの方が`loudness`大きいのじゃ...)


```:サイレントマジョリティー(欅坂46)の曲特徴成分
acousticness: 0.261
danceability: 0.583
duration_ms: 265827
energy: 0.952
instrumentalness: 0
key: 1
liveness: 0.314
loudness: -2.491
mode: 1
speechiness: 0.0797
tempo: 123.015
time_signature: 4
valence: 0.81

# 各特徴について
https://www.wizard-notes.com/entry/music-analysis/spotify-api-audio-features
```

- UI
    - 今回の裏目標として、`1.typescriptを使う 2.scssを使う 3.UIを妥協しない`を設定していました。特にUIは妥協してしまいがちなんですよね。動くし...。よって、今回はiosでの見た目を優先しつつ、ios,web共に思い描いたクオリティに仕上げました。98点です!!（まだ、~~3点~~1点妥協している部分があるので、確認してみてください笑）特に拘ったのは、曲調選択エリアでして、なるべく直感的に、かつ、高機能な仕上がりとなっております。
![スクリーンショット 2021-02-24 12.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/f1f14b6d-9430-f70f-8da9-0b1bb2e7c7f8.png)


# github

一応、githubに置いておきます。
Spotify Developer トークンの作成・callbackエンドポイントの登録を行えば、
`docker-compose up`で動作します✨

- https://github.com/shoot16625/spotify_extension_a

```:repository
.
├── Dockerfile
├── README.md
├── docker-compose.yml
├── .env # spotify の developer tokenなどを記述するファイル（別途作成）
├── main
│   ├── index.ts # nodeのサーバー
│   └── public
│       ├── index.html
│       └── statics
│           ├── css
│           │   ├── common.css # scssをコンパイルしたもの
│           │   └── common.scss 
│           ├── img
│           └── js
│               └── common.js
├── package-lock.json
├── package.json # 必要なライブラリやコマンドを記述したもの
├── .prettierrc.json # フォーマット関連
├── .eslintrc.json # フォーマット関連
├── tsconfig.json # フォーマット関連
└── tslint.json # フォーマット関連
```

# 終わりに

まだまだ自作のプレイリストには勝てませんが、大好きなアーティストの知らない曲を発掘できていい感じです！！

`console.log()`をいくつか仕込んでいるので、chromeなどで挙動を確認してみると面白いと思います😁 この曲、tempo：0.3なのかよ！みたいな笑

※ちなみに、
> まだ、~~3点~~1点妥協している部分があるので、確認してみてください笑

の答えは

1. 初期状態で`range slider`の中央をクリックすると、ポップアップが一番左に出てしまう <- 初期の中央クリックがjqueryでchange判定されないため...
2. ~~`toggle button`がORの時のマークを`✔︎`ではなくて`||`にしたい <- かなりむずい~~
3. ~~アクセストークンが期限切れでもAPIのローディングマークが（永遠に）出てしまう。~~