Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

WEB 面接の裏側

株式会社メドレーのエンジニアの笹塚です。
私が開発を担当しているジョブメドレーで、先月10月23日に WEB 面接・動画選考をリリースしました。

job-medley.com
WEB 面接、動画選考ともに、昨今の非対面での就職活動ニーズに応えるべく開発しました。

リリースは2つの機能を同時ですが、今回は WEB 面接の裏側に絞ってご紹介します。

WEB 面接概要

WEB 面接とは、リアルタイムで事業者様と求職者様が、オンライン面接を行うことができる機能です。
専用のアプリケーションは必要なく、PC、スマートフォンのブラウザから利用できます。

f:id:medley_inc:20201126143843p:plain


サービス選定

開発にあたり、いくつかの候補があがりましたが、最終的には自社内でも導入実績のある SkyWay を使用することにしました。

SkyWay とは

WebRTC(Web Real Time Communication)を使用したオンラインのビデオ通話を、サービスに導入できるマルチプラットフォーム SDK です。

2020年11月時点で、JavaScript SDKiOS SDKAndroid SDK が提供されています。

  • シグナリングサーバなどの WebRTC に必要となるインフラ構築が不要です
  • 使用上限つきの無料プランもあります
  • NTT コミュニケーションズが開発しています

webrtc.ecl.ntt.com

WEB 面接の対応ブラウザバージョン(2020年11月時点)

PC: Google Chrome

バージョン84以上

PC: Microsoft Edge

バージョン84以上

iOS: Safari

iOS12 以上

Android: Google Chrome

バージョン85以上
Andoid9 以上

 SkyWay  JavaScript SDK の動作確認ブラウザ、WebRTC の対応状況、利用者の利用傾向から対応ブラウザのバージョンを上記のように設定しました。

webrtc.ecl.ntt.com

SkyWay の接続モデル

SkyWay でビデオ通話を実装する場合、2種類の接続モデルから選びます。

SkyWay 電話モデル

  • 電話のように1対1でのビデオ通話を想定したモデルです。
  • Peer インスタンス(シグナリングサーバによって発行された一意の PeerID を持つ)同士で接続します。
  • 接続するためには、相手の PeerID が必要になります。

SkyWay ルームモデル

  • 同一ルーム内の全ての Peer でビデオ通話するモデルです。
  • ルーム名を使用して参加します。相手の PeerID を知る必要はありません。
  • ルーム名は API キー毎に独立しています。
  • ルームの接続タイプはフルメッシュか SFU の2種類から選べます。
  • 参加者全員へのチャットなどのデータ送信もできます。

ジョブメドレーの WEB 面接では、 今後の機能拡張を想定して、こちらのルームモデルを採用しました。

ルームの通信タイプ

ルームに複数人が参加している場合、それぞれの通信をどう行うかを、メッシュと SFU から選ぶことができます。

フルメッシュ

f:id:medley_inc:20201126180010p:plain

画像引用元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90

全員が相互に通信を行います。人数が増えると、人数分端末のエンコード負荷と通信量が増加します。

SFU

SFU の場合、上りの接続は1本になるので、メッシュよりも端末のエンコード負荷や、通信量の軽減が期待できます。

f:id:medley_inc:20201126180029p:plain

画像引用元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90

通信方式の違いは SkyWay が隠蔽してくれるので、joinRoom 時の mode を mesh から sfu に変更するだけで切り替わります。

peer.joinRoom(roomName, { mode: 'mesh か sfu を指定', stream: mediaStream });

webrtc.ecl.ntt.com
ジョブメドレーの WEB 面接では、面接参加人数を考慮して mesh を使用しています。

実装イメージ

const peer = new Peer(peer_id, {

  key: api_key

});

peer.once('open', () => {

  room.once('open', () => {

    // ルーム参加後に発生するイベント

  });

  room.on('peerJoin', (peerId: string) => {

    // ルームに誰か参加した場合に発生するイベント

  });

  room.on('stream', (stream: RoomStream) => {

    // stream を受けた場合に発生するイベント

  });

  room.on('data', ({ src, data }) => {

   // data を受けた場合に発生するイベント

  });

});

peer.on('error', (error: Error) => {

 // エラー発生時に発生するイベント

});

peer.joinRoom(roomName, { mode: 'mesh', stream: mediaStream });


room.close();

peer.disconnect();


Peer を作成し

  1. peer.joinRoom() でルームに参加

  2. room.stream イベントで他の参加者の stream を受け取る

  3. room.data() でチャットなど、データ送信もできる

  4. room.close() でルームから退出
が SkyWay の JavaScript SDK を使用した基本的な実装になります。

この実装に

  • navigator.mediaDevices.getUserMedia() で取得した stream を joinRoom で渡す
  • steam イベントで受け取った stream を video で再生する

を追加すれば、オンラインでのビデオ通話が可能になります。

スマートフォン対応

PC と同様のコードでほぼ動作しましたが、iOSAndroid 端末で、機種依存と思われる挙動の調査と対応に時間がかかりました。その一部を紹介します。

タブを移動すると映像が映らない

発生した問題
iOS12、iOS13 などで

  • 複数のタブをひらいた場合に、映像の取得ができなくなる
  • スクリーンロックからの復帰時に、映像が取得できなくなる

という問題が起きました。iOS14 ではタブ切り替え時に映像を取得できるようになっていましたが、スクリーンロックからの復帰時は映像を取得できないままでした。

対応

この対応は visibilitychange イベントで、タブの切り替えと、スクリーンロックからの復帰時のイベントを拾い

  1. 取得済の stream の track を stopする
  2. stream を取り直す
  3. SkyWay の room.replaceStream() で、WebRTC で使用している stream を差し替える

以上の実装により、対応しました。

document.addEventListener('visibilitychange', async () => {

  if (document.visibilityState !== 'visible') {

    return;

   }

   localMedia.getTracks().forEach((track: MediaStreamTrack) => {

     track.stop();

   });

   const replaceStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })

     room.replaceStream(replaceStream);

   }

});

イヤホンの操作で映像が止まる

発生した問題 

iOS12、iOS13 では起こりませんでしたが、iOS14 でオンライン面接途中にイヤホンをスマートフォンから外すと、相手側の映像が止まるようになりました。

対応

それまでは、相手の映像と音声を再生するために、video タグに stream を渡して映像と音声を再生していましたが


video : mute にして映像を再生
audio : 音声を再生


と、音声と再生を分けたところ、イヤホンを外しても停止することはなくなりました。

制約設定

getUserMediaで取得する MediaStream は、制約を設定することでデバイスの消費リソースを抑えることができます。

設定例:
navigator.mediaDevices.getUserMedia({ audio: true, video: true });

navigator.mediaDevices.getUserMedia({ audio: true, video: { frameRate: 15 } }); 
制約が設定可能かどうかの確認:
const supportedConstraints = navigator.mediaDevices.getSupportedConstraints();

getSupportedConstraints() で、対応している制約名を取得することができます。

使用しているブラウザがその制約に対応しているかを確認し、対応している場合のみ設定を有効にします。

例えば、スマートフォンの場合に以下の設定をすれば、インカメラを使用し、フレームレートを20に抑え、320x320の解像度に制限することができます。

{ facingMode: 'user', frameRate: 20, width: 320, height: 320 }

指定した制限が必ず使用される保証はなく、機種依存の影響を受ける設定でもあるので、対象としている環境にあわせて検証と調整をする必要がある点には注意が必要です。

動作検証中に、機種依存と思われる挙動をした例を紹介します。

frameRate

指定すると一部 Android 端末で以下の挙動をした。
1. Android 端末で面接に参加する
2. iOS Safari で参加する
3. Android 側の映像と音声が Safari に送られない
Safari で先に参加する場合には問題がない。

解像度指定

例: width: 320, height: 320
frameRate だけ指定していたときに上記の挙動をした Android、iOS Safari の組み合わせで問題が起こらなくなった。

解像度を指定するとインカメラではなく、リアカメラを使う Android 端末があった。

制約設定については、現在も調整中です。

参考情報

SkyWay Conference

conf.webrtc.ecl.ntt.com

github.com
SkyWay のルーム機能を使用したデモ環境です。
GitHub にコードも公開されているので、ルーム を使用した場合の挙動と実装方法を確認できます。
開発をしていると、実装の問題なのか、SkyWay の SDK の仕様なのか、特定のデバイスで起こる問題なのかの切り分けに時間がかかるため、こちらの環境が参考になりました。

まとめ

SkyWay が WebRTC とグループでのビデオ通話の実装を統合して提供してくれるため、開発時は、自社サービスとしての WEB 面接の機能に集中することができました。

スマートフォンのブラウザ対応と調査に時間がかかることもありますが、今後も利用者からのフィードバックを得ながら改善していきたいと思います。

メドレーでは、ニーズにあわせた新機能の開発にも力を入れています。多くの利用者に実際に使われるサービスの開発をしてみたいと思った方、ぜひお気軽にお話しましょう!

www.medley.jp