Relaymを出展して技育展「Webアプリ」部門で優勝してきた

September 27, 2020

こんにちは

9/27 に技育展というイベントが行われました

「Web アプリ」部門でCAMPHOR-のメンバーと開発していた Relaym を出典していました。

技育展は「未来の技術者を育てる」ことを目的とし 自らのアウトプットを「展示」する学生向けテックカンファレンスです。 (公式サイトより)

Relaym | Spotify の楽曲を 1 つのスピーカーで楽しめる Web アプリ

そこでなんと最優秀賞を頂くことができました!!めちゃめちゃ嬉しい!!!ありがとうございます!!!!!!

この記事では発表したことに加えて、時間の都合で説明できなかった技術的に細かぁ〜い部分を紹介したいと思います。

解決したい課題

スライド

Relaym はそれぞれが聴きたい Spotify の楽曲を 1 つのスピーカーで楽しめる Web アプリケーションです。

スライド

Relaym は例えば上記のような課題を解決したいと思い開発されました。

ドライブ中に限らず、複数人での勉強会や鍋パ中など音楽を流している人に流したい人を頼まなければならない、もしくは Bluetooth を繋ぎ変えなければならないみたいな経験ありがちではないですか?

また、一人で作業している際、いつも同じプレイリストばかり使用してしまい、なかなか新しい曲に出会う機会がない、そう言ったときにも新しい曲を発掘したいという方もいませんか?

そんな中以下の考えのもと Relaym の開発に着手しました。

スライド

具体的に Relaym でできること

Relaym ではセッションという中心となる概念が存在していて、皆でセッションを共有して曲を追加していくような使用方法になります。

スライド

Relaym の使用はまず画像のようにセッションを作成するところから始まります。

スライド

セッションの作成後は左側のメニューバーからリンクを共有してセッションへの招待を行うことができます。

スライド

また、セッション作成時に他人からの操作を許可しないことで、上記のように「SNS 上に招待リンクを投稿し不特定多数の人から作業 BGM を募集する」といった使い方もできます。

スライド

セッションの作成後は、曲の検索/追加を行うことができます。

ここにはインクリメンタルサーチを採用しており、滑らかな検索体験を実現しています。

スライド

曲の追加後に再生を行うことができます。その他、曲の停止やスキップなどの操作を行うことができます。

もちろん再生後も随時曲の新規追加を行えます。

Relaym の設計/デザインに関して

スライド

Relaym は前述のように「複数人で曲を楽しんで欲しい」と言った思いから生まれているため、セッションのシェア/参加の気軽さという点を中心に設計が行われています。

  • Web アプリなのでインストール不要
  • Relaym にアカウントという概念がないためログイン/登録不要
  • 参加者に関しては Spotify アカウントすら不要

そのため本当に招待 URL にアクセスするだけでセッションに参加できます。

技術スタックの話

ここから少し技術の話に入っていきます。

スライド

技術スタックはこんな感じです。

Spotify Web API を選んだ理由としては

  • Spotify の豊富な楽曲を利用できる
  • Web アプリなのにバックグラウンドで利用できる

というところにあります。

参加者同士の情報の同期

Relaym では参加者同士の情報の同期を実現する必要がありました。

以下のように操作の内容が別の参加者の画面にすぐに反映されています。

同期の様子

これを実現するために Relaym ではWebSocket を用いたイベントの一斉送信を行っています

スライド

例えば再生開始が誰かの端末からリクエストされた際の流れを追ってみます

  1. API サーバーがリクエストを受ける
  2. SpotifyAPI を通し、Spotify 上で再生を実行
  3. API サーバーは WebSocket を通して全端末へ再生開始のイベントを送信

このように逐一サーバーからセッションへの操作の内容を全端末へ通知することで参加者同士の情報の同期を実現しています。

また、参加者同士の情報の同期が実現できたとしても Spotify との実際の再生内容とあっていなければ元も子もありません。

スライド

そのため、API サーバーは特定のタイミングでSpotify の再生状況の確認を行い、Relaym の想定している動作とずれていないかを確認しています。

これによって Spotify が Relaym の想定と異なる状況だった場合は同様に WebSocket を通して全端末に同期失敗のイベントを通知しています。

Relaym の再生状況を管理について

ここから発表で話せなかった少し細かい技術的な部分の紹介を行います。

僕がサーバーサイドの開発しか担当していなかった為、そちら中心の話になります

Relaym では前述のようにセッションの再生状況の管理を API サーバーで行っています。Go お得意の非同期処理で持っているわけですが、セッションのライフサイクルを追ってみましょう。

1. セッションが作成される

ソースコードでいうところのこの部分です。

この時点では DB 内に空のセッションが作成されるだけです。

2. セッションに曲が追加される

ソースコードでいうところのこの部分です。

曲の追加では DB と同時に Spotify 側のキューに曲の追加を行います。

3. 再生の開始

ソースコードでいうところのこの部分です。

再生の開始のタイミングでここではまず前述のようにSpotify APIを通して曲の再生開始がリクエストされます。その後非同期処理でのセッションの管理が始まります。

非同期処理内ではセッションごとに曲の終了の検知を行う Timerが作成されます。

再生開始時に再生される曲の時間分の長さの Timer が作成されます。

(厳密には SpotifyAPI の遅延を吸収する為に数秒足された時間の Timer がセットされます。)

4. 曲の終了

ソースコードでいうところのこの部分です。

先ほどセットした Timer の終了を検知して、次の曲への遷移の処理に移ります。

SpotifyAPI 側の処理の遅延の吸収のために

SpotifyAPI へのリクエストから実際に端末でリクエストの内容が動作するまでに少し時間がかかってしまいます。また、この遅延時間は利用者の端末の通信状況などでも変わってくる為、一定ではありません。

その為

  • 曲の再生が終了する
  • 次の曲の再生を Relaym からリクエストする

なんてことをやっていると利用者から見て、「曲の遷移が遅い」「曲が完全に終わっていないのに次の曲の再生が始まった」というふうな違和感が生じる原因となります。

この対策に Relaym ではSpotify 側に先に 2 曲先の曲まで積んでおくと言った処理を行っています。

具体的には

  • 「2. セッションに曲が追加される」内で、追加された曲が現在再生されている曲の 2 曲先以内であれば Spotify に積む
  • 曲が終了するたびに次の曲の 2 曲先に再生予定の物を Spotify 側に積む

と言った処理を行っています。

これによって曲の終了とともに Spotify 側で自動で次の曲の再生が実行される為、前述の問題が解決します。

エッジケースへの対応

Relaym は Spotify を利用するサービスである為、いくつか利用者の状況によって Relaym が正常に動作しないというケースがありました。

Spotify 側のキューに既に曲が積んである場合

前述のように Relaym は Spotify 側のキューを利用する為、Relaym の利用前に Spotify 側のキューに曲を積んでいた場合(具体的には Spotify の「次に聴く」の機能を使用した場合)に Relaym が次に流して欲しい曲とは別の曲が先に再生されてしまいます。

その為、Relaym では再生を開始する際にSpotify 側のキューをいったんリセットするという処理を行っています

「キューの曲をなくす」と言ったニッチな API は Spotify 側から提供されていなかった為、SkipAPI を利用して無理やり実装を行いました。

  • 曲の Skip の API を叩く
  • 曲の再生状況を取得し、再生状況が STOP になっていた場合キューに曲がなくなったとみなす

これを繰り返すことによって Spotify 側のキューのリセットを実現しています。

また、先ほど「Spotify 側に先に2 曲先の曲まで積んでおく」というのがありましたが、ここで全ての曲ではなく 2 曲先までのみを追加としている理由はキューの曲の全 Skip に時間がかかるためです。

Spotify で何かしらの曲を再生していないと Spotify 側で検知できない

開発中に最も苦しめられた問題です。

Spotify で何かしらの曲を再生していない場合、SpotifyAPI から「Active Device」として認識できず、その端末での再生が開始できません。

その対策のために Relaym では再生時に Active Device not found が発生した際に Spotify で何かしらの曲を再生してもらうという手法をとっています

スライド

このダイアログを出すことで利用者に先に Spotify で再生を行ってもらい、利用者が Spotify から戻ってきた際に Relaym の再生がスタートするという設計にしています。

終わりに

技育展での発表の内容、また発表で伝えられなかった具体的な Relaym の動作について紹介しました。

Relaym はサーバーサイド、フロントエンド両方が OSS として公開されています。あなたの contribution をお待ちしています!!!!

camphor-/relaym-server - GitHub camphor-/relaym-client - GitHub

また、関西近郊の学生の方はぜひ CAMPHOR- HOUSE に一度きてみてくださいね…👀👀

CAMPHOR- —京都の IT 系学生コミュニティ—

このエントリーをはてなブックマークに追加