ロコガイド テックブログ

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの社員がいろいろな記事を書いています。

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの社員がいろいろな記事を書いています。

不明確な要件の解像度を上げていく開発の話

f:id:littlestarling:20201223102742p:plain

開発部の小椋です。普段はサーバサイドの開発をしたり、小ネタをこねたり、野菜を育てたりしています。
この記事はロコガイド Advent Calendar 2020の23日目です。
前日は金子さんの エッジケースエラーをチームで低減させた話 でした。

先ごろ、トクバイではスポットライト動画という機能をリリースしました
トクバイアプリ上では「動画でお知らせ」というセクションが追加されています。
現在小売店の担当者の方が商品やお知らせを投稿して配信するフローに、動画投稿が加わったイメージです。
運用時にはこれまでの操作とさほど変わらず、よりお得な商品をユーザーに注目してもらえる効果を期待しています。

わたしたちにはいわゆる広告商品の動画配信オペレーションを行った実績はありましたが、自前の動画配信の仕組み作りは初めての経験でした。今回は機能を作り上げるにあたってぶつかった課題と、その解消に向けた取り組みの流れをご紹介します。

エンジニアとしての関わり

主に広告系商品の開発の場合、企画については営業やマーケティング担当と開発ディレクターの間で開発要件をまとめ、エンジニア側での技術設計を経て実装に入っていきます。
今回も同様ではありましたが、動画の取り扱い、配信ノウハウがないことや、外部のサービスとの連携など全体的に不明確な要素が多かったです。そのため、開発要件の検討段階から技術面での懸念がないか相談を受けていました。
このようにすることで、オペレーションの練り上げはディレクターにおまかせしつつ、事前に懸念点を洗い出す時間をとることができました。

要件を考える

まずは要件を考えます。アプリへの動画配信となるのですが、ユーザーは外出時に閲覧するケースが多いと考えられます。そうなると通常の動画ファイルだと、ダウンロードが完了しないと再生できないため、待ち時間が発生しUXを損ねることになります。このような場合にはHLS形式でのストリーム配信方式が適していると想定されます。
ただ動画のHLS形式へ変換は結構面倒な要素が多いため、担当者が変換して入稿するオペレーションは取りづらく、システム側に動画形式の変換機能を組み込むことになりそうです。

また、配信にあたってCDNの利用は前提になります。そのためインフラチームとも連携して進めていくことになります。

これらから、以下がシステム側で実装すべき要件になりました。

  • 担当者は通常の動画を入稿し、システム側でファイル形式を変換する
  • 適切な場所に公開し、その公開URLをAPI経由でアプリに返す

開発の進め方

アプリ側もプレイヤーの組み込み・検証が必要になるため、まずは先にAPIを定義し、サンプルの動画を用意してから前段階のつなぎこみをしていくようにしました。プレイヤーの導入については明日yokomiiさんがエントリーをあげてくれるのでそちらをご参照ください。

まずはテスト用の動画を変換します。これにはffmpegを利用しました。ドキュメントのhlsオプションを参考に以下のようなコマンドを実行します。この場合は1080pから240pまでの解像度で動画ファイルを変換出力します。

ffmpeg -i ~/source.mp4 \
  -filter:v:0 scale=1920:-2 -c:v:0 h264 -c:a:0 aac -b:a:0 192k \
  -filter:v:1 scale=1280:-2 -c:v:1 h264 -c:a:1 aac -b:a:1 128k \
  -filter:v:2 scale=854:-2 -c:v:2 h264 -c:a:2 aac -b:a:2 128k \
  -filter:v:3 scale=640:-2 -c:v:3 h264 -c:a:3 aac -b:a:3 96k \
  -filter:v:4 scale=426:-2 -c:v:4 h264 -c:a:4 aac -b:a:4 64k \
  -map 0:v -map 0:v -map 0:v -map 0:v -map 0:v \
  -map 0:a -map 0:a -map 0:a -map 0:a -map 0:a \
  -f hls -hls_time 3 -hls_list_size 0 -master_pl_name master_playlist.m3u8 \
  -hls_segment_filename "v%v_source%3d.ts" \
  -hls_playlist_type vod \
  -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 v:3,a:3 v:4,a:4" \
  %v-output.m3u8

生成された各ファイルをテストサーバに準備し、生成されたマスタプレイリストのURLを返す準備をします。

動画の変換

実際の動画変換には、弊社ではAWSをメインに利用していることもあり、AWS Elemental MediaConvert(以下MediaConvert)の利用が妥当な選択と判断しました。

MediaConvertでは入力ソースファイル、生成オプション、出力設定をして個別のファイル変換ができます。定型的に使う場合はジョブテンプレートに基づいたジョブ実行が可能です。設定値は解像度、セグメント長、QVBRレベルくらいの調整で問題ないでしょう。

また、何らかの理由で再生ができなかった場合のオルタネイト要素としてサムネイルを出力しておくとUXを損ねにくくなります。MediaConvertで出力アウトプットの JPEG へのフレームキャプチャ を追加し、フレームレートとキャプチャ数を指定することである程度の秒数のコマを抽出できます。試行錯誤の結果、2.8秒程度のコマをサムネイルにすると比較的シズル感が出そうという結論になりました。
ジョブ実行はS3にソースファイルがアップロードされたことをトリガーに、AWS Lambdaによって実行します。変換完了の状態をどう把握するかですが、再生リストのマスタファイルとサムネイルがあれば変換完了しているとみなすことにしました。これらが変換出力先パスに存在しているかどうかを定時バッチで監視し、存在していれば再生リストURLとサムネイルの転記を行い、ステータスを 配信準備完了状態 にします。

コスト問題

自前配信をするには、配信データ量のコストも意識する必要があります。配信コストが利益を超えてしまうようではサービスとして成立しないためです。キャッシュヒット率のよい場合悪い場合において、トップページリクエストにデータ配信が乗ってきた場合のシミュレーションを行い、ビジネスサイドと調整しました。

これらの仕様検討や開発を進めている状況でも、いくつかのオペレーションが定まらない状態にありました。例えば動画作成の外部サービスとのつなぎ込みが決めきれなかったことなどがその理由です。このあたりは別途外部サービス側との調整が必要と判断して、最低限のフローで進められるようディレクターと運用フローを整理しました。調整ごとはしばしば開発のブロッカーになりがちですが、今回は止めずに進めるためのコミュニケーションを密にとることができました。

まとめ

このようにしてなんとかリリースを迎えました。粛々とこなしていったように書きましたが実際には「なるほど、わからん...」と頭を抱えていた状況もありました。また、急な差し込みタスクが発生して同僚にヘルプをお願いして進めていったところもあります。コロナ禍の状況でわたしたちも原則リモートワークをしていますが、必要な時にコミュニケーションを随時とることができました。これが不確実性の高かったプロジェクトをそれなりに着地させられた要因ではないかと考えています。

もちろん、リリースして終わりというわけではありません。ちょうど世の中的にブラックフライデーキャンペーンを各社が展開している時期でもあったためか、動画の1日あたりの配信コストが試算の10倍になってしまう日がありました。こちらのコスト圧縮のための調整は配信状況を鑑みながら進めています。
ユーザーの立場で見ると、ちょっとしたコーナーが増えただけになりますが、そこに至るまでの道筋は一筋縄ではいきませんでした。不明要素が多かった分、ビジネスサイド、開発サイドそれぞれのコミュニケーション密度が上がりました。プロジェクトメンバー間の適切なコミュニケーションが大事という話ですね。残念ながら、日次のチーム会は音声ベースで進めていたこともあって具体的なやり取りのログをここでご紹介できませんでした。今後はプロジェクト進行において有効だったやり取りの例も拾っていけるようにしたいです。

明日はyokomiiさんのスポットライト動画の再生側のtips紹介 ExoPlayer in Carouselを実現するための手引き です。お楽しみに。