はじめに

こんにちは。24卒で新卒入社予定の土田祐将です。

今回、内定者アルバイトとして2ヶ月間、株式会社AbemaTVのコンテンツエンジニアリングチームでお世話になりました。

本記事では、2ヶ月間で取り組んだABEMAの映像流出対策について紹介します。

動画プレビューの機能提供における課題

mam tool とは

ABEMAには、年間数万本・数ペタバイト級の動画コンテンツが入稿されます。コンテンツエンジニアリングチームでは、これらの膨大なコンテンツ資産を高度に管理するため MediaAssetManagement (以下 MAM )と呼ばれるシステムをクラウド上に構築しています。
一例として AbemaTV の MAM では以下のような機能を提供しています。

  • トランスコードワークフロー
  • メタデータ管理
  • コンテンツのアーカイブ
  • 動画編集
  • 動画解析
  • 販促管理
  • 権限管理

MAM に格納された動画のプレビュー

MAM は AbemaTV 社内のコンテンツ管理者に対して Web ブラウザでアクセスできるインターフェイスを提供しています。コンテンツ管理者は権限を割り当てられたコンテンツのプレビュー動画を視聴することができます。 これは主に、「映像品質に問題ないか確認する」、「欲しい映像があるか探す」などの目的で使用されます。

MAMでのプレビュー
MAMでのプレビュー

しかし、このプレビュー機能は一歩間違えると重大な問題につながることが予想されます。

コンテンツ流出の危険性

MAMは、AbemaTVが制作した映像に加え、外部から調達したコンテンツも管理します。そのため、地上波や他社サービスで未公開であるコンテンツも、管理者はそれらの映像をプレビューすることができます。

もちろん、正当な目的でプレビューをすることは問題はありません。

しかし、もし悪意を持つ管理者がいれば、未公開映像のプレビューを保存し、SNS等を通して流出させることができてしまいます。

無論、プレビューのダウンロード等は禁止していますが、画面録画やスマートフォンで直接画面を撮影されたら防ぎようがありません。

そこで今回、内定者アルバイトのテーマとして「MAM上のプレビューに対する動画流出対策」に取り組むことになりました。

MAM上のプレビューに対する動画流出対策

動画の流出対策として、今回は「知覚可能型ウォーターマークの付与」という方法を導入しました。

知覚可能型ウォーターマーク

知覚可能型ウォーターマークとは、目的の映像に透かしをいれる手法です。 実際には、プレビューしている管理者のIDを映像に入れてトランスコードする、という手法を取りました。

MAMでのユーザIDが入ったプレビュー
MAMでのユーザIDが入ったプレビュー

これによって以下の2つが期待されます。

  • 映像自体に管理者IDを含めることで流出の抑止力となる。
  • 映像が流出しても、プレビューに載った管理者IDから誰が流出させたかを特定できる。

懸念点

知覚可能型ウォーターマークを載せることで、流出対策という目的は達成されますが、懸念される点がいくつかあります。

1. 全動画に対するプレビューの事前準備は不可能

冒頭でも紹介したように、MAMにはペタバイト級のコンテンツが保存されています。そのため、それらすべての動画に対して、尚且つすべての管理者IDに対して、プレビューを事前作成するのは現実的ではありません。

2. プレビューの権限管理

ウォーターマーク付きプレビューの権限には気をつけなければいけません。

もし、UserA(管理者ID) が透かしてあるプレビューを UserB が取得でき、流出させたら…

➡️ プレビューにはUserAが載っているため、UserAが容疑者になってしまう

このように、自身の管理者IDが透かしてある動画は別の管理者からは決してアクセスできないようにする必要があります。

要件

1. スムーズにプレビューの再生を始められること

プレビューの事前準備をしないという制約の上で、再生ボタンが押されてから実際に再生が開始されるまでの時間をできるだけ短くしたいです。これは管理者の利便性を損ねないためにも必要だと考えます。

2. クライアントに特殊な実装を持たせないこと

プレビューに管理者IDが記載されるようになるという変更は、本来バックエンド側のみの変更であるはずなので、クライアント側に特殊な実装をすることは避けたいです。

成果物

MAMでプレビューを要求した際に、要求した管理者のIDが含まれた動画が再生されるようになりました!

以下ではその仕組みを説明します。

オンザフライ プレビュー生成による動画流出対策

先ほど紹介した通り、「全動画に対するプレビューの事前準備は不可能」 です。

そこで、管理者がプレビューをリクエストしたときに、その場でプレビューの生成をすることにしました。

その場でトランスコードを開始
その場でトランスコードを開始

ここで疑問が生まれると思います。

Q. リクエストが来てからプレビューを生成すると時間がかかりそうだけど?

その通りです。そこで、AWS Elemental MediaConvert + HLS を採用しました。

AWS Elemental MediaConvert

AWS Elemental MediaConvert は、ブロードキャストグレードの機能を備えたファイルベースの動画変換サービスです。ブロードキャストおよびマルチスクリーン配信用のライブストリームコンテンツを大規模に作成します。 AWS Elemental MediaConvert

HLS (HTTP Live Streaming)

Send live and on‐demand audio and video to iPhone, iPad, Mac, Apple Watch, Apple TV, and PC with HTTP Live Streaming (HLS) technology from Apple. Using the same protocol that powers the web, HLS lets you deploy content using ordinary web servers and content delivery networks. HLS is designed for reliability and dynamically adapts to network conditions by optimizing playback for the available speed of wired and wireless connections. HTTP Live Streaming

HLSは、動画を分割したセグメント (.ts) と 再生の順番が書いてあるマニフェスト (.m3u8) に分かれています。

HLS
HLSのファイル

 

MediaConvert はウォーターマーク画像を合成しつつ、HLSにトランスコードしてくれます。

そして、HLSにトランスコードする際、MediaConvertはその時点で完了したトランスコード分の映像に対する、マニフェスト、セグメントをS3に適宜出力してくれます。

そのため、目的の動画のトランスコードが完了する前に、マニフェストを参照することで、トランスコードが終わった分の再生を開始することができます。

こうして、オンザフライのトランスコードでも実用的な待機時間で視聴することができるようになりました。

プレビューの流れ

まず、プレビューの流れを説明します。

プレビューの流れ
プレビューの流れ

① 動画へのアクセス許可の取得

試聴したいプレビューへのアクセス許可をAPIサーバに要求します。

APIサーバでは、アクセスしてきた管理者の情報をもとに、プレビューに対する権限を付与する署名を作成し、返却します。

② プレビューの取得

プレビューを取得します。

①で取得した署名をリクエストに付与し、署名の検証を行います。

権限を持っていることを確認できたら、その場でプレビューを生成し、返します。

アーキテクチャ

今回はAWSを用いて上記の流れを実現させました。

以下は採用したアーキテクチャです。

アーキテクチャ図
アーキテクチャ図

API for MAM

アーキテクチャ (API for MAM)
アーキテクチャ (API for MAM)

これはプレビューの流れで示した①を担当します。

API for MAMはMAMの裏側で動くAPIであり、ここにプレビュー試聴の権限付与の処理を追加しました。

構成は、API Gateway + Lambda + Systems Manager(Parameter Store)です。

  1. 管理者はMAMから見たい動画を選択します。
  2. 選択をトリガーとしてAPIに「署名付きCookie」を要求します。
  3. API (Lambda) は、リクエストした管理者用のプレビューに対するアクセス許可を含んだ署名を生成します。
  4. ブラウザは、APIから取得した署名付きCookieを保存します。

署名付きCookie

ここでの署名付きCookieは、CloudFront署名付きCookieを指します。

CloudFront 署名付き Cookie を使用すると、現在の URL を変更したくない場合や、複数の制限付きファイル (ウェブサイトの購読者の領域にあるすべてのファイルなど) へのアクセスを提供する場合に、誰がコンテンツにアクセスできるかを制御できます。 署名付き Cookie の使用

署名付きCookieを用いることで、複数のファイルに対する権限や、有効期限を柔軟に設定することができます。

実際に用いている署名の形式は以下の通りです。

{
    "Statement": [
        {
            "Resource": "https://***.***/users/{管理者ID}/{元動画のバケット}/{動画ID}/*",
            "Condition": {
                "DateLessThan": {
                    "AWS:EpochTime": {署名の有効期限}
                }
            }
        }
    ]
}

CloudFrontの署名付きCookieでは「*」を用いてパス配下のアクセスを全て許可することができます。

そこで、動画ごとにディレクトリを作成し、ここにHLSのマニフェストやセグメントを格納します。

そうすることで、その動画に対する視聴権限を持つ署名を作ることができます。

MAM HLS Proxy

アーキテクチャ (MAM HLS PROXY)
アーキテクチャ (MAM HLS PROXY)

これはプレビューの流れで示した②を担当します。

  1. API for MAMで生成した署名付きCookieと共にCloudFrontへプレビューのマニフェストを要求をします。
  2. Lambda@Edgeでプレビューを管理するS3にマニフェストが存在するかを確認します。
    – 存在しない場合、MediaConvertにプレビュー作成のジョブを追加します。
  3. 現時点で、S3に存在するMediaConvertが出力したセグメントを取得します。
  4. イントロセグメントと 3 で取得したセグメントの情報から自力でマニフェストを生成します。
  5. 作成したマニフェストを返却します。

クライアント側はマニフェストを定期的にフェッチすることで、トランスコードされた分の動画を継続的に再生することができます。

補足1 自力でマニフェストを生成

HLSで動画を再生するにはマニフェスト+複数のセグメントが必要です。 マニフェストに記載されたセグメントの再生順番を読んでクライアントは再生します。

MediaConevertはトランスコードの進捗に応じて、マニフェストを更新し続けてくれるという話でした。そのままマニフェストを返せば、トランスコードできた部分まで再生することができるはずです。

では、なぜそうしないかというと、MediaConvertの仕様変更でトランスコード中にマニフェストを出力しないようになってしまったからです。(セグメントは適宜追加されます。)

そうなると、トランスコードが終わってからしかマニフェストを取得できず、再生を要求してから多くの時間が必要になってしまいます。そこで、どこまでセグメントが出力されたかを取得し、自力でマニフェストを作成する仕様になりました。

マニフェストの例:トランスコード中 (トランスコードが完了していない時)
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:EVENT
#EXTINF:0.500000,
intro.ts
#EXT-X-DESCONTINUITY
#EXTINF:3.000000,
main1.ts

この時、「#EXT-X-PLAYLIST-TYPE」は「EVENT」になっています。

これは、ストリームが生配信であることを意味するため、クライアントは新しいセグメントを再生するために、定期的にマニフェストをフェッチします。

マニフェストの例:トランスコード完了時
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:0.500000,
intro.ts
#EXT-X-DESCONTINUITY
#EXTINF:3.000000,
main1.ts
#EXTINF:3.000000,
main2.ts
#EXT-X-ENDLIST

この時、「#EXT-X-PLAYLIST-TYPE」は「VOD」になっています。

これは、ストリームが生配信でない(マニフェストは更新されない)ことを意味するため、それ以降、クライアントはマニフェストを定期的にフェッチすることをやめます。
MediaConvertがトランスコード中は、クライアントは定期的にマニフェストをフェッチし、トランスコードが終了すれば、それ以降はマニフェストをフェッチしません。

こうすることで、プレビューを要求してからできるだけ短い時間での再生を可能にしています。

補足2 イントロセグメント

プレビューがない状態で再生を要求すると、Lambda@EdgeでMediaConvertのジョブを作成します。 その後、セグメントが出力され始めたら再生ができるようになるわけですが、出力され始めるまでの待機時間の体験を改善するために導入したのがイントロセグメントです。

管理者は、再生を要求してもしばらくローディングの状態で、「ネットワークの調子が悪いのかな?」と思う可能性があります。

そこで、「少々お待ちください。ただいまプレビューを生成中です。」という内容の蓋絵としてマニフェストの先頭にセグメントを追加することにしました。これをイントロセグメントと呼んでいます。

補足1で示したプレイリストの例の「intro.ts」にあたるセグメントのことです。

intro.ts
intro.ts

まとめ

本記事では、ABEMAでのオンザフライ プレビュー生成による動画流出対策について紹介しました。

知覚可能型ウォーターマークを付与する方法を採用し、映像自体に管理者IDを含めることで流出の抑止力となり、映像が流出しても誰が流出させたかを特定できるようになりました。

また、プレビューにあたって体験を損ねないよう、オンザフライのトランスコードをAWS Elemental MediaConvertとHLS、CloudFrontとLambda@Edgeで実現させました。

これにより、プレビューの再生をスムーズに始められるようになり、プレビューの権限管理も適切に行うことができました。

今回の取り組みにより、ABEMAの映像流出対策が強化され、より信頼していただけるサービスに近づけたと考えています!

感想

エンジニアとして大きく成長することができました!

これまでは大学の研究の傍ら、個人開発を少し行う程度で、ここまで大規模な実務のシステムに触れることはありませんでした。

しかしこうして会社で働くと、メンターやチームメンバーの方々にサポートされながら、前例が少ないチャレンジングな開発に裁量を持って取り組むことができ、知識も技術も短期間で高めることができたと思います。

計25日間の中で、技術検証からトラブルの解決、実装、テスト、本番環境への適用まで一通りの流れをこなすことができ、非常に満足度の高い経験でした。

映像分野に興味のあるエンジニアの方、ABEMAおすすめですよ!

謝辞

今回、ABEMAのコンテンツエンジニアリングチームを始め、内定者アルバイトをするにあたって関わっていただいたすべての皆様に感謝を申し上げます。

メンターやチームの方々が内定者アルバイトの課題を一緒に考え、提案し、アドバイスしてくださったおかげで、自分一人では得ることのできない経験と知識、技術を身につけることができました!

今後も、エンジニアとして精進していこうという決意と共に、特に映像分野では誰にも負けないように力をつけていこうと思います。本当にありがとうございました!