Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
DRMを導入した話
Search
Kota Yoshikawa
May 29, 2026
Programming
57
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
DRMを導入した話
AndroidアプリでDRMを導入した話をLT枠でお話ししました
https://droidkaigi.connpass.com/event/391168/
Kota Yoshikawa
May 29, 2026
More Decks by Kota Yoshikawa
See All by Kota Yoshikawa
Android OSのバージョンアップに追従するためにすべきこと
clown6613
0
63
Other Decks in Programming
See All in Programming
わからない話を追いかけたら、プログラミング言語を作る側にいた
ydah
3
540
React本体のコードリーディング
high_g_engineer
1
150
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
360
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
230
Go を使い始めて 2 ヶ月の学び / My first two months with Go
contour_gara
0
360
Cloudflare is Agents
chimame
0
180
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
160
不幸な GC
chencmd
0
610
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
510
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.4k
VibeCodingからAgenticWorkflowへ
starfish719
0
760
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
220
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
Abbi's Birthday
coloredviolet
3
9.4k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
360
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Practical Orchestrator
shlominoach
191
12k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
400
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Transcript
DRMを導入した話 2026/5/29 DroidKaigi.collect { #30@Tokyo }
About Me Kota Yoshikawa (吉川 晃太) @clown6613 clown6613 CyberAgent, Inc.
DRM / Widevineとは DRM(Digital Rights Management) デジタルコンテンツの著作権管理技術の総称 コンテンツの再生条件をライセンスで管理する仕組み コンテンツをスクショや録画から守る Widevine
プレミアムメディア向けの Google のコンテンツ保護システム 3段階のセキュリティレベル L1 : Trusted Execution Environment(TEE)内で復号・デコード L2 : TEE内で復号のみ L3 : ソフトウェア処理
なぜDRMが必要か ビジネス観点 コンテンツホルダーとの契約や配信要件 不正録画/再配布による収益損失の防止 技術観点 root化している端末ではFLAG_SECUREによる保護を回避できてしまう Trusted Execution Environment(TEE)というSecureなOS領域での復号が 可能でroot化端末での読み取りが難しい
参考:https://source.android.com/docs/security/features/trusty
Widevineの導入方法 Certified Widevine Implementation Partner Program(CWIP) 自社でWidevineライセンスサーバーを 構築・運用できるようになる ⚠️ 認定プロセスに時間とコストがかかる
Google認定のパートナーになる ライセンスサーバをSaaSとして提供 認定プロセスなしで導入開始できる 導入が比較的早い サーバーの運用・保守が不要 ⚠️ 利用料に応じた費用が発生する DRMベンダーを利用する
Widevineの導入方法 Certified Widevine Implementation Partner Program(CWIP) 自社でWidevineライセンスサーバーを 構築・運用できるようになる ⚠️ 認定プロセスに時間コストがかかる
Google認定のパートナーになる ライセンスサーバをSaaSとして提供 認定プロセスなしで導入開始できる 導入が比較的早い サーバーの運用・保守が不要 ⚠️ 利用料に応じた費用が発生する DRMベンダーを利用する
DRMベンダーを利用したシーケンス 初回のみデバイス証明書の発行 自社で建てたプロキシサーバーを経 由してDRMベンダーへライセンス のリクエスト Playerがライセンス情報を読 み取りコンテンツを復号
今回の主な実装内容 背景:既存実装はHLSのみ対応。DRM保護されたDASHコンテンツの再生には未対応だった DASH再生への対応 ExoPlayerに DashMediaSourceを組 み込み MPD形式のマニフェス トを解析/再生できるよ うに対応 ExoPlayerに
DashMediaSource を組み込み MPD形式のマニフェ ストを解析/再生でき るように対応 ライセンスリクエストの実装 自社プロキシサーバーへ のライセンスリクエスト client情報と認証ヘッ ダーをつけてDRMベン ダーへ中継 必要に応じてログの実装 DrmSessionManagerの実装 MediaDrm Callbackの実 装やDRMセッションの設 定 client情報と認証ヘッダー をつけてDRMベンダーへ 中継
DRM周りの実装例 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class CustomMediaDrmCallback( private val licenseUrl: String, private val authToken: String, ) : MediaDrmCallback { override fun executeProvisionRequest( uuid: UUID, request: ExoMediaDrm.ProvisionRequest ): ByteArray { // プロビジョニングはWidevineサーバーへ直接 return HttpUtil.executePost( request.defaultUrl, request.data, emptyMap() ) } override fun executeKeyRequest( uuid: UUID, request: ExoMediaDrm.KeyRequest ): ByteArray { // 自社Proxy Serverへライセンスリクエストを送信 val headers = mapOf( "Authorization" to "Bearer $authToken", "Content-Type" to "application/octet-stream" ) return HttpUtil.executePost( licenseUrl, request.data, headers ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun buildDrmSessionManager( licenseUrl: String, authToken: String, ): DrmSessionManager { val callback = CustomMediaDrmCallback( licenseUrl = licenseUrl, authToken = authToken, ) return DefaultDrmSessionManager.Builder() .setUuidAndExoMediaDrmProvider( C.WIDEVINE_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER ) .setMultiSession(false) .build(callback) }
DRM周りの実装例 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class CustomMediaDrmCallback( private val licenseUrl: String, private val authToken: String, ) : MediaDrmCallback { override fun executeProvisionRequest( uuid: UUID, request: ExoMediaDrm.ProvisionRequest ): ByteArray { // プロビジョニングはWidevineサーバーへ直接 return HttpUtil.executePost( request.defaultUrl, request.data, emptyMap() ) } override fun executeKeyRequest( uuid: UUID, request: ExoMediaDrm.KeyRequest ): ByteArray { // 自社Proxy Serverへライセンスリクエストを送信 val headers = mapOf( "Authorization" to "Bearer $authToken", "Content-Type" to "application/octet-stream" ) return HttpUtil.executePost( licenseUrl, request.data, headers ) } } Widevineサーバーへ のリクエスト デバイス証明証 の発行 プロキシサーバーへ のリクエスト 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun buildDrmSessionManager( licenseUrl: String, authToken: String, ): DrmSessionManager { val callback = CustomMediaDrmCallback( licenseUrl = licenseUrl, authToken = authToken, ) return DefaultDrmSessionManager.Builder() .setUuidAndExoMediaDrmProvider( C.WIDEVINE_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER ) .setMultiSession(false) .build(callback) }
実装時にはまったポイント multiSessionの設定 1コンテンツに対して複数の鍵が必要な場合に有効にする(キーローテーションとか) 配信設定で映像と音声で異なる鍵が設定されており、音声しか流れないような現象が発生 エミュレータでのデバッグ L3での検証が限界、動作確認は実機推奨 エミュレータではビルドのたびにprovisionRequestが必要 うまく動かない時はその箇所を見直して正常に動くことがあった Player.Listener#onMetaDataで値が検知できない DASHでの再生に対応する中で、onMetaDataにEventStreamが流れてこなくなった
実装時にはまったポイント multiSessionの設定 1コンテンツに対して複数の鍵が必要な場合に有効にする(キーローテーションとか) 配信設定で映像と音声で異なる鍵が設定されており、音声しか流れないような現象が発生 エミュレータでのデバッグ L3での検証が限界、動作確認は実機推奨 エミュレータではビルドのたびにprovisionRequestが必要 うまく動かない時はその箇所を見直すと良い Player.Listener#onMetaDataで値が検知できない DASHでの再生に対応する中で、onMetaDataが流れてこなくなった
実装時にはまったポイント multiSessionの設定 1コンテンツに対して複数の鍵が必要な場合に有効にする(キーローテーションとか) 配信設定で映像と音声で異なる鍵が設定されており、音声しか流れないような現象が発生 エミュレータでのデバッグ L3での検証が限界、動作確認は実機推奨 エミュレータではビルドのたびにprovisionRequestが必要 うまく動かない時はその箇所を見直して正常に動くことがあった Player.Listener#onMetaDataで値が検知できない DASHでの再生に対応する中で、onMetaDataにEventStreamが流れてこなくなった
まとめ DRMは「動けば終わり」ではなく、映像・音声の鍵管理・セッション設計など細かい設定が再生 品質に影響する Widevineの仕様はドキュメントが少なく、実際に動かしながら挙動を確認する試行錯誤が必要 エミュレータとの挙動, multiSessionの設定など、見落としやすいポイントが多い クライアント側の実装自体は多くないが、バックエンドの実装者とのコミュニケーションをとり ながら設定を決めていく必要がある drm-test: https://github.com/clown6613/drm-test