TECH PLAY

株匏䌚瀟メドレヌ

株匏䌚瀟メドレヌ の技術ブログ

å…š1406ä»¶

はじめに はじめたしお、メドレヌ新卒入瀟 2 幎目の森川です。 むンフラ経隓がただ 4 ヶ月ほどの未熟者ですが、 AWS 認定資栌クラりドプラクティショナヌ の詊隓に合栌するこずができたした。䞊䜍の資栌取埗に向けお今埌も勉匷しおいきたす。 先日私が担圓させおいただいた CloudFront のアラヌト改善に぀いお、問題の原因ず察応方法を本蚘事で曞かせおいただきたす。 よろしければお付き合いください。 背景ず問題 匊瀟が運営しおいるプロダクトの䞀぀ ゞョブメドレヌ ではむンフラ環境に AWS を利甚しおいたす。 監芖には CloudWatch や Datadog などを䜿甚しおいたす。サヌビスの異垞を怜知するための蚭定のひず぀に、CloudFront の゚ラヌレスポンス増加を怜知するためのアラヌト通知がありたす。 CloudFront が返すレスポンスのうち、特定の時間範囲の䞭で 4xx, 5xx 系の゚ラヌを返した割合が閟倀を超過したこずを怜知しお、CloudWatch アラヌムから Lambda を通しお Slack に通知を行っおいたす。 ずころが、ある頃を境に CloudFront での 4xx 系゚ラヌレスポンスの発生割合が増加し、アラヌトの通知頻床が想定以䞊に高くなっおしたいたした。 原因 調査を行ったずころ、刷新した瀟内システムにお以䞋 2 ぀の原因でアラヌトが発生しおいるこずが分かりたした。 原因 1. 瀟倖サヌビスからのアクセスでアラヌトが発生 CloudFront のログを確認したずころ、瀟倖サヌビスSlack, Google スプレッドシヌトなどからのアクセスに察しおステヌタスコヌド 403 を返しおいるレスポンスログが数倚く蚘録されおいたした。 これらのサヌビスに匊瀟の瀟内管理システムの URL がポストされるず、プレビュヌを衚瀺するためのリク゚ストが送信されたすが、この時のリク゚ストが瀟倖からのアクセスずしお WAF で制限されおいたした。 むンフラ刷新前から珟圚たで皌働しおいる CloudFront のログも確認したずころ、こちらでも同様の゚ラヌレスポンスが発生しおいるこずが分かりたした。しかし、゚ラヌ割合増加のアラヌトが頻発するこずは珟圚でもほずんどありたせん。 以前はゞョブメドレヌが持぀システム党䜓ぞのアクセスをひず぀の CloudFront で凊理しおいたため、アラヌト通知の割合ずしお蚈算する際の母数が倧きく、瀟倖からのアクセスによる゚ラヌが発生しおいおも、その割合が閟倀を超過するこずが少なかったからだず考えられたす。 むンフラ構成を刷新したこずをきっかけに、これたで目立っおいなかった瀟倖からのアクセスずいう問題が衚面化しおきたのです。 原因 2. 利甚者が少ない時間に゚ラヌレヌトが高くなりアラヌトが発生 CloudWatch アラヌムでは、䞀定期間内でのレスポンスのうち、4xx, 5xx 系の゚ラヌごずにその割合が閟倀を超過したこずを怜知しおアラヌトを発生させる蚭定ずしおいたした。 しかし、深倜など利甚者が少ない時間に䞀床でも゚ラヌが発生するず、その割合が跳ね䞊がっおしたうこずでアラヌト発生頻床が増加し、誀怜知ず蚀える状態になっおいたした。 以䞋の画像では、4xx 系゚ラヌの割合が倜間に 100%ずなっおいる箇所が確認できたす。衚瀺時間は UTC です 察応方法 2 ぀の原因に察し、それぞれ察応を行いたした。 察応 1. 特定の瀟倖サヌビスからのアクセスを゚ラヌ怜知の察象倖ずする 各サヌビスの蚭定により、プレビュヌ衚瀺によるアクセスを停止させる遞択肢が考えられたす。しかし、該圓するサヌビスすべおに蚭定を行うのは難しく、管理も耇雑になりそうです。 そこで、特定の瀟倖サヌビスからのアクセスを ゚ラヌ怜知の察象倖ずする 方針で察応を行いたした。 ログのすべおを CloudWatch アラヌムの評䟡察象ずしおいたために、誀怜知ず蚀えるアラヌトが発生しおいるのが珟状です。したがっお、評䟡させたいログだけに絞り CloudWatch で評䟡させるこずができれば解決が図れたす。今回であれば、特定のナヌザヌ゚ヌゞェントや IP アドレスなどを陀倖しお CloudWatch に枡すずいう凊理が求められたす。 その実珟のため、今回新たに䜜成したのが Lambda の関数です。 S3 に CloudFront のログが保存されたこずをトリガヌに Lambda を起動させるように蚭定したした。 ログごずに蚘録されおいるリク゚スト元のナヌザヌ゚ヌゞェントや IP アドレスなどを確認し、陀倖察象かどうかを刀定したす。 そうしお遞別を通過したログを今床はステヌタスコヌドの 5 ぀のクラス1xx, 2xx, 3xx, 4xx, 5xx 系ごずに振り分けたす。 ただし、CloudFront ではステヌタスコヌドに 000 が入るこずがありたす。 https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html ステヌタスコヌド 000 はアラヌトで怜知したずころで察応できるこずが特にないため、怜知察象から陀倖する方針ずしたした。 S3 のログを盎接確認するず 000 なのですが、Athena でログを確認するず 0 で衚瀺されるため、少しハマりたした こういった意図しない倀がステヌタスコヌドに含たれおいた堎合などを怜知できるようにするため、5 ぀のクラス以倖の倀が含たれおいた堎合に UNKNOWN_STATUS_CODE なクラスずしお分類するようにしたした。 必芁なものに絞ったログを 6 ぀のステヌタスパタヌンに分け、それぞれの件数を CloudWatch メトリクスぞ PUT させたす。 ここたでが Lambda の仕事ずなりたす。 各ステヌタスのログの件数を CloudWatch メトリクスで確認できるようになったので、レスポンス党䜓における 4xx, 5xx 系゚ラヌの割合が算出できたす。これを元に閟倀を蚭定し、以前のようなアラヌトを䜜成するこずができたした。 察応 2. CloudWatch アラヌムの怜知ルヌルを調敎する 利甚者が少ない時間に゚ラヌレヌトが高くなりアラヌトが発生する件に぀いおは、 CloudWatch アラヌムの怜知ルヌルを調敎 するこずによっお察応したした。 䞀定期間での゚ラヌ数に閟倀を定め、超過した際にアラヌトを通知するように倉曎したした。぀たり、割合ではなく絶察数で刀断させるようにしおいたす。 以䞋の画像の緑色のグラフが新たな怜知ルヌルで参照するものずなりたす。橙色で瀺しおいるのが 4xx 系゚ラヌの割合ですが、これが 100%ずなっおいる箇所においおも新たな怜知ルヌルには反応しおいないこずが分かりたす。 察応を終えお Lambda を甚いた集蚈凊理の䜜成ず、アラヌトの怜知ルヌルの調敎を行うこずで、CloudFront の゚ラヌ監芖粟床を向䞊させるこずができたした。 以前は頻繁にアラヌトがあがっおいたしたが、察応埌はすっかり萜ち着きを芋せおいたす。 システムの安定皌働を実珟するためにも、適切にアラヌトを怜知できるように今埌も改善を図っおいきたいず思いたす。 今回の課題に察する解決手段ずしおはシンプルな察応であったかずは思いたすが、私には実りの倚い玆䜙曲折な経隓ずなりたした。 AWS の基本的なサヌビスの連携を孊ぶこずができたこずに加え、新たに䜜成する AWS のサヌビスの課金額の詊算や、実行蚈画を定めおからの実装など事前準備を意識しお取り組むこずができたした。恵たれた環境の䞭、日々孊ばせおいただいおおりたす。 さいごに メドレヌでは「医療ヘルスケアの未来を぀くる」ずいうミッションを掲げ、各プロダクトの開発・運営が進められおいたす。 ゚ンゞニア・デザむナヌをはじめ倚くのポゞションで新たなメンバヌを募集しおいたす。ご興味をお持ちいただけた方は、ぜひお気軜にお話しさせおいただければず思いたす ここたでお付き合いいただき、ありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 https://www.medley.jp/jobs/
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは、第䞀開発グルヌプの矢野です。ゞョブメドレヌ開発゚ンゞニアずしお、䞻にバック゚ンドを担圓しおいたす。 盎近では、ゞョブメドレヌが先月リリヌスした 「動画遞考」 機胜の開発プロゞェクトに携わっおおり、動画ファむルのアップロヌド配信環境の蚭蚈・実装を行っおいたした。 今回のブログでは、この「動画遞考」機胜の開発に利甚した AWS Elemental MediaConvert サヌビスず、 hls.js ずいう OSS ラむブラリに぀いお玹介したいず思いたす。 ゞョブメドレヌの「動画遞考」機胜 はじめに、今回リリヌスした「動画遞考」機胜に぀いお抂芁を玹介したす。 新型コロナりむルス感染拡倧によっお、察面での面接に䞍安を感じたり、公共亀通機関の利甚が難しくなったりするこずにより、満足な転職掻動ができなくなっおいる方もいらっしゃるかず思いたす。 このような課題を解決するために、ゞョブメドレヌではリアルタむムにオンラむンで面接を行う「WEB 面接」ず、事業者があらかじめ蚭定した質問に察しお応募者が動画で回答を送る「動画遞考」の 2 ぀の機胜を提䟛開始いたしたした。 ref. WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画遞考動画面接は、近幎増加傟向にあるオンラむン遞考の䞀皮です。䞀般的に、求職者 / 就掻生が PC ・スマヌトフォン等のカメラで、予め甚意された蚭問に応じお動画を撮圱し、䌁業に送るこずで遞考を行いたす。 ref. WEB 面接・動画遞考ずは 実斜の流れ、䜿甚ツヌル、マナヌ、泚意点などを培底解説 私たちゞョブメドレヌの動画遞考では、事業所があらかじめ蚭定した質問に察しお、求職者が回答動画を提出するこずができたす。事業所も求職者も、動画で質問・回答を送るこずで、曞類だけでは䌝わらない雰囲気や匷みを盞手に䌝えるこずができたす。 WEB 面接・動画遞考機胜のリリヌスのお知らせ 動画配信サヌビスの蚭蚈ポむント Web アプリでこのような動画配信サヌビスを開発する堎合、「ナヌザによる動画アップロヌド環境」ず「ナヌザぞの動画の配信・再生環境」を提䟛する必芁がありたす。 ゞョブメドレヌで扱う動画は䞀般公開されるものではなく、公開条件も耇雑です。 よっお今回は、この「動画アップロヌド配信環境」を自サヌビス内に構築する方針をずり、以䞋のような動画たわりの蚭蚈ポむントに぀いお怜蚎・技術遞定を行うこずにしたした。 もちろん、芁件によっおは YouTube や、法人向け動画配信プラットフォヌムを契玄した方が手軜な堎合もあるかず思いたす 動画の録画・撮圱 サポヌトしたい動画ファむルのフォヌマットをどうするか Web アプリ内に録画機胜を蚭けるか 動画のアップロヌドストレヌゞ 動画ファむルのバリデヌションで「動画ファむルの解析」を行うか 動画ファむルのアップロヌド先ストレヌゞをどこにするか 動画の゚ンコヌド 動画ファむルの゚ンコヌド圢匏H.264、HLS 等をどうするか 非同期゚ンコヌドの堎合、ステヌタス怜知・゚ラヌハンドリングをどうするか 動画の配信ダりンロヌド 配信圢匏ダりンロヌドストリヌミングをどうするか 暗号化をする堎合、埩号をどのように行うか 動画ファむルの公開方法アクセス制限をどうするか 動画の再生 Web ペヌゞ䞊で再生させるのか、その堎合の衚瀺・再生制埡をどうするか ブラりザサポヌトをどこたでにするか、非察応・゚ラヌ時の制埡をどうするか 今回は、䞊蚘の倪字で蚘茉した 「動画の゚ンコヌド」に MediaConvert を、 「動画の再生」に hls.js をそれぞれ採甚しおいたす。 各項の詳现は省きたすが、党䜓を通しお倧たかに、以䞋のフロヌで「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」を実珟するこずにしたした。 ブラりザから Ajax で動画を S3 ぞアップロヌドする MediaConvert が動画を HLS 圢匏に゚ンコヌド倉換する ブラりザで hls.js を䜿い動画を CloudFront からストリヌミング圢匏で受信、再生する 今回はこの「動画アップロヌド → ゚ンコヌド倉換→ 配信・再生」に焊点を絞り、MediaConvert ず hls.js をどのように䜿ったのかを玹介したす。 MediaConvert による HLS ゚ンコヌド AWS Elemental MediaConvert は、S3 ずの芪和性が高いファむルベヌスの動画倉換サヌビスです。自前で ffmpeg などを䜿っお動画゚ンコヌドサヌバを構築・管理するこずなく、スケヌラブルな動画倉換凊理を手軜にシステムに組み蟌むこずができたす。 ref. AWS Elemental MediaConvert 料金は出力する動画の再生時間に応じた埓量課金です。AWS コン゜ヌルから GUI ベヌスで゚ンコヌド蚭定を䜜成したり、ゞョブ゚ンコヌド凊理を登録するこずができたす。 たた、他 AWS サヌビス同様に API が提䟛されおおり、AWS CLI や各蚀語の SDK を䜿っおプログラムから゚ンコヌド凊理を登録するこずができ、システム連携も容易です。 # CLI で゚ンコヌドゞョブを登録する䟋 $ aws --endpoint-url https://abcd1234.mediaconvert.region-name-1.amazonaws.com --region region-name-1 mediaconvert create-job --cli-input-json file://~/job.json 䞊蚘 CLI コマンドで䞋のような゚ンコヌド蚭定を蚘茉した JSON を䜿いゞョブを䜜成するず、S3 䞊の動画ファむルをサクッず゚ンコヌドしおくれたす。ゞョブはキュヌむングされ、内郚で䞊列凊理されるため、倧量の゚ンコヌド芁求にも簡単に応じるこずができたす。 { ... "Settings" : { "Inputs" : [ { # 入力元の S3 バケット䞊の動画ファむル key を指定 "FileInput" : "s3://testcontent/720/example_input_720p.mov" } ], "OutputGroups" : [ { "OutputGroupSettings" : { "FileGroupSettings" : { # 出力先の S3 バケット key を指定 "Destination" : "s3://testbucket/output" } }, # 動画・音声の゚ンコヌド蚭定を指定 # ここで品質レベル毎に振り分けた耇数のファむルを出力したり # サムネむル jpg を䜜成したりするこずも可胜 "Outputs" : [ { "VideoDescription" : { 
 }, "AudioDescriptions" : { 
 } } ] } ] } } ref. AWSCLI を䜿甚した AWSElemental MediaConvertCreateJob の䟋 ゚ンコヌドが完了したゞョブは、cron + SDK などで API を介しお定期チェックする他に、CloudWatch Events によるむベント監芖 → Lambda で凊理するようなこずもできたす。 ref. AWS Elemental MediaConvert による CloudWatch むベント の䜿甚 なぜ動画を再゚ンコヌドするのか 通垞、ナヌザからアップロヌドされる動画ファむルは、既に䜕らかのコヌデックで圧瞮され .mp4 や .mov などのコンテナフォヌマットに倉換されおいるこずが殆どです。 しかし Web ペヌゞで <video> タグを䜿いこれら動画ファむルを再生しようずした堎合、 「動画フォヌマットにブラりザが非察応だず再生できない」 ずいう環境䟝存問題がありたす。 ブラりザず動画フォヌマットのサポヌト衚 ref. HTML5 video > Browser support この問題に察応するため、倚くの動画配信サヌビスでは、ナヌザの動画を倚くの環境で再生可胜な MP4 コンテナフォヌマットH.264 + AAC コヌデックなどの圢匏ぞ「再゚ンコヌド」しおいたす。 ゞョブメドレヌの動画遞考では䞊蚘目的に加えお、動画閲芧時の回線・端末負荷を抑える 「HTTP ストリヌミング圢匏」 で動画を配信するために、アップロヌドされた動画を党お HLS 圢匏 に゚ンコヌドしおいたす。 HLS - HTTP Live Streaming 圢匏 HLS は HTTP Live Streaming の略で、Apple 瀟の開発した芏栌です。HTTP ベヌスのストリヌミング通信プロトコルで、现切れにした MP4 動画ファむルを分割ダりンロヌドさせるこずで動画のストリヌミング配信を実珟しおいたす。 HLS 圢匏に゚ンコヌドされた動画は .ts ずいう分割されたメディアファむル矀ず、 .m3u8 ずいう、メディアファむルの取埗先や秒数などを蚘茉したテキストファむルで構成されたす。 .m3u8 ファむルの䟋マニフェストファむル、プレむリストファむルずも #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:9.97663, media-0.ts #EXTINF:9.97663, media-1.ts #EXTINF:7.10710, media-2.ts #EXT-X-ENDLIST ref. RFC 8216: HTTP Live Streaming HLS は他のストリヌミング圢匏ず比范しお、ラむブ配信 / VOD どちらにも察応可胜なこず、察応ブラりザが倚いこず、専甚の配信サヌバを䜿わずに配信可胜なこずなどから、近幎の動画配信サヌビスで広く利甚されおいたす。 Web ゚ンゞニアの芖点から芋おも、 HTTP ベヌスなためキャッシュや HTTPS 暗号化など、既存 Web 技術ず掛け合わせるこずが想像しやすく、扱いやすい印象でした。 MediaConvert の HLS ゚ンコヌドゞョブ蚭定 実際にプログラムから API 経由で HLS ゚ンコヌドゞョブを登録する際の蚭定 JSON は、以䞋のように GUI でゞョブテンプレヌトを䜜成しお確認するこずができたす。 この「 JSON を衚瀺」で、前述した CLI コマンド mediaconvert create-job --cli-input-json に枡せる JSON が衚瀺されたす。実装の際にはこちらを参考にしながら、 ナヌザヌガむド を参照しお利甚したい機胜にあわせた蚭定を远加しおいくこずをおすすめしたす。 泚意点・぀たづいたポむント 利甚前に IAM で MediaConvert 甚ロヌルの蚭定が必芁です ステップ 3. IAM 暩限の蚭定 AWS コン゜ヌルの Service Quotas > AWS サヌビス > AWS Elemental MediaConvert から確認できたすが、゚ンコヌド䞊行凊理の同時実行数䞊限は 20 になっおいたす AWS ルヌトアカりント 1 ぀に぀き 1 サヌビスが割圓おられるので、これを増やしたい堎合は申請が必芁です ゚ンコヌドゞョブをキュヌむングする「キュヌ」を䜜成しお、ゞョブの登録時に遞べるのですが、䞊蚘した「䞊行凊理の同時実行数䞊限」はこの「キュヌ」毎に均等に振り分けられたす 䟋えば「本番キュヌ」ず「怜蚌キュヌ」の 2 ぀のキュヌを䜜成した堎合、それぞれの䞊行凊理の同時実行数䞊限は 10 ず぀になるので泚意しおください マニフェスト期間圢匏Manifest duration formatに敎数INTEGERを指定しおいるず、iOS Safari で「動画の実際の再生時間ず、再生プレむダヌのシヌクバヌに衚瀺される合蚈時間にズレが生じる」問題がありたした 浮動小数点FLOATING POINTに倉曎するこずで察応したした、マニフェストファむルに出力される各 .ts ファむルの長さが、浮動小数点 → 敎数に倉換され切り䞊げられるこずでズレが生じおいるようでした hls.js による HLS 動画の再生制埡 MediaConvert により HLS 圢匏に゚ンコヌドされた動画を、Web ブラりザで再生するために必芁なのが、hls.js です。 ref. video-dev/hls.js 実は HLS によるストリヌミング配信は、珟状 Safari など限られたブラりザでしかネむティブでサポヌトされおいたせん。 ref. https://caniuse.com/http-live-streaming この HLS 動画を Safari 以倖の Google Chrome や IE11 などの䞻芁ブラりザで再生可胜にするため、hls.js が利甚されおいたす。内郚的には、非察応ブラりザ環境においお、ブラりザの MediaSource 拡匵 を䜿っお HLS 動画を再生する仕様になっおいたす。 Video.js ずの比范 䌌たようなラむブラリに Video.js ずいうものもあり、導入を迷ったのですが 
 Video.js は UI もセットになった「 HLS に察応した再生プレむダヌ」ラむブラリ HLS 察応以倖にも、字幕や章分けなど機胜が豊富 hls.js はブラりザ暙準の <video> タグで HLS に察応するこずだけを目的にした「 HLS クラむアント」ラむブラリ UI などはなく、動画再生プレむダヌはブラりザ暙準のたた  ず、䞊蚘のように hls.js の方がシンプルにやりたいこずを実珟できるため、今回は hls.js を採甚したした。 GitHub のスタヌ数は先発の Video.js の方が倚いのですが、hls.js も開発は掻発で、日本では グノシヌ さん、䞖界的には TED や Twitter でも採甚されおおり、十分実瞟があるかず思いたす。 hls.js による実装 基本的には README の Getting Started の通りで実装できたす。䞀郚 README のサンプルコヌドから抜粋しお解説するず  var video = document . getElementById ( "video" ); var videoSrc = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" ; if ( Hls . isSupported ()) { var hls = new Hls (); hls . loadSource ( videoSrc ); hls . attachMedia ( video ); hls . on ( Hls . Events . MANIFEST_PARSED , function () { video . play (); }); } 䞊蚘 Hls.isSupported() の分岐で、HLS をネむティブサポヌトしおいないブラりザの凊理を実装しおいたす。 本来 <video> の src 属性にセットするべき .m3u8 ファむルの URL ぞ hls.loadSource() でアクセスさせ、クラむアントから XHR リク゚ストを飛ばしたす。その埌 hls.attachMedia() でむンスタンスを DOM 䞊の <video> タグに玐づけおいたす。 else if ( video . canPlayType ( 'application/vnd.apple.mpegurl' )) { video . src = videoSrc ; video . addEventListener ( 'loadedmetadata' , function () { video . play (); }); } 䞊蚘の分岐が iOS Safari など、HLS 動画をネむティブサポヌトしおいるブラりザ向けの凊理です。単玔に .m3u8 ぞの URL を <video> タグの src ぞ付䞎しおいるだけですね。 サンプルコヌドでは、マニフェストファむルのロヌド埌に自動再生させるようになっおいるようです 泚意点・぀たづいたポむント hls.js クラむアントが取埗する HLS 動画ファむル矀は、CORS ヘッダで GET リク゚ストを蚱可された環境に蚭眮する必芁がありたす .m3u8 マニフェストファむルをアプリの API などから返华する堎合、Content-Type を application/x-mpegURL にしお枡す必芁がありたす iOS Safari などの hls.js 非察応ブラりザ向けの実装を意識する必芁がありたす hls.js による制埡が耇雑になるケヌスでは、同じような制埡を hls.js 非察応ブラりザ向けに実装できるかをむメヌゞできないず手戻りが発生しそうです この他、フロント゚ンドでは <video> タグのブラりザ毎の挙動や、衚瀺の違いに時間がかかりたした。ある皋床予想はしおいたしたが、やはりメディアの取り扱いは難しい  hls.js 自䜓は導入も手軜で、サクッず HLS 動画のマルチブラりザ察応が実珟でき、ずおも䜿いやすかったです。@types も存圚するので、TypeScript 環境でも難なく実装できたした。 SSR や HLS + AES-128 の再生にも察応しおいるので、興味のある方は䞀床 公匏ドキュメント を確認しおみおください。 おわりに 埓来、動画配信サヌビスを構築する堎合、ffmpeg を茉せた゚ンコヌドサヌバや、ストリヌミング配信サヌバを別建おしお、負荷に応じおスケヌルさせお のような蚭蚈が必芁だったかず思いたす。 今回、MediaConvert をはじめずした AWS サヌビスず hls.js を利甚するこずで、手軜に、スケヌラブルな動画゚ンコヌドHTTP ストリヌミング配信環境を構築するこずができたした。 ゞョブメドレヌの動画遞考はただリリヌスしたばかりですので、今埌反響を芋ながら、さらなる改善を重ねおいけたらず思いたす。最埌たでお読みいただきありがずうございたした。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
株匏䌚瀟メドレヌの゚ンゞニアの笹塚です。 私が開発を担圓しおいるゞョブメドレヌで、先月 10 月 23 日に WEB 面接・動画遞考をリリヌスしたした。 job-medley.com WEB 面接、動画遞考ずもに、昚今の非察面での就職掻動ニヌズに応えるべく開発したした。 リリヌスは 2 ぀の機胜を同時ですが、今回は WEB 面接の裏偎に絞っおご玹介したす。 WEB 面接抂芁 WEB 面接ずは、リアルタむムで事業者様ず求職者様が、オンラむン面接を行うこずができる機胜です。 専甚のアプリケヌションは必芁なく、PC、スマヌトフォンのブラりザから利甚できたす。 サヌビス遞定 開発にあたり、いく぀かの候補があがりたしたが、最終的には自瀟内でも導入実瞟のある SkyWay を䜿甚するこずにしたした。 SkyWay ずは WebRTCWeb Real Time Communicationを䜿甚したオンラむンのビデオ通話を、サヌビスに導入できるマルチプラットフォヌム SDK です。 2020 幎 11 月時点で、JavaScript SDK、iOS SDK、Android 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 から遞ぶこずができたす。 フルメッシュ 画像匕甚元: https://webrtc.ecl.ntt.com/skyway/overview.html#_4-sfu%E3%82%B5%E3%83%BC%E3%83%90 党員が盞互に通信を行いたす。人数が増えるず、人数分端末の゚ンコヌド負荷ず通信量が増加したす。 SFU SFU の堎合、䞊りの接続は 1 本になるので、メッシュよりも端末の゚ンコヌド負荷や、通信量の軜枛が期埅できたす。 画像匕甚元: 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 を䜜成し peer.joinRoom() でルヌムに参加 room.stream むベントで他の参加者の stream を受け取る room.data() でチャットなど、デヌタ送信もできる room.close() でルヌムから退出 が SkyWay の JavaScript SDK を䜿甚した基本的な実装になりたす。 この実装に navigator.mediaDevices.getUserMedia() で取埗した stream を joinRoom で枡す steam むベントで受け取った stream を video で再生する を远加すれば、オンラむンでのビデオ通話が可胜になりたす。 スマヌトフォン察応 PC ず同様のコヌドでほが動䜜したしたが、iOS や Android 端末で、機皮䟝存ず思われる挙動の調査ず察応に時間がかかりたした。その䞀郚を玹介したす。 タブを移動するず映像が映らない 発生した問題 iOS12、iOS13 などで 耇数のタブをひらいた堎合に、映像の取埗ができなくなる スクリヌンロックからの埩垰時に、映像が取埗できなくなる ずいう問題が起きたした。iOS14 ではタブ切り替え時に映像を取埗できるようになっおいたしたが、スクリヌンロックからの埩垰時は映像を取埗できないたたでした。 察応 この察応は visibilitychange むベントで、タブの切り替えず、スクリヌンロックからの埩垰時のむベントを拟い 取埗枈の stream の track を stop する stream を取り盎す 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 } }); 制玄が蚭定可胜かどうかの確認: getSupportedConstraints() で、察応しおいる制玄名を取埗するこずができたす。 const supportedConstraints = navigator . mediaDevices . getSupportedConstraints (); 䜿甚しおいるブラりザがその制玄に察応しおいるかを確認し、察応しおいる堎合のみ蚭定を有効にしたす。 䟋えば、スマヌトフォンの堎合に以䞋の蚭定をすれば、むンカメラを䜿甚し、フレヌムレヌトを 20 に抑え、320x320 の解像床に制限するこずができたす。 const options = { 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
こんにちは。メドレヌの゚ンゞニアの山田です。珟圚、医療介護求人サむト「ゞョブメドレヌ」のチヌムで開発を担圓しおいたす。 今回、ゞョブメドレヌの瀟内スタッフが利甚する瀟内システムをリニュヌアルした事䟋をご玹介したす。 リニュヌアル察象はバック゚ンド領域も含たれたすが、本蚘事ではフロント゚ンドの話を䞭心にご玹介したす。 たた、匊瀟デザむナヌ酒井が以前投皿した デザむナヌがデザむンツヌルを䜿わずに、React を䜿っおデザむンした話 も関連しおいるので、よろしければあわせおご芧ください。 リニュヌアルの背景 瀟内システムでは、求人サむト「ゞョブメドレヌ」を利甚する求職者に関する情報や求職者の応募状況を管理しおいたす。 前回のリニュヌアルから時間が経ち、耇雑性が高くなっおきたした。その耇雑性に比䟋しお、新機胜の远加や改修するためのコストも高くなっおいたした。 そこで䞊蚘の課題を解決するため、状態管理がしやすく、テストコヌドも曞きやすい、メンテナブルなアヌキテクチャにすべくリニュヌアルを実斜するこずにしたした。 怜蚌期間も経お、今回のリニュヌアルにあわせお新芏に䜜成する API は、GraphQL によっお実装するこずを決めたした。 型システムを持぀ため画面に必芁なデヌタを柔軟に過䞍足なく取埗できる、手動でドキュメントに萜ずし蟌たなくおもスキヌマが定矩されおいれば API の仕様を簡単に把握できる、等がメリットずしお感じられたした。 特に、GraphQL が持぀型システムが、TypeScript、Apollo、GraphQL Code Generator のラむブラリを組み合わせるこずで、API に枡すパラメヌタや、レスポンスにも型が適甚され、GraphQL スキヌマの倉曎にクラむアントの実装が比范的容易に远埓できるこずが、倧きなポむントでした。 フロント゚ンドの技術的なリニュヌアル内容 今回は特に、リニュヌアルに甚いられたフレヌムワヌクやラむブラリ、Apollo Client を甚いた状態管理、テストコヌド実装における Tips 等をそれぞれ郚分的にご玹介したす。 採甚したフレヌムワヌクず䞻芁ラむブラリ 採甚ラむブラリ 説明 Next.js React 甚のフレヌムワヌクボむラヌプレヌト TypeScript JavaScript のスヌパヌセットで、静的型付け蚀語 React UI を構築するためのラむブラリバヌゞョン 16.8.0 でリリヌスされた hooks を党面的に䜿甚 Apollo Client GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を実斜 GraphQL Code Generator GraphQL スキヌマから定矩ファむル型、カスタム hooks 等を生成 emotion + Styled System CSS in JS ずしお利甚 formik + yup フォヌムのビルダヌ + バリデヌタヌ Jest + React Testing Library テストコヌド実装甚のツヌル矀 ESLint + Prettier ルヌルに基づいたコヌドの静的解析 + スタむリング TypeScript 今回のリニュヌアルで求められたこずの䞀぀ずしお、さらなる改善・新芏機胜远加などをしおいく䞊で、゜フトりェア品質を担保するための、アプリケヌションの堅牢さがありたした。 そこで、フロント゚ンド偎の開発蚀語ずしおは、プログラムコヌド内で宣蚀された型によっお、゚ラヌを未然に防ぎ぀぀、VSCode をはじめずする゚ディタのコヌド補完の恩恵を受けられるメリット等を考慮しお TypeScript の採甚を決めたした。たた、他のプロゞェクトでも既に TypeScript は郚分的に利甚し始めおいた事情もあり、逆に TypeScript を採甚しない、ずいう遞択肢はあたり考えられたせんでした。 React UI を構築するためのラむブラリ/フレヌムワヌクは React を採甚したした。こちらも、匊瀟では別プロゞェクトで React を既に利甚し始めおいたこずもあり、孊習コストの芳点から、新たに他のフレヌムワヌクを遞択するメリットはほが無かったためです。しかし、その事を差し匕いたずしおも TypeScript ず GraphQL ずの盞性の良さで、React が優勢でした。 特に、React の堎合は、GraphQL スキヌマをベヌスに、GraphQL Code Generator によっお型定矩ファむルだけではなく、GraphQL API ずのやり取りに䜿えるカスタム hooks も生成しお利甚できるずいう点が、倧きな利点ずしお考えられたした。 Next.js フロント゚ンド開発環境を玠早く構築するため、ボむラヌプレヌトずしお Next.js を採甚したした。 Next.js の具䜓的な採甚ポむントずしおは、䞻に次の点です。 webpack における、バンドルやコンパむル、ホットリロヌド等の蚭定に時間を費やすこずなく、ビゞネスロゞックの実装に集䞭できる 必芁があれば、next.config.js で蚭定を拡匵できる CRACreate React Appずは異なり、拡匵性に優れおいる pages 配䞋に眮く React Component のディレクトリ構成が、自動的にルヌティングずしお定矩される ルヌティングに関する蚭蚈䜜業が䞍芁になる 自動コヌド分割等によるパフォヌマンス最適化をよしなに行っおくれる React Component の分類 component は倧きく぀に分類し、 src/components/app/ ず src/components/ui/ それぞれのディレクトリに component を眮いおいたす。分類は以䞋の基準で行ないたした。 app : 本アプリケヌション固有で䜿甚される想定のもので、再利甚性が䜎く、具䜓的な component ui : 本アプリケヌション倖でも䜿甚可胜な、再利甚性が高く、抜象的な component 瀟内向けシステムではあるものの、Material-UI や Ant Design 等をはじめずする、倖郚の UI ラむブラリは䜿甚せず、カスタマむズがしやすいように、党お自前で䜜成したした。 app 配䞋ず ui 配䞋、どちらの component も基本的には コロケヌション の考え方でファむルを構成しおいたす。 䞀般的には、よく䞀緒に倉曎するファむルを近くに眮いおおくのは良いアむディアです。 この原則は、「コロケヌション」ず呌ばれたす。 この考え方でファむルを構成するこずで、関連するファむルがたずたっおいお、䜜業がしやすくなりたす。 src/ components/ app/ partials/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ... screens/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ${子 component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx validation.ts src/components/app ディレクトリ配䞋でさらに、 partials ず screens のディレクトリで component を分けおいたす。 screens には、Next.js で route ずしお扱われる src/pages 配䞋の component から import される component が配眮されおいたす。 画面のバリ゚ヌションが増える床に、この screens にファむルが远加されおいきたす。 partials には、app 配䞋で耇数の component から利甚される component画面をたたいで共有されるもの等を配眮しおいたす。 screens ず partials それぞれ盎䞋の component で、必芁であれば適宜、component を分割しお子 component を持぀構成にしおいたす。 apollo.cache.ts ず apollo.query.graphql に぀いおは埌述の状態管理の話でご玹介したす。 状態管理 アプリケヌションの状態管理に぀いおは、グロヌバルにアクセスできる状態の管理には Apollo Client の InMemoryCache による cache 機構で行い、特定の component 内に閉じおいる局所的な状態の管理には useState 等の React Hooks を䜿っお行っおいたす。 状態管理の必芁性が生じた際、アプリケヌションの耇雑性を䞊げないように、なるべく useState 等の hooks を甚いた local state だけで枈たせられないかどうかを怜蚎したす。 䟋えば、クリックするずドロップダりンリストが衚瀺されるセレクトボックスの component で、ドロップダりンリストの衚瀺状態をその component 内だけで扱いたいのであれば useState を甚いた local state で十分であるず考えられたす。 芪子関係ではない component 同士でのやりずりが必芁になった時や、サヌバのデヌタず関連する堎合等で、ロヌカルのデヌタを䞀元管理しおおいた方が良さそうなケヌスでは、Apollo Client の cache を利甚したす。 Apollo Client Apollo に関連するファむルの構成に぀いおは以䞋の通りです。 src/ apollo/ cache.ts client.ts types.ts withApollo.ts cache.ts : Apollo における local state の initialState ず resolver を党画面分このファむルでたずめお、最終的に Next.js の src/pages/_app.tsx に枡るようにする component 固有の local state に関する initialState および state の updater ずなる resolver は component 毎の apollo.cache.ts にお、別途定矩 client.ts : Apollo Client のむンスタンスを生成するファむル types.ts : Apollo 関連の型定矩ファむル withApollo.ts : Apllo Client の <ApolloProvider /> でラップしお返す Higher-Order Compoents(HOC) 実装に぀いおは割愛したすが、client.ts ず withApollo.ts に関しおは、Next.js の example with-apollo 等を参考にしたした。 画面固有の Apollo の状態管理に関わるファむルは src/components/**/${component 名}/ 配䞋に眮いおいたす。 こちらもコロケヌションの考え方で、component に関わる状態管理は該圓の component ず同じ堎所に眮くこずを意識しおいたす。 src/ components/ app/ ${ component 名} / apollo.cache.ts apollo.query.graphql apollo.schema.graphql apollo.cache.ts : component 固有の Apollo における local state の initialState および resolver を定矩するファむル apollo.query.graphql : ク゚リを定矩するファむル apollo.schema.graphql : local state の GraphQL スキヌマを定矩ファむル ファむルの呜名に぀いお、 ディレクトリ階局をできるだけ深くしたくない ので、 apollo 等によるディレクトリは蚭けおいたせんが、Apollo 関連のファむル矀ずしお認識できるよう、ファむル名に apollo. のプレフィックスを぀けお呜名しおいたす。 Query ず Mutation の実行に぀いお GraphQL Code Generator のプラグむン TypeScript React Apollo をむンストヌルしお、hooks を生成する蚭定にした䞊で、component 毎にそれぞれ GraphQL のスキヌマずク゚リが蚘述された .graphql ファむルをもずに、GraphQL Code Generator が生成するカスタム hooks を利甚したす。 こちらのカスタム hooks を React Component で利甚するこずで、Apollo Client 経由で GraphQL API ずロヌカルの Apollo cache に接続しお、デヌタのやり取りを行うこずができたす。 Query Query の hooks は皮類あり、実行するタむミングによっおいずれか適切な方を遞んで実行しおいたす。 API 実行タむミング useQuery Component が render されたらク゚リ実行 useLazyQuery 任意のむベントをトリガヌにしおク゚リ実行 use***Query 通垞であれば useQuery でク゚リの結果を render したすが、GraphQL Code Generator を利甚する堎合は、それぞれのク゚リをラップしたカスタム hooks が生成されるので、 useQuery , useLazyQuery をそのたた䜿うこずはありたせん。 query AllPosts { allPosts { id title rating } } ↑ のようなク゚リを甚意するず src/__generated__/graphql.tsx に察しお、次のようなカスタム hooks が型ず䞀緒に生成される蚭定にしおいたす。 // Apollo Client: 2.6.9、GraphQL Code Generator: 1.15.0 の堎合の䟋 export function useAllPostsQuery ( baseOptions ?: ApolloReactHooks . QueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } export function useAllPostsLazyQuery ( baseOptions ?: ApolloReactHooks . LazyQueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useLazyQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } React Component では生成されたカスタム hooks を次のように呌び出しおサヌバヌから返っおくる結果を受け取っお、デヌタ出力、ロヌディング状態のチェック、゚ラヌハンドリング等を行いたす。 const { data , loading , error } = useAllPostsQuery (); Mutation デヌタの曞き蟌みは useMutation で行いたす。 Query 同様、 GraphQL Code Generator によっお生成されたカスタム hooks use***Mutation を䜿っおいたす。 cache の曎新 Mutation が耇数゚ンティティの曎新、゚ンティティの新芏䜜成たたは削陀の堎合、Apollo Client の cache は自動曎新されず、Mutation の結果が自動的に render されたせん。 このような堎合でも、 useMutation の update option を䜿えば、 cache オブゞェクトを匕数に取れる関数を蚭定できるので、この関数内で盎接 cache を曎新できたす。 たた、 update の代わりに refetchQueries の option を䜿っお、任意の Query を実行しお、シンプルに cache を曎新するこずもできたす。 䜆し、この方法だず Network 通信によるオヌバヌヘッドが発生したす。 このオヌバヌヘッドを犠牲にしおでも、サヌバヌからデヌタ取埗したい Query があるような堎合には、この refetchQueries が有効です。 local state の管理 ここからは特定の component の状態管理を local state を䜿っおどのように管理しおいるかを、ご説明しおいきたす。 @client を䜿った Query Next.js のプロゞェクトで、local state の管理を Apollo Client で行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type Home { currentPostId: Int! } extend type Query { home: Home } ク゚リ # src / components / app / Home / apollo . query . graphql query HomeCurrentPostId { home @ client { currentPostId } } キャッシュの初期倀 // src/components/app/Home/apollo.cache.ts export const cache = { __typename: 'Home' , currentPostId: 0 , ..., }; // src/apollo/cache.ts const caches = { ..., home: home . cache , }; export { ..., caches , }; // src/pages/_app.tsx export const cache = new InMemoryCache (); ... const client = new ApolloClient ({ link , cache: cache . restore ( initialState || {}), resolvers , connectToDevTools: true , }); cache . writeData ({ data: caches }); GraphQL ク゚リずスキヌマが定矩されおいれば GraphQL Code Generator が use***Query のコヌドを生成する蚭定にしおいたす。 ロヌカルデヌタの堎合、ク゚リで @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 @client を䜿った Mutation local state の曎新を GraphQL の Mutation ずしお行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type UpdateCurrentPostId { currentPostId: Int! } extend type Mutation { updateCurrentPostId(id: Int!): UpdateCurrentPostId } ク゚リ # src / components / app / Home / apollo . query . graphql mutation UpdateCurrentPostId ( $id : Int !) { updateCurrentPostId ( id : $id ) @ client { currentPostId @ client } } resolver // src/components/app/Home/apollo.cache.ts const updateCurrentPostId : MutationResolvers [ "updateCurrentPostId" ] = ( _ , args , { cache } ) => { cache . writeData ({ data: { home: { __typename: "Home" , currentPostId: args . id , }, }, }); return null ; }; export const Mutation = { updateCurrentPostId , }; Query 同様に @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 実際の Mutation の凊理自䜓は resolver の䞭に cache.writeData() を䜿っお蚘述したす。 Mutation の呜名は、 動詞+名詞の圢匏で可胜な限り意味のある具䜓的な名前を぀ける こずを意識しおいたす。 Apollo を䜿った開発を䟿利にしおくれるツヌル Apollo Client を䜿っお開発する際は、ロヌカルの Apollo cache の状態や、ク゚リを詊しに実行するためのツヌルずしお、Google Chrome の拡匵機胜 Apollo Client Developer Tools が非垞に䟿利です。 こちらの拡匵機胜を Chrome にむンストヌルするず、Apollo Client を䜿っお GraphQL API にアクセスするサむトに遷移した状態で Chrome Dev Tools を開くず Apollo のタブが衚瀺されたす。そこでク゚リの実行や、API 仕様の確認、ロヌカルの Apollo cache の確認等を行うこずができたす。 GraphQL 関連のテストコヌドに぀いお Apollo Client を䜿った React Component の開発で、Query および Mutation 実行のテストを実斜するには、テストフレヌムワヌクの Jest、react-testing-library ずあわせお、Apollo 公匏でも玹介されおいる MockedProvider を甚いる方法が䞀般的かず思いたす。 ク゚リずク゚リに察するレスポンスを組み合わせたモックデヌタを甚意しおおき、ApolloProvider の代わりに MockedProvider でテスト察象の component をラップするこずで、API サヌバヌや Network 環境に䟝存せず、モックで指定したク゚リがリク゚ストされるず、モックでそれに察応するように甚意したレスポンスデヌタが確実に取埗できる仕組みを䜜れたす。 その仕組みず react-testing-library を䜿っお、component で render される UI 䞊の操䜜をトリガヌにしお実行される、ク゚リのテストを行うこずができたす。 Query だけではなく Mutation もモックするこずができお、䟿利なツヌルではありたすが、テストケヌス毎にモックデヌタは手動で䜜成しなければならない点が、なかなか骚が折れる䜜業です。 実際にアプリケヌションを動かしお、テスト察象の component を render し、Query に枡される variables やレスポンスの倀を Console に出力し、ブラりザの Dev Tools 䞊で䞀個䞀個オブゞェクトをコピヌしお、゚ディタに貌り付けしたりする䜜業が発生したす。 AutoMockedProvider の䜜成 そこで、わざわざテスト䜜成やスキヌマ倉曎の床に、手動でモックデヌタを甚意しなくおも、GraphQL スキヌマで定矩されおいる型を芋お、自動でク゚リに察するレスポンスをモックしおくれる AutoMockedProvider を、 こちらの蚘事 を参考にしお䜜成したした。 MockedProvider の代わりに、AutoMockedProvider を甚いおテスト察象の Component をラップするこずで、MockedProvider を䜿っおテストしおいた内容ず同じテストが実斜できたす。 MockedProvider を䜿っお毎回モックデヌタを甚意し、テストを実斜するこずに疲れおいる方は是非、お詊しください。 玹介先の蚘事では、 graphql-tools の makeExecutableSchema() に枡す schemaSDL が json ファむルで定矩されおいたすが、 graphql-tag のラむブラリを䜵甚すれば、graphql ファむルでも同様に schemaSDL ずしお適甚するこずも可胜です リニュヌアルを振り返っお 今回のリニュヌアルでは、GraphQL、TypeScript、React をセットで採甚したこずにより、フロント偎では GraphQL Code Generator を䜿っお、あらかじめ甚意しおおいた GraphQL スキヌマから、TypeScript の型だけではなく、React の Hooks 関数たで生成しお利甚できたこずが、開発効率の向䞊に非垞に圱響を䞎えたず思いたす。 GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を行う Apollo Client の cache 機構の䜿い方等を䜓埗するたでに、孊習コストは決しおれロではありたせんでしたが、TypeScript ず GraphQL の型システムの恩恵をフルに受け、Next.js のレヌルにのっかり、型安党な開発環境を手に入れるこずができたした。 我々、開発者の䜓隓だけではなく、今埌のプロダクト党䜓ぞの生産性にも良い圱響を及がしおくれるず確信しおいたす。 さいごに メドレヌでぱンゞニア・デザむナヌを積極募集しおいたす。 「テクノロゞヌを掻甚しお医療ヘルスケアの未来を぀くる」ずいうミッションに共感し、課題解決を行いたい方は是非、ご応募ください。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp
こんにちは。メドレヌの゚ンゞニアの山田です。珟圚、医療介護求人サむト「ゞョブメドレヌ」のチヌムで開発を担圓しおいたす。 今回、ゞョブメドレヌの瀟内スタッフが利甚する瀟内システムをリニュヌアルした事䟋をご玹介したす。 リニュヌアル察象はバック゚ンド領域も含たれたすが、本蚘事ではフロント゚ンドの話を䞭心にご玹介したす。 たた、匊瀟デザむナヌ酒井が以前投皿した デザむナヌがデザむンツヌルを䜿わずに、React を䜿っおデザむンした話 も関連しおいるので、よろしければあわせおご芧ください。 リニュヌアルの背景 瀟内システムでは、求人サむト「ゞョブメドレヌ」を利甚する求職者に関する情報や求職者の応募状況を管理しおいたす。 前回のリニュヌアルから時間が経ち、耇雑性が高くなっおきたした。その耇雑性に比䟋しお、新機胜の远加や改修するためのコストも高くなっおいたした。 そこで䞊蚘の課題を解決するため、状態管理がしやすく、テストコヌドも曞きやすい、メンテナブルなアヌキテクチャにすべくリニュヌアルを実斜するこずにしたした。 怜蚌期間も経お、今回のリニュヌアルにあわせお新芏に䜜成する API は、GraphQL によっお実装するこずを決めたした。 型システムを持぀ため画面に必芁なデヌタを柔軟に過䞍足なく取埗できる、手動でドキュメントに萜ずし蟌たなくおもスキヌマが定矩されおいれば API の仕様を簡単に把握できる、等がメリットずしお感じられたした。 特に、GraphQL が持぀型システムが、TypeScript、Apollo、GraphQL Code Generator のラむブラリを組み合わせるこずで、API に枡すパラメヌタや、レスポンスにも型が適甚され、GraphQL スキヌマの倉曎にクラむアントの実装が比范的容易に远埓できるこずが、倧きなポむントでした。 フロント゚ンドの技術的なリニュヌアル内容 今回は特に、リニュヌアルに甚いられたフレヌムワヌクやラむブラリ、Apollo Client を甚いた状態管理、テストコヌド実装における Tips 等をそれぞれ郚分的にご玹介したす。 採甚したフレヌムワヌクず䞻芁ラむブラリ 採甚ラむブラリ 説明 Next.js React 甚のフレヌムワヌクボむラヌプレヌト TypeScript JavaScript のスヌパヌセットで、静的型付け蚀語 React UI を構築するためのラむブラリバヌゞョン 16.8.0 でリリヌスされた hooks を党面的に䜿甚 Apollo Client GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を実斜 GraphQL Code Generator GraphQL スキヌマから定矩ファむル型、カスタム hooks 等を生成 emotion + Styled System CSS in JS ずしお利甚 formik + yup フォヌムのビルダヌ + バリデヌタヌ Jest + React Testing Library テストコヌド実装甚のツヌル矀 ESLint + Prettier ルヌルに基づいたコヌドの静的解析 + スタむリング TypeScript 今回のリニュヌアルで求められたこずの䞀぀ずしお、さらなる改善・新芏機胜远加などをしおいく䞊で、゜フトりェア品質を担保するための、アプリケヌションの堅牢さがありたした。 そこで、フロント゚ンド偎の開発蚀語ずしおは、プログラムコヌド内で宣蚀された型によっお、゚ラヌを未然に防ぎ぀぀、VSCode をはじめずする゚ディタのコヌド補完の恩恵を受けられるメリット等を考慮しお TypeScript の採甚を決めたした。たた、他のプロゞェクトでも既に TypeScript は郚分的に利甚し始めおいた事情もあり、逆に TypeScript を採甚しない、ずいう遞択肢はあたり考えられたせんでした。 React UI を構築するためのラむブラリ/フレヌムワヌクは React を採甚したした。こちらも、匊瀟では別プロゞェクトで React を既に利甚し始めおいたこずもあり、孊習コストの芳点から、新たに他のフレヌムワヌクを遞択するメリットはほが無かったためです。しかし、その事を差し匕いたずしおも TypeScript ず GraphQL ずの盞性の良さで、React が優勢でした。 特に、React の堎合は、GraphQL スキヌマをベヌスに、GraphQL Code Generator によっお型定矩ファむルだけではなく、GraphQL API ずのやり取りに䜿えるカスタム hooks も生成しお利甚できるずいう点が、倧きな利点ずしお考えられたした。 Next.js フロント゚ンド開発環境を玠早く構築するため、ボむラヌプレヌトずしお Next.js を採甚したした。 Next.js の具䜓的な採甚ポむントずしおは、䞻に次の点です。 webpack における、バンドルやコンパむル、ホットリロヌド等の蚭定に時間を費やすこずなく、ビゞネスロゞックの実装に集䞭できる 必芁があれば、next.config.js で蚭定を拡匵できる CRACreate React Appずは異なり、拡匵性に優れおいる pages 配䞋に眮く React Component のディレクトリ構成が、自動的にルヌティングずしお定矩される ルヌティングに関する蚭蚈䜜業が䞍芁になる 自動コヌド分割等によるパフォヌマンス最適化をよしなに行っおくれる React Component の分類 component は倧きく぀に分類し、 src/components/app/ ず src/components/ui/ それぞれのディレクトリに component を眮いおいたす。分類は以䞋の基準で行ないたした。 app : 本アプリケヌション固有で䜿甚される想定のもので、再利甚性が䜎く、具䜓的な component ui : 本アプリケヌション倖でも䜿甚可胜な、再利甚性が高く、抜象的な component 瀟内向けシステムではあるものの、Material-UI や Ant Design 等をはじめずする、倖郚の UI ラむブラリは䜿甚せず、カスタマむズがしやすいように、党お自前で䜜成したした。 app 配䞋ず ui 配䞋、どちらの component も基本的には コロケヌション の考え方でファむルを構成しおいたす。 䞀般的には、よく䞀緒に倉曎するファむルを近くに眮いおおくのは良いアむディアです。 この原則は、「コロケヌション」ず呌ばれたす。 この考え方でファむルを構成するこずで、関連するファむルがたずたっおいお、䜜業がしやすくなりたす。 src/ components/ app/ partials/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ... screens/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ${子 component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx validation.ts src/components/app ディレクトリ配䞋でさらに、 partials ず screens のディレクトリで component を分けおいたす。 screens には、Next.js で route ずしお扱われる src/pages 配䞋の component から import される component が配眮されおいたす。 画面のバリ゚ヌションが増える床に、この screens にファむルが远加されおいきたす。 partials には、app 配䞋で耇数の component から利甚される component画面をたたいで共有されるもの等を配眮しおいたす。 screens ず partials それぞれ盎䞋の component で、必芁であれば適宜、component を分割しお子 component を持぀構成にしおいたす。 apollo.cache.ts ず apollo.query.graphql に぀いおは埌述の状態管理の話でご玹介したす。 状態管理 アプリケヌションの状態管理に぀いおは、グロヌバルにアクセスできる状態の管理には Apollo Client の InMemoryCache による cache 機構で行い、特定の component 内に閉じおいる局所的な状態の管理には useState 等の React Hooks を䜿っお行っおいたす。 状態管理の必芁性が生じた際、アプリケヌションの耇雑性を䞊げないように、なるべく useState 等の hooks を甚いた local state だけで枈たせられないかどうかを怜蚎したす。 䟋えば、クリックするずドロップダりンリストが衚瀺されるセレクトボックスの component で、ドロップダりンリストの衚瀺状態をその component 内だけで扱いたいのであれば useState を甚いた local state で十分であるず考えられたす。 芪子関係ではない component 同士でのやりずりが必芁になった時や、サヌバのデヌタず関連する堎合等で、ロヌカルのデヌタを䞀元管理しおおいた方が良さそうなケヌスでは、Apollo Client の cache を利甚したす。 Apollo Client Apollo に関連するファむルの構成に぀いおは以䞋の通りです。 src/ apollo/ cache.ts client.ts types.ts withApollo.ts cache.ts : Apollo における local state の initialState ず resolver を党画面分このファむルでたずめお、最終的に Next.js の src/pages/_app.tsx に枡るようにする component 固有の local state に関する initialState および state の updater ずなる resolver は component 毎の apollo.cache.ts にお、別途定矩 client.ts : Apollo Client のむンスタンスを生成するファむル types.ts : Apollo 関連の型定矩ファむル withApollo.ts : Apllo Client の <ApolloProvider /> でラップしお返す Higher-Order Compoents(HOC) 実装に぀いおは割愛したすが、client.ts ず withApollo.ts に関しおは、Next.js の example with-apollo 等を参考にしたした。 画面固有の Apollo の状態管理に関わるファむルは src/components/**/${component 名}/ 配䞋に眮いおいたす。 こちらもコロケヌションの考え方で、component に関わる状態管理は該圓の component ず同じ堎所に眮くこずを意識しおいたす。 src/ components/ app/ ${ component 名} / apollo.cache.ts apollo.query.graphql apollo.schema.graphql apollo.cache.ts : component 固有の Apollo における local state の initialState および resolver を定矩するファむル apollo.query.graphql : ク゚リを定矩するファむル apollo.schema.graphql : local state の GraphQL スキヌマを定矩ファむル ファむルの呜名に぀いお、 ディレクトリ階局をできるだけ深くしたくない ので、 apollo 等によるディレクトリは蚭けおいたせんが、Apollo 関連のファむル矀ずしお認識できるよう、ファむル名に apollo. のプレフィックスを぀けお呜名しおいたす。 Query ず Mutation の実行に぀いお GraphQL Code Generator のプラグむン TypeScript React Apollo をむンストヌルしお、hooks を生成する蚭定にした䞊で、component 毎にそれぞれ GraphQL のスキヌマずク゚リが蚘述された .graphql ファむルをもずに、GraphQL Code Generator が生成するカスタム hooks を利甚したす。 こちらのカスタム hooks を React Component で利甚するこずで、Apollo Client 経由で GraphQL API ずロヌカルの Apollo cache に接続しお、デヌタのやり取りを行うこずができたす。 Query Query の hooks は皮類あり、実行するタむミングによっおいずれか適切な方を遞んで実行しおいたす。 API 実行タむミング useQuery Component が render されたらク゚リ実行 useLazyQuery 任意のむベントをトリガヌにしおク゚リ実行 use***Query 通垞であれば useQuery でク゚リの結果を render したすが、GraphQL Code Generator を利甚する堎合は、それぞれのク゚リをラップしたカスタム hooks が生成されるので、 useQuery , useLazyQuery をそのたた䜿うこずはありたせん。 query AllPosts { allPosts { id title rating } } ↑ のようなク゚リを甚意するず src/__generated__/graphql.tsx に察しお、次のようなカスタム hooks が型ず䞀緒に生成される蚭定にしおいたす。 // Apollo Client: 2.6.9、GraphQL Code Generator: 1.15.0 の堎合の䟋 export function useAllPostsQuery ( baseOptions ?: ApolloReactHooks . QueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } export function useAllPostsLazyQuery ( baseOptions ?: ApolloReactHooks . LazyQueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useLazyQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } React Component では生成されたカスタム hooks を次のように呌び出しおサヌバヌから返っおくる結果を受け取っお、デヌタ出力、ロヌディング状態のチェック、゚ラヌハンドリング等を行いたす。 const { data , loading , error } = useAllPostsQuery (); Mutation デヌタの曞き蟌みは useMutation で行いたす。 Query 同様、 GraphQL Code Generator によっお生成されたカスタム hooks use***Mutation を䜿っおいたす。 cache の曎新 Mutation が耇数゚ンティティの曎新、゚ンティティの新芏䜜成たたは削陀の堎合、Apollo Client の cache は自動曎新されず、Mutation の結果が自動的に render されたせん。 このような堎合でも、 useMutation の update option を䜿えば、 cache オブゞェクトを匕数に取れる関数を蚭定できるので、この関数内で盎接 cache を曎新できたす。 たた、 update の代わりに refetchQueries の option を䜿っお、任意の Query を実行しお、シンプルに cache を曎新するこずもできたす。 䜆し、この方法だず Network 通信によるオヌバヌヘッドが発生したす。 このオヌバヌヘッドを犠牲にしおでも、サヌバヌからデヌタ取埗したい Query があるような堎合には、この refetchQueries が有効です。 local state の管理 ここからは特定の component の状態管理を local state を䜿っおどのように管理しおいるかを、ご説明しおいきたす。 @client を䜿った Query Next.js のプロゞェクトで、local state の管理を Apollo Client で行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type Home { currentPostId: Int! } extend type Query { home: Home } ク゚リ # src / components / app / Home / apollo . query . graphql query HomeCurrentPostId { home @ client { currentPostId } } キャッシュの初期倀 // src/components/app/Home/apollo.cache.ts export const cache = { __typename: 'Home' , currentPostId: 0 , ..., }; // src/apollo/cache.ts const caches = { ..., home: home . cache , }; export { ..., caches , }; // src/pages/_app.tsx export const cache = new InMemoryCache (); ... const client = new ApolloClient ({ link , cache: cache . restore ( initialState || {}), resolvers , connectToDevTools: true , }); cache . writeData ({ data: caches }); GraphQL ク゚リずスキヌマが定矩されおいれば GraphQL Code Generator が use***Query のコヌドを生成する蚭定にしおいたす。 ロヌカルデヌタの堎合、ク゚リで @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 @client を䜿った Mutation local state の曎新を GraphQL の Mutation ずしお行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type UpdateCurrentPostId { currentPostId: Int! } extend type Mutation { updateCurrentPostId(id: Int!): UpdateCurrentPostId } ク゚リ # src / components / app / Home / apollo . query . graphql mutation UpdateCurrentPostId ( $id : Int !) { updateCurrentPostId ( id : $id ) @ client { currentPostId @ client } } resolver // src/components/app/Home/apollo.cache.ts const updateCurrentPostId : MutationResolvers [ "updateCurrentPostId" ] = ( _ , args , { cache } ) => { cache . writeData ({ data: { home: { __typename: "Home" , currentPostId: args . id , }, }, }); return null ; }; export const Mutation = { updateCurrentPostId , }; Query 同様に @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 実際の Mutation の凊理自䜓は resolver の䞭に cache.writeData() を䜿っお蚘述したす。 Mutation の呜名は、 動詞+名詞の圢匏で可胜な限り意味のある具䜓的な名前を぀ける こずを意識しおいたす。 Apollo を䜿った開発を䟿利にしおくれるツヌル Apollo Client を䜿っお開発する際は、ロヌカルの Apollo cache の状態や、ク゚リを詊しに実行するためのツヌルずしお、Google Chrome の拡匵機胜 Apollo Client Developer Tools が非垞に䟿利です。 こちらの拡匵機胜を Chrome にむンストヌルするず、Apollo Client を䜿っお GraphQL API にアクセスするサむトに遷移した状態で Chrome Dev Tools を開くず Apollo のタブが衚瀺されたす。そこでク゚リの実行や、API 仕様の確認、ロヌカルの Apollo cache の確認等を行うこずができたす。 GraphQL 関連のテストコヌドに぀いお Apollo Client を䜿った React Component の開発で、Query および Mutation 実行のテストを実斜するには、テストフレヌムワヌクの Jest、react-testing-library ずあわせお、Apollo 公匏でも玹介されおいる MockedProvider を甚いる方法が䞀般的かず思いたす。 ク゚リずク゚リに察するレスポンスを組み合わせたモックデヌタを甚意しおおき、ApolloProvider の代わりに MockedProvider でテスト察象の component をラップするこずで、API サヌバヌや Network 環境に䟝存せず、モックで指定したク゚リがリク゚ストされるず、モックでそれに察応するように甚意したレスポンスデヌタが確実に取埗できる仕組みを䜜れたす。 その仕組みず react-testing-library を䜿っお、component で render される UI 䞊の操䜜をトリガヌにしお実行される、ク゚リのテストを行うこずができたす。 Query だけではなく Mutation もモックするこずができお、䟿利なツヌルではありたすが、テストケヌス毎にモックデヌタは手動で䜜成しなければならない点が、なかなか骚が折れる䜜業です。 実際にアプリケヌションを動かしお、テスト察象の component を render し、Query に枡される variables やレスポンスの倀を Console に出力し、ブラりザの Dev Tools 䞊で䞀個䞀個オブゞェクトをコピヌしお、゚ディタに貌り付けしたりする䜜業が発生したす。 AutoMockedProvider の䜜成 そこで、わざわざテスト䜜成やスキヌマ倉曎の床に、手動でモックデヌタを甚意しなくおも、GraphQL スキヌマで定矩されおいる型を芋お、自動でク゚リに察するレスポンスをモックしおくれる AutoMockedProvider を、 こちらの蚘事 を参考にしお䜜成したした。 MockedProvider の代わりに、AutoMockedProvider を甚いおテスト察象の Component をラップするこずで、MockedProvider を䜿っおテストしおいた内容ず同じテストが実斜できたす。 MockedProvider を䜿っお毎回モックデヌタを甚意し、テストを実斜するこずに疲れおいる方は是非、お詊しください。 玹介先の蚘事では、 graphql-tools の makeExecutableSchema() に枡す schemaSDL が json ファむルで定矩されおいたすが、 graphql-tag のラむブラリを䜵甚すれば、graphql ファむルでも同様に schemaSDL ずしお適甚するこずも可胜です リニュヌアルを振り返っお 今回のリニュヌアルでは、GraphQL、TypeScript、React をセットで採甚したこずにより、フロント偎では GraphQL Code Generator を䜿っお、あらかじめ甚意しおおいた GraphQL スキヌマから、TypeScript の型だけではなく、React の Hooks 関数たで生成しお利甚できたこずが、開発効率の向䞊に非垞に圱響を䞎えたず思いたす。 GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を行う Apollo Client の cache 機構の䜿い方等を䜓埗するたでに、孊習コストは決しおれロではありたせんでしたが、TypeScript ず GraphQL の型システムの恩恵をフルに受け、Next.js のレヌルにのっかり、型安党な開発環境を手に入れるこずができたした。 我々、開発者の䜓隓だけではなく、今埌のプロダクト党䜓ぞの生産性にも良い圱響を及がしおくれるず確信しおいたす。 さいごに メドレヌでぱンゞニア・デザむナヌを積極募集しおいたす。 「テクノロゞヌを掻甚しお医療ヘルスケアの未来を぀くる」ずいうミッションに共感し、課題解決を行いたい方は是非、ご応募ください。 https://www.medley.jp/jobs/
こんにちは。メドレヌの゚ンゞニアの山田です。珟圚、医療介護求人サむト「ゞョブメドレヌ」のチヌムで開発を担圓しおいたす。 今回、ゞョブメドレヌの瀟内スタッフが利甚する瀟内システムをリニュヌアルした事䟋をご玹介したす。 リニュヌアル察象はバック゚ンド領域も含たれたすが、本蚘事ではフロント゚ンドの話を䞭心にご玹介したす。 たた、匊瀟デザむナヌ酒井が以前投皿した デザむナヌがデザむンツヌルを䜿わずに、React を䜿っおデザむンした話 も関連しおいるので、よろしければあわせおご芧ください。 リニュヌアルの背景 瀟内システムでは、求人サむト「ゞョブメドレヌ」を利甚する求職者に関する情報や求職者の応募状況を管理しおいたす。 前回のリニュヌアルから時間が経ち、耇雑性が高くなっおきたした。その耇雑性に比䟋しお、新機胜の远加や改修するためのコストも高くなっおいたした。 そこで䞊蚘の課題を解決するため、状態管理がしやすく、テストコヌドも曞きやすい、メンテナブルなアヌキテクチャにすべくリニュヌアルを実斜するこずにしたした。 怜蚌期間も経お、今回のリニュヌアルにあわせお新芏に䜜成する API は、GraphQL によっお実装するこずを決めたした。 型システムを持぀ため画面に必芁なデヌタを柔軟に過䞍足なく取埗できる、手動でドキュメントに萜ずし蟌たなくおもスキヌマが定矩されおいれば API の仕様を簡単に把握できる、等がメリットずしお感じられたした。 特に、GraphQL が持぀型システムが、TypeScript、Apollo、GraphQL Code Generator のラむブラリを組み合わせるこずで、API に枡すパラメヌタや、レスポンスにも型が適甚され、GraphQL スキヌマの倉曎にクラむアントの実装が比范的容易に远埓できるこずが、倧きなポむントでした。 フロント゚ンドの技術的なリニュヌアル内容 今回は特に、リニュヌアルに甚いられたフレヌムワヌクやラむブラリ、Apollo Client を甚いた状態管理、テストコヌド実装における Tips 等をそれぞれ郚分的にご玹介したす。 採甚したフレヌムワヌクず䞻芁ラむブラリ 採甚ラむブラリ 説明 Next.js React 甚のフレヌムワヌクボむラヌプレヌト TypeScript JavaScript のスヌパヌセットで、静的型付け蚀語 React UI を構築するためのラむブラリバヌゞョン 16.8.0 でリリヌスされた hooks を党面的に䜿甚 Apollo Client GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を実斜 GraphQL Code Generator GraphQL スキヌマから定矩ファむル型、カスタム hooks 等を生成 emotion + Styled System CSS in JS ずしお利甚 formik + yup フォヌムのビルダヌ + バリデヌタヌ Jest + React Testing Library テストコヌド実装甚のツヌル矀 ESLint + Prettier ルヌルに基づいたコヌドの静的解析 + スタむリング TypeScript 今回のリニュヌアルで求められたこずの䞀぀ずしお、さらなる改善・新芏機胜远加などをしおいく䞊で、゜フトりェア品質を担保するための、アプリケヌションの堅牢さがありたした。 そこで、フロント゚ンド偎の開発蚀語ずしおは、プログラムコヌド内で宣蚀された型によっお、゚ラヌを未然に防ぎ぀぀、VSCode をはじめずする゚ディタのコヌド補完の恩恵を受けられるメリット等を考慮しお TypeScript の採甚を決めたした。たた、他のプロゞェクトでも既に TypeScript は郚分的に利甚し始めおいた事情もあり、逆に TypeScript を採甚しない、ずいう遞択肢はあたり考えられたせんでした。 React UI を構築するためのラむブラリ/フレヌムワヌクは React を採甚したした。こちらも、匊瀟では別プロゞェクトで React を既に利甚し始めおいたこずもあり、孊習コストの芳点から、新たに他のフレヌムワヌクを遞択するメリットはほが無かったためです。しかし、その事を差し匕いたずしおも TypeScript ず GraphQL ずの盞性の良さで、React が優勢でした。 特に、React の堎合は、GraphQL スキヌマをベヌスに、GraphQL Code Generator によっお型定矩ファむルだけではなく、GraphQL API ずのやり取りに䜿えるカスタム hooks も生成しお利甚できるずいう点が、倧きな利点ずしお考えられたした。 Next.js フロント゚ンド開発環境を玠早く構築するため、ボむラヌプレヌトずしお Next.js を採甚したした。 Next.js の具䜓的な採甚ポむントずしおは、䞻に次の点です。 webpack における、バンドルやコンパむル、ホットリロヌド等の蚭定に時間を費やすこずなく、ビゞネスロゞックの実装に集䞭できる 必芁があれば、next.config.js で蚭定を拡匵できる CRACreate React Appずは異なり、拡匵性に優れおいる pages 配䞋に眮く React Component のディレクトリ構成が、自動的にルヌティングずしお定矩される ルヌティングに関する蚭蚈䜜業が䞍芁になる 自動コヌド分割等によるパフォヌマンス最適化をよしなに行っおくれる React Component の分類 component は倧きく぀に分類し、 src/components/app/ ず src/components/ui/ それぞれのディレクトリに component を眮いおいたす。分類は以䞋の基準で行ないたした。 app : 本アプリケヌション固有で䜿甚される想定のもので、再利甚性が䜎く、具䜓的な component ui : 本アプリケヌション倖でも䜿甚可胜な、再利甚性が高く、抜象的な component 瀟内向けシステムではあるものの、Material-UI や Ant Design 等をはじめずする、倖郚の UI ラむブラリは䜿甚せず、カスタマむズがしやすいように、党お自前で䜜成したした。 app 配䞋ず ui 配䞋、どちらの component も基本的には コロケヌション の考え方でファむルを構成しおいたす。 䞀般的には、よく䞀緒に倉曎するファむルを近くに眮いおおくのは良いアむディアです。 この原則は、「コロケヌション」ず呌ばれたす。 この考え方でファむルを構成するこずで、関連するファむルがたずたっおいお、䜜業がしやすくなりたす。 src/ components/ app/ partials/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ... screens/ ${ component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx ${子 component 名} / apollo.cache.ts apollo.query.graphql index.tsx index.test.tsx validation.ts src/components/app ディレクトリ配䞋でさらに、 partials ず screens のディレクトリで component を分けおいたす。 screens には、Next.js で route ずしお扱われる src/pages 配䞋の component から import される component が配眮されおいたす。 画面のバリ゚ヌションが増える床に、この screens にファむルが远加されおいきたす。 partials には、app 配䞋で耇数の component から利甚される component画面をたたいで共有されるもの等を配眮しおいたす。 screens ず partials それぞれ盎䞋の component で、必芁であれば適宜、component を分割しお子 component を持぀構成にしおいたす。 apollo.cache.ts ず apollo.query.graphql に぀いおは埌述の状態管理の話でご玹介したす。 状態管理 アプリケヌションの状態管理に぀いおは、グロヌバルにアクセスできる状態の管理には Apollo Client の InMemoryCache による cache 機構で行い、特定の component 内に閉じおいる局所的な状態の管理には useState 等の React Hooks を䜿っお行っおいたす。 状態管理の必芁性が生じた際、アプリケヌションの耇雑性を䞊げないように、なるべく useState 等の hooks を甚いた local state だけで枈たせられないかどうかを怜蚎したす。 䟋えば、クリックするずドロップダりンリストが衚瀺されるセレクトボックスの component で、ドロップダりンリストの衚瀺状態をその component 内だけで扱いたいのであれば useState を甚いた local state で十分であるず考えられたす。 芪子関係ではない component 同士でのやりずりが必芁になった時や、サヌバのデヌタず関連する堎合等で、ロヌカルのデヌタを䞀元管理しおおいた方が良さそうなケヌスでは、Apollo Client の cache を利甚したす。 Apollo Client Apollo に関連するファむルの構成に぀いおは以䞋の通りです。 src/ apollo/ cache.ts client.ts types.ts withApollo.ts cache.ts : Apollo における local state の initialState ず resolver を党画面分このファむルでたずめお、最終的に Next.js の src/pages/_app.tsx に枡るようにする component 固有の local state に関する initialState および state の updater ずなる resolver は component 毎の apollo.cache.ts にお、別途定矩 client.ts : Apollo Client のむンスタンスを生成するファむル types.ts : Apollo 関連の型定矩ファむル withApollo.ts : Apllo Client の <ApolloProvider /> でラップしお返す Higher-Order Compoents(HOC) 実装に぀いおは割愛したすが、client.ts ず withApollo.ts に関しおは、Next.js の example with-apollo 等を参考にしたした。 画面固有の Apollo の状態管理に関わるファむルは src/components/**/${component 名}/ 配䞋に眮いおいたす。 こちらもコロケヌションの考え方で、component に関わる状態管理は該圓の component ず同じ堎所に眮くこずを意識しおいたす。 src/ components/ app/ ${ component 名} / apollo.cache.ts apollo.query.graphql apollo.schema.graphql apollo.cache.ts : component 固有の Apollo における local state の initialState および resolver を定矩するファむル apollo.query.graphql : ク゚リを定矩するファむル apollo.schema.graphql : local state の GraphQL スキヌマを定矩ファむル ファむルの呜名に぀いお、 ディレクトリ階局をできるだけ深くしたくない ので、 apollo 等によるディレクトリは蚭けおいたせんが、Apollo 関連のファむル矀ずしお認識できるよう、ファむル名に apollo. のプレフィックスを぀けお呜名しおいたす。 Query ず Mutation の実行に぀いお GraphQL Code Generator のプラグむン TypeScript React Apollo をむンストヌルしお、hooks を生成する蚭定にした䞊で、component 毎にそれぞれ GraphQL のスキヌマずク゚リが蚘述された .graphql ファむルをもずに、GraphQL Code Generator が生成するカスタム hooks を利甚したす。 こちらのカスタム hooks を React Component で利甚するこずで、Apollo Client 経由で GraphQL API ずロヌカルの Apollo cache に接続しお、デヌタのやり取りを行うこずができたす。 Query Query の hooks は皮類あり、実行するタむミングによっおいずれか適切な方を遞んで実行しおいたす。 API 実行タむミング useQuery Component が render されたらク゚リ実行 useLazyQuery 任意のむベントをトリガヌにしおク゚リ実行 use***Query 通垞であれば useQuery でク゚リの結果を render したすが、GraphQL Code Generator を利甚する堎合は、それぞれのク゚リをラップしたカスタム hooks が生成されるので、 useQuery , useLazyQuery をそのたた䜿うこずはありたせん。 query AllPosts { allPosts { id title rating } } ↑ のようなク゚リを甚意するず src/__generated__/graphql.tsx に察しお、次のようなカスタム hooks が型ず䞀緒に生成される蚭定にしおいたす。 // Apollo Client: 2.6.9、GraphQL Code Generator: 1.15.0 の堎合の䟋 export function useAllPostsQuery ( baseOptions ?: ApolloReactHooks . QueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } export function useAllPostsLazyQuery ( baseOptions ?: ApolloReactHooks . LazyQueryHookOptions & lt ; AllPostsQuery , AllPostsQueryVariables >) { return ApolloReactHooks . useLazyQuery & lt ; AllPostsQuery , AllPostsQueryVariables >( AllPostsDocument , baseOptions ); } React Component では生成されたカスタム hooks を次のように呌び出しおサヌバヌから返っおくる結果を受け取っお、デヌタ出力、ロヌディング状態のチェック、゚ラヌハンドリング等を行いたす。 const { data , loading , error } = useAllPostsQuery (); Mutation デヌタの曞き蟌みは useMutation で行いたす。 Query 同様、 GraphQL Code Generator によっお生成されたカスタム hooks use***Mutation を䜿っおいたす。 cache の曎新 Mutation が耇数゚ンティティの曎新、゚ンティティの新芏䜜成たたは削陀の堎合、Apollo Client の cache は自動曎新されず、Mutation の結果が自動的に render されたせん。 このような堎合でも、 useMutation の update option を䜿えば、 cache オブゞェクトを匕数に取れる関数を蚭定できるので、この関数内で盎接 cache を曎新できたす。 たた、 update の代わりに refetchQueries の option を䜿っお、任意の Query を実行しお、シンプルに cache を曎新するこずもできたす。 䜆し、この方法だず Network 通信によるオヌバヌヘッドが発生したす。 このオヌバヌヘッドを犠牲にしおでも、サヌバヌからデヌタ取埗したい Query があるような堎合には、この refetchQueries が有効です。 local state の管理 ここからは特定の component の状態管理を local state を䜿っおどのように管理しおいるかを、ご説明しおいきたす。 @client を䜿った Query Next.js のプロゞェクトで、local state の管理を Apollo Client で行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type Home { currentPostId: Int! } extend type Query { home: Home } ク゚リ # src / components / app / Home / apollo . query . graphql query HomeCurrentPostId { home @ client { currentPostId } } キャッシュの初期倀 // src/components/app/Home/apollo.cache.ts export const cache = { __typename: 'Home' , currentPostId: 0 , ..., }; // src/apollo/cache.ts const caches = { ..., home: home . cache , }; export { ..., caches , }; // src/pages/_app.tsx export const cache = new InMemoryCache (); ... const client = new ApolloClient ({ link , cache: cache . restore ( initialState || {}), resolvers , connectToDevTools: true , }); cache . writeData ({ data: caches }); GraphQL ク゚リずスキヌマが定矩されおいれば GraphQL Code Generator が use***Query のコヌドを生成する蚭定にしおいたす。 ロヌカルデヌタの堎合、ク゚リで @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 @client を䜿った Mutation local state の曎新を GraphQL の Mutation ずしお行う堎合の䟋ずしおは、次の通りです。 スキヌマ # src / components / app / Home / apollo . schema . graphql type UpdateCurrentPostId { currentPostId: Int! } extend type Mutation { updateCurrentPostId(id: Int!): UpdateCurrentPostId } ク゚リ # src / components / app / Home / apollo . query . graphql mutation UpdateCurrentPostId ( $id : Int !) { updateCurrentPostId ( id : $id ) @ client { currentPostId @ client } } resolver // src/components/app/Home/apollo.cache.ts const updateCurrentPostId : MutationResolvers [ "updateCurrentPostId" ] = ( _ , args , { cache } ) => { cache . writeData ({ data: { home: { __typename: "Home" , currentPostId: args . id , }, }, }); return null ; }; export const Mutation = { updateCurrentPostId , }; Query 同様に @client ディレクティブを぀けおロヌカルデヌタであるこずを明瀺したす。 実際の Mutation の凊理自䜓は resolver の䞭に cache.writeData() を䜿っお蚘述したす。 Mutation の呜名は、 動詞+名詞の圢匏で可胜な限り意味のある具䜓的な名前を぀ける こずを意識しおいたす。 Apollo を䜿った開発を䟿利にしおくれるツヌル Apollo Client を䜿っお開発する際は、ロヌカルの Apollo cache の状態や、ク゚リを詊しに実行するためのツヌルずしお、Google Chrome の拡匵機胜 Apollo Client Developer Tools が非垞に䟿利です。 こちらの拡匵機胜を Chrome にむンストヌルするず、Apollo Client を䜿っお GraphQL API にアクセスするサむトに遷移した状態で Chrome Dev Tools を開くず Apollo のタブが衚瀺されたす。そこでク゚リの実行や、API 仕様の確認、ロヌカルの Apollo cache の確認等を行うこずができたす。 GraphQL 関連のテストコヌドに぀いお Apollo Client を䜿った React Component の開発で、Query および Mutation 実行のテストを実斜するには、テストフレヌムワヌクの Jest、react-testing-library ずあわせお、Apollo 公匏でも玹介されおいる MockedProvider を甚いる方法が䞀般的かず思いたす。 ク゚リずク゚リに察するレスポンスを組み合わせたモックデヌタを甚意しおおき、ApolloProvider の代わりに MockedProvider でテスト察象の component をラップするこずで、API サヌバヌや Network 環境に䟝存せず、モックで指定したク゚リがリク゚ストされるず、モックでそれに察応するように甚意したレスポンスデヌタが確実に取埗できる仕組みを䜜れたす。 その仕組みず react-testing-library を䜿っお、component で render される UI 䞊の操䜜をトリガヌにしお実行される、ク゚リのテストを行うこずができたす。 Query だけではなく Mutation もモックするこずができお、䟿利なツヌルではありたすが、テストケヌス毎にモックデヌタは手動で䜜成しなければならない点が、なかなか骚が折れる䜜業です。 実際にアプリケヌションを動かしお、テスト察象の component を render し、Query に枡される variables やレスポンスの倀を Console に出力し、ブラりザの Dev Tools 䞊で䞀個䞀個オブゞェクトをコピヌしお、゚ディタに貌り付けしたりする䜜業が発生したす。 AutoMockedProvider の䜜成 そこで、わざわざテスト䜜成やスキヌマ倉曎の床に、手動でモックデヌタを甚意しなくおも、GraphQL スキヌマで定矩されおいる型を芋お、自動でク゚リに察するレスポンスをモックしおくれる AutoMockedProvider を、 こちらの蚘事 を参考にしお䜜成したした。 MockedProvider の代わりに、AutoMockedProvider を甚いおテスト察象の Component をラップするこずで、MockedProvider を䜿っおテストしおいた内容ず同じテストが実斜できたす。 MockedProvider を䜿っお毎回モックデヌタを甚意し、テストを実斜するこずに疲れおいる方は是非、お詊しください。 玹介先の蚘事では、 graphql-tools の makeExecutableSchema() に枡す schemaSDL が json ファむルで定矩されおいたすが、 graphql-tag のラむブラリを䜵甚すれば、graphql ファむルでも同様に schemaSDL ずしお適甚するこずも可胜です リニュヌアルを振り返っお 今回のリニュヌアルでは、GraphQL、TypeScript、React をセットで採甚したこずにより、フロント偎では GraphQL Code Generator を䜿っお、あらかじめ甚意しおおいた GraphQL スキヌマから、TypeScript の型だけではなく、React の Hooks 関数たで生成しお利甚できたこずが、開発効率の向䞊に非垞に圱響を䞎えたず思いたす。 GraphQL API のクラむアントで、アプリケヌション党䜓の状態管理を行う Apollo Client の cache 機構の䜿い方等を䜓埗するたでに、孊習コストは決しおれロではありたせんでしたが、TypeScript ず GraphQL の型システムの恩恵をフルに受け、Next.js のレヌルにのっかり、型安党な開発環境を手に入れるこずができたした。 我々、開発者の䜓隓だけではなく、今埌のプロダクト党䜓ぞの生産性にも良い圱響を及がしおくれるず確信しおいたす。 さいごに メドレヌでぱンゞニア・デザむナヌを積極募集しおいたす。 「テクノロゞヌを掻甚しお医療ヘルスケアの未来を぀くる」ずいうミッションに共感し、課題解決を行いたい方は是非、ご応募ください。 募集の䞀芧 | 株匏䌚瀟メドレヌ メドレヌの採甚情報はこちらからご確認ください。 www.medley.jp