エージェンティック広告が変える広告の未来 - 技術標準と実装事例から見る業界変革

はじめに

こんにちは。広告プロダクト担当の大野です。

去年あたりから、アドテク界隈でエージェンティック広告(Agentic Advertising)に関する話題が急速に盛り上がっています。IAB Tech LabがAAMP(Agentic Ad Management Protocols)という包括的なイニシアチブのもと、ARTF(Agentic Real Time Framework)などの業界標準仕様の策定を進めているほか、Amazon AdsGoogle AdsがMCP(Model Context Protocol)を活用したAIエージェント機能の提供を開始するなど、広告の新しいトレンドとして注目を集めています。

毎週のように様々なエージェンティック広告に関するアップデートがあるので、現状の動向の個人的な整理をかねて、この記事を書くことにしました。

エージェンティック広告がここまで盛り上がっているのは、当然ながら昨今のLLMの進化と、それによる技術革新が、様々な分野において、AIが人間の業務を代替できるという実績がでてきているからです。 広告業界においても広告運用やメディアプランニング、見積もりなどの作業は労働集約的な要素がまだ多く残っている状況です。

私も長年プログラマティック広告などの運用型広告に関連した仕事に携わっており、常々労働集約的な部分、専門性が高い部分の効率化や品質の再現性をどうするかというところは課題感をもっていました。

そんな中、AI技術の進化により、エージェンティック広告という新しいアプローチが、広告の運用や広告の未来を大きく変えそうな雰囲気をビシビシ感じています。

前置きが長くなりましたが、この記事では、AgenticAdvertising.orgによるAdCP(Ad Context Protocol)や、IAB Tech LabによるAAMPなどのエージェンティック広告を支える技術標準や最新事例を交えながら、エージェンティック広告の技術的なアーキテクチャ、従来手法との違い、現状の活用トレンド、今後の展望について解説したいと思います。

エージェンティック広告とは

エージェンティック広告(Agentic Advertising)とは、AIエージェントが広告のプランニング、バイイング、クリエイティブ最適化、効果測定といった一連の業務を自律的に判断・実行するアプローチを指します。ここでいう「エージェント(Agent)」は、単なる自動化ツールではなく、目標を与えられたら自ら状況を分析し、最適な行動を選択・実行できるAIシステムを意味します。この辺りがこれまでの人の作業のルール化を中心とした自動化と大きく異なります。

従来の自動化との違い

これまでも広告業界では、様々な自動化手法が取り入れられてきましたが、従来の自動化手法とエージェンティック広告には明確な違いがあります。

従来の自動化アプローチ: - ルールベース自動化: 人間が事前に設定したルール(例:「CTRが1%以下なら入札停止」)に従って機械的に実行 - 機械学習ベース最適化: 過去データから学習し、予測モデルに基づいて入札額やターゲティングを調整

エージェンティック広告の特徴

  • 自律的な判断: 状況に応じてAIが柔軟に判断
  • マルチステップの実行: 単一タスクではなく、複数の業務プロセスを連携して実行
  • 自然言語での指示:「新製品の認知度を高めたい」といった抽象的な目標から、具体的な施策を設計
  • 継続的な学習と改善: 実行結果をフィードバックし、次の判断に活かす

例えば、従来の自動入札では「CVRを最大化する」という目標に対して入札額を調整するだけです。一方、エージェンティック広告では「新製品の認知拡大」という目標に対し、ターゲット設定、メディア選定、クリエイティブ案の提示、配信スケジュール最適化まで一貫して提案・実行できます。特に後述するMCPやAdCPなどの登場により、AIエージェントが複数のメディアの情報を横断的に取得し、プランニングをするなど、これまで人間が担っていた業務をAIが自律的に行うことが可能になってきています。

広告領域での位置づけ

エージェンティック広告は、広告業務の以下の領域で活用が進んでいます:

  • プランニング: キャンペーン設計、メディアプラン策定、予算配分
  • バイイング: 媒体選定、入札戦略、在庫管理
  • クリエイティブ最適化: 広告素材の生成、A/Bテスト設計、パーソナライゼーション
  • 効果測定と分析: アトリビューション分析、レポート作成、改善提案

広告技術仕様を策定しているIAB Tech Labは、これらの領域における標準化や、既存の広告配信システム(DSP、SSP、DMPなど)とのスムーズな連携を可能にする技術仕様の策定を進めています。

技術的アーキテクチャ

エージェンティック広告は、複数の技術要素が組み合わさることで実現されています。ここでは、主要な技術要素について解説します。

主要な技術要素

1. LLMベースの意思決定エンジンとMCP統合

大規模言語モデル(LLM)を活用することで、自然言語での指示を理解し、複雑な広告戦略に変換します。GoogleやAmazonは、MCP(Model Context Protocol)を採用し、LLMやAIエージェントと広告APIをシームレスに統合する仕組みを提供しています。

Google Ads MCP: - Google Ads APIとLLM/エージェントを統合 - 自然言語でのキャンペーン情報取得や設定変更が可能 - GitHubでオープンソースとして公開され、開発者が自由に活用可能

Amazon Ads MCP: - Amazon Advertising APIへのプログラムアクセスを提供 - LLM/AIエージェントと広告APIの統合を実現 - オープンベータ版として提供開始

2. マルチエージェント協調

単一のAIエージェントではなく、複数の専門エージェントが協調して動作する仕組みが採用されています。

エージェント 役割
プランニングエージェント キャンペーン全体の戦略を設計
クリエイティブエージェント 広告素材の生成と最適化
バイイングエージェント 入札戦略の実行と調整
アナリティクスエージェント 効果測定と改善提案

3. 既存システムとの連携

エージェンティック広告は、既存の広告配信エコシステムと統合される形で実装されています。IAB Tech Labは、OpenRTB(リアルタイム入札)、AdCOM(広告コモンオブジェクトモデル)、OpenDirect(予約型広告取引)といった既存の広告取引標準と、MCP、Agent2Agent(A2A)、gRPCなどの現代的なプロトコルを統合する仕様を策定しています。

これにより、エージェンティック広告は以下のような既存システムとシームレスな連携が可能になります: - プログラマティック広告の入札・配信プラットフォーム - オーディエンスデータ管理システム - 広告効果測定ツール - クリエイティブ管理システム

4. AdCP(Ad Context Protocol)

Ad Context Protocol(AdCP)は、AgenticAdvertising.orgが策定するオープンスタンダード(Apache 2.0ライセンス)で、AIエージェントが複数の広告プラットフォームを横断して、キャンペーン管理・クリエイティブ生成・オーディエンス活用を単一インターフェースで実行できるようにするためのプロトコルです。IAB Tech LabのAAMPとは別のイニシアチブですが、いずれもエージェンティック広告のエコシステムを支える標準として相互補完的な関係にあります。

主な役割

機能 説明
コンテキスト情報の標準化 ページコンテンツ、ユーザー行動、配信環境などの情報を標準フォーマットで提供
リアルタイム情報交換 AIエージェント間でコンテキスト情報を迅速に共有
プライバシー配慮 ユーザープライバシーを保護しながら、必要な情報のみを提供

AdCPにより、AIエージェントは配信先の文脈を深く理解し、より適切な広告配信判断が可能になります。例えば、ニュース記事のトーン、動画コンテンツのジャンル、ユーザーの関心領域などを考慮した配信最適化が実現します。

IAB Tech Labによる標準化の動き:AAMPイニシアチブ

エージェンティック広告の普及、課題解決のため、IAB Tech Labは、AAMP(Agentic Ad Management Protocols)という包括的なイニシアチブを立ち上げました。

AAMPは単一の仕様ではなく、エージェンティック広告のエコシステムを支える以下の「3つの柱」で構成されています。

1. 実行基盤(Delivery and Execution control plane)

AIエージェントが広告システム内で安全かつ確実、そして高速に動作するための実行環境を定義します。

  • ARTF(Agentic Real Time Framework):
    • コンテナベースのエージェント実行環境を定義
    • リアルタイム入札(RTB)環境での遅延を大幅に削減(最大90%削減)
    • MCP(Model Context Protocol)インターフェースを内蔵し、本番環境での実行能力を確保

2. 管理プロトコル(Agentic Protocols)

エージェント間や広告主・各プラットフォーム間での交渉、取引、情報交換のためのスキーマやツールを定義します。

  • Agentic Audiences (旧 User Context Protocol): リアルタイムの意図信号とアイデンティティ情報の交換標準
  • Agentic Direct: 予約型広告取引(OpenDirectベース)のエージェント対応
  • Agentic Mobile: モバイルアプリエコシステムにおけるエージェントワークフロー
  • Agentic Ad Objects: 広告共通オブジェクトモデル(AdCOM)から派生したエージェント用オブジェクト定義

また、エージェント間の直接通信を可能にするAgent2Agent(A2A)プロトコルなどもこのレイヤーに含まれます。

3. 信頼と透明性:Agent Registry

エージェントの中立的な透明性と説明責任を確保するための基盤です。

  • Tech Lab Agent Registry: エージェントのアイデンティティ、検証結果、情報の開示状況などを登録・公開する仕組み。これにより、取引相手が「誰(あるいは何)」であるかを確実に把握できるようになります。

これらの3つの柱は、相互に補完し合うように設計されています。実行基盤がなければスケールせず、共有標準がなければ実行基盤は意味をなさず、そして信頼がなければエコシステム全体が不透明なものになってしまうからです。

従来の広告配信システムとの違い

従来のプログラマティック広告では、人間が戦略を立て、システムが実行するという役割分担でした。一方、エージェンティック広告では、AIエージェントが戦略立案から実行、検証、改善までを一貫して担います。

項目 従来のアプローチ エージェンティックアプローチ
戦略立案 人間が担当 AIエージェントが担当
実行 システムが自動実行 AIエージェントが自律実行
分析 人間が分析 AIエージェントが分析
改善 人間が改善策を検討 AIエージェントが改善策を実行
人間の主な役割 オペレーター(戦略立案・分析・改善) 監督者・意思決定者(目標設定・承認・監督)

人間の役割は、オペレーターから監督者・意思決定者へとシフトします。

現状の活用事例とトレンド

エージェンティック広告の具体的な活用例として、クロスメディアプランニングの領域での実装が進んでいます。

AdCPを活用したクロスメディアプランニング

Ad Context Protocol(AdCP)への対応が、Yahoo、PubMatic、Magniteなどの主要プラットフォームや、Scope3、Samba TVなどのデータプロバイダーを含む複数のベンダーで進んでいます。これらは、AdCPを通じて各メディアのコンテキスト情報を統合的に把握し、最適な広告配信戦略を自動で立案します。

主な機能

  • 予算配分の最適化: テレビ(地上波・CTV)、デジタル(ディスプレイ・動画・SNS)間での最適な予算配分を、コンテキスト情報に基づいて自動計算
  • リーチ重複の排除: 複数メディアでの重複リーチを考慮し、効率的なフリークエンシー管理
  • コンテキスト連動配信: 各メディアのコンテンツ特性に応じた最適なクリエイティブとタイミングで配信
  • アトリビューション分析: 各メディアの貢献度を測定し、次回キャンペーンの戦略に反映

従来、広告代理店の担当者がExcelで手作業で行っていたメディアプランニング業務が、AdCPによるコンテキスト情報の自動収集・分析により、スピーディーに完了するようになってきています。

IAB Tech LabのARTF(Agentic Real Time Framework)

ARTF(Agentic Real Time Framework)は、前述のAAMPイニシアチブの実行基盤として策定が進められています。現在想定される主な活用領域は以下の通りです。

活用領域: - アイデンティティ解決(Identity Resolution) - ディール活性化(Deal Activation) - セグメンテーション - インプレッション前の不正検知

ARTFは2026年1月に公開コメント期間を終了し、現在最終化の準備が進められています。バージョン2.0の開発も既に進行しており、エージェンティック広告のインフラとして業界標準となることが期待されています。ご興味のある方はARTFのページをご確認ください。

NBCUniversalのプレミアム動画買付自動化

NBCUniversalは、RPA、FreeWheel、Newton Researchとのパートナーシップにより、エージェンティックAIを使用したプレミアム動画買付の革新的なアプローチを導入しました。

主な特徴

  • リニア・デジタル統合買付: リニアテレビとデジタルプラットフォーム全体にわたり、秒単位でプレミアム動画に投資し最適化
  • ライブスポーツへの適用: 2026年Q1のライブフットボールプレーオフゲームなどのプレミアム枠を対象に実装
  • 業界初の取り組み: AIエージェントがリニアテレビ上でライブスポーツインベントリを自動化するのは初めての事例

この取り組みが今年のCESで発表されたことが、個人的にはエージェンティック広告への興味を引くきっかけになったほど、大きなインパクトがありました。

従来の広告運用との比較

エージェンティック広告は、従来の広告運用と比較して多くのメリットをもたらす一方で、新たな課題も生じています。

観点 従来の広告運用 エージェンティック広告
最適化作業 担当者が手動で入札調整・A/Bテスト・レポート作成 AIが自動実行。大規模運用でも高い一貫性を維持
意思決定スピード 日次・週次でデータ確認後、人間が判断・設定変更 24時間365日リアルタイムに監視・最適化
担当者の役割 定型業務(入札・レポート)中心。戦略業務は一部 監督・承認・戦略業務が中心。定型業務は一部
最終意思決定 人間がすべての判断を担当 大規模予算変更・ブランド判断など重要事項は人間が承認必須
データ依存度 担当者の経験・判断でカバー可能 データ品質に大きく依存。ガバナンス整備が必要
判断の透明性 担当者の意図・根拠が明確 ブラックボックス化リスクあり。可視化・監査機能の整備が必要
導入コスト 既存スキルで運用可能 プロンプト設計・AI監督など新スキル習得が必要

今後の展望と課題

エージェンティック広告は発展途上の技術領域であり、今後数年で大きく進化すると予想されます。

短期的な展望(1-2年)

Google、Amazon、Metaなどの主要プラットフォームでエージェント機能や様々なAI機能の統合が進み、中小規模の広告主でも専門知識なしに高度な広告運用が可能になっていくでしょう。 特に、メディアプランニング、運用、レポーティングなど定型的な業務プロセスでの自動化が加速し、広告代理店の役割で運用代行部分のウェイトが減り、戦略コンサルティングなどの部分に役割のウェイトがシフトしていくことが予想されます。

中長期的な展望(3-5年)

テレビ(地上波・CTV)、デジタル、OOHなどあらゆるメディアを統合したクロスメディアプランニングや広告運用の自動化、クリエイティブ制作の自動化が進展すると予想されます。動画広告の自動生成やブランドトーンの学習による一貫性のある広告制作が実現し、AIによる映像認識技術を活用したショッパブル広告、インタラクティブ広告などの新フォーマットが普及するでしょう。

業界全体への影響

スキルセットの変化

広告運用担当者に求められるスキルが、プラットフォーム操作やデータ集計から、AIエージェントへの適切な指示設計(プロンプトエンジニアリング)、戦略立案、AIの判断監督・評価へと変化します。AIエージェント監督者やエージェント戦略設計者など、新しい職種が登場する可能性もあります。

ガバナンスの重要性

AIエージェントが自律的に広告配信を行う環境では、AIの判断根拠の可視化、バイアス排除、プライバシー保護、監査体制の確立など、透明性と説明責任の確保が不可欠です。IAB Tech Labの標準化やガバナンスフレームワークが、業界共通の指針として重要な役割を果たすことが期待されます。

エージェンティック広告への対応

広告プラットフォームやメディアはエージェンティックAIへの対応をしないと、広告プランニングに入らないというような状況が生まれる可能性もあります。

まとめ

エージェンティック広告は、AIエージェントが広告のプランニングから配信、最適化、分析までを自律的に実行する新しいアプローチです。IAB Tech Labによる標準化の推進や、Google、Amazonなどの主要プラットフォームでの実装により、業界全体での普及が進んでいます。

従来のルールベースやデータドリブンな自動化とは異なり、エージェンティック広告では、AIが状況に応じて柔軟に判断し、複数の業務プロセスを統合的に実行できる点が大きな特徴です。これにより、広告運用の複雑化へ対応しつつ、人間はより戦略的・クリエイティブな業務に集中できるようになります。

一方で、AIの判断に対する透明性の確保、プライバシー保護、人間による適切な監督など、解決すべき課題も残されています。IAB Tech LabのガバナンスフレームワークやAPI標準化の取り組みや、国内においてもエージェンティック広告に関するルールづくりの整備は今後徐々に進んでいくと思います。

なお、まだ部分的な利用が多いですが、TVerでの広告開発や運用業務において、AIを活用したことによる恩恵を日々実感しています。(Claude Codeとの対話時間が爆増しています) TVerとしても、広告運用の効率化や高度化、広告価値向上において、MCPやA2Aなどを活用したエージェンティック広告の可能性を探っていく価値があると考えています。特にプランニング、運用、レポーティングなど、人がやるとどうしても煩雑になりがちな業務においては、AIエージェントの導入は有力な選択肢となると考えています。少しずつですが、出来る部分から検討を進めています。

またNBCUniversalから発表された内容のように、放送と配信の広告をAI技術の活用により、再構築していくことを目指しているところは、TVerの広告にとっても考えていくべきだと感じています。

エージェンティック広告は、まだ発展途上の技術領域ですが、今後数年で広告業界の標準的な手法となる可能性が高いと感じています。業界全体としても、技術の進化を注視しつつ、透明性とガバナンスを確保した形での導入を進めることが重要だと言えます。

そんな変化の激しい広告業界ですが、TVerの広告プロダクト開発チームでは一緒に広告プロダクトを開発するメンバーを絶賛募集中です。もちろん広告以外のエンジニアポジションも募集中です。AIなどの新しい技術を活用した広告プロダクト開発に興味のある方は、是非ご検討ください。

ご興味のある方は、是非弊社採用サイトをご確認ください。

前提知識ゼロでもAIで乗り切った!大規模プロジェクトでのClaude Code活用術

こんにちは、TVerでiOSエンジニアを担当している福島(@mantaroufire)です。

今回は、ある大規模プロジェクトにおいて、前提知識がほぼない状態から途中参画し、AIを活用してバグ修正を効率的に進めた経験についてご紹介します。

大規模プロジェクトへの途中参画

TVerでは、ボリュームの大きな機能の開発プロジェクトが進行していました。私が参画したのは、一通りの実装が完了し、不具合解消フェーズに入ったタイミングでした。

つまり、プロジェクト固有の要件・仕様や、細かい実装アプローチをほとんど把握していない状態からのスタートです。

通常であれば、まずコードを読み込んでキャッチアップに時間をかけるところですが、リリースまでの時間は限られています。そこで活用したのが、Claude Codeスキルでした。

Claude Codeのスキルとは

Claude Codeには、特定のタスクに特化した「スキル」を自作できる機能があります。プロジェクト固有の作業手順をスキルとして定義しておくことで、誰でも同じ品質・同じ手順で作業を進められるようになります。

今回のプロジェクトでは、以下の3つのスキルを順番に使うワークフローが活躍しました。

/analyze-and-create-issues → /implement-issue → /create-pr

不具合の分析からPR作成まで、一連の流れをスキルで標準化しています。

TVerでは不具合管理にGitHub Issueを活用しています。Claude Codeはターミナル操作も自律的に行えるため、GitHub Issueを中心としたワークフローとの相性が良く、ghコマンド(GitHub CLI)を使ったIssue作成・PR作成や、他リポジトリの探索も実行してくれます。これにより、調査から実装・PR作成までをシームレスに進められます。もちろん実行前に承認を求めてくれるので、内容を確認しながら対話的に進められます。

各スキルの紹介

1. /analyze-and-create-issues - 不具合の分析とIssue作成

QAチームから報告された不具合Issueをインプットとして、以下を自動で行います。

実行内容

  • 不具合Issueの内容を読み取り、問題を分析
  • 現在のソースコードを調査し、原因を特定
  • 調査結果と修正方針をまとめたIssueを作成

対話例

👤:

/analyze-and-create-issues

🤖:

案件分析を開始します。まず、インプット情報を収集させてください。

issueのURLまたは番号を教えてください

👤:

QAから報告されたこのIssueを見て(不具合IssueのURLを共有)

🤖:

不具合Issueを確認しました。特集画面で一部エリアのレイアウトが崩れている問題ですね。

調査の参考になる補足情報があれば教えてください。(任意・スキップ可)

例:実装対象のファイルパス、参考にすべき既存実装、その他の補足情報など

👤:

Androidではどう実装されているか確認してほしい

🤖:

承知しました。Androidリポジトリも含めて調査します。(ソースコード・Androidリポジトリを調査)

調査が完了しました。XXXXXViewでアイコンの表示条件に問題がありそうです。

Android側と比較したところ、iOS側のフィルタリング条件が仕様と異なっていました。Android実装に合わせる形で修正するのが良さそうです。

以下のIssue分割案で進めてよろしいですか?

👤:

OK、Android比較の結果もIssueに含めて作成して

🤖:

承知しました。Android実装との比較を含めたIssueを作成します。(Issueを作成)

Issue #7017 を作成しました。


作成されるIssueの例:

Issueには、概要・背景・調査結果・影響範囲・参考コード・関連リンクなどが詳細に記載されます。

このように、スキルが対話形式で情報を収集してくれるので、途中で「Androidの実装を確認して」といった追加の依頼を挟みながら、より精度の高いアウトプットを得ることができます。

2. /implement-issue - Issueに基づく実装

前のスキルで作成したIssueをインプットとして、実装を行います。

実行内容

  • Issueの調査結果や方針を読み取り、具体的な実装方針を策定
  • 採用アーキテクチャに沿った設計で実装
  • ビルド確認
  • コミット作成

対話例

👤:

/implement-issue #7017

🤖:

Issue #7017 の内容を確認し、実装を進めます。

(実装を進める)

実装が完了しました。ビルドも通っています。


Issueに「影響範囲」「参考コード」が詳細に記載されているため、AIはそれをもとに実装方針を固めて進められます。実装後はセルフレビューを行い、違和感があれば対話で修正します。

3. /create-pr - PR作成

実装が完了したら、PRを作成します。

実行内容

  • 変更内容の分析
  • Android実装との比較表の作成
  • Before/Afterの整理
  • PR本文の生成

対話例

👤:

/create-pr

🤖:

PRを作成します。Android実装との比較表も含めます。(PRを作成)

PR #7021 を作成しました。


作成されるPRの例:

このように、レビュワーが「なぜこの修正が正しいのか」を判断できる情報がPRに詰め込まれています。特にAndroid実装との比較表があることで、修正の妥当性を客観的に確認できます。

バグ修正とAIの相性の良さ

今回の経験を通じて、バグ修正はAI活用と非常に相性が良いと感じました。その理由は以下の通りです。

1. 期待値が明確

新機能開発と異なり、バグ修正には「正しい動作」という明確なゴールがあります。仕様書、Android実装など、参照できる情報源が多いため、AIが判断に迷う余地が少ないです。

2. スコープが限定的

バグ修正は影響範囲が比較的小さく、1つのPRで完結することが多いです。AIにとって扱いやすいタスクサイズです。

3. 調査の自動化

人間が複数のリポジトリやドキュメントを行き来して調査するのは時間がかかりますが、AIなら高速に横断的な調査ができます。

プロンプトの工夫

スキルを作成する際に工夫した点をいくつかご紹介します。

1. 対話形式での情報収集

必要な情報を一度に全て聞くのではなく、1つずつ質問して回答を得てから次へ進む設計にしました。これにより、ユーザーが何を入力すればいいか迷わずに済みます。また、やりとりの粒度を小さくすることで、AIが情報を見落としにくくなる効果もあります。

2. 段階的なアプローチ

Issue分割案を提示する際は、まず概要を提示して承認を得てから詳細を出力するようにしました。これにより、方向性の確認が早い段階でできるため、手戻りを防止できます。

3. 補足情報の任意収集

ファイルパスや用語説明など、調査を効率化するための補足情報を任意で収集するステップを設けました。人間側が持っている情報をAIに渡すことで、調査精度が上がります。

まとめ

私と同様に途中からプロジェクトに参画したメンバーにも、これらのスキルを使ってもらいました。

前提知識がない状態でプロジェクトに途中参画するのは不安なものですが、スキルで作業手順を標準化しておくことで、キャッチアップの時間を大幅に短縮できました。「どこまで調査すればいいか」「PRにはどんな情報を含めるべきか」といった属人的なノウハウがスキルに集約されているため、プロジェクトの背景を知らなくても一定品質のアウトプットを出せます。

結果として、無事にプロジェクトのリリースを迎えることができました


さいごに

TVerでは一緒に働く仲間を募集しています。AIを活用した開発や、大規模プロジェクトへの対応など、チャレンジングな環境で一緒に働きませんか?

カジュアル面談も受け付けていますので、少しでも気になった方はお気軽にご連絡ください!

recruit.tver.co.jp

混合負の二項分布による広告フリークエンシー分布の推定

こんにちは。TVer の広告事業領域でデータサイエンティストをしている川井です。普段は TVer 広告の配信システムの開発や、広告効果分析、データ基盤構築などを担当しています。

ストリーミング広告の配信において、「誰に何回広告が届いたか」を把握することは非常に重要です。同じユーザーに繰り返し広告が届くよりも、まだ届いていないユーザーに届けたい——そうしたニーズに応えるには、広告接触回数の分布構造を理解する必要があります。

以前の記事「負の二項分布でストリーミング広告のリーチを予測してみた」では、リーチカーブに直接フィットさせるアプローチを紹介しました。今回は別のアプローチとして、フリークエンシー分布(広告接触回数の分布)そのものを混合モデルで分解する手法を紹介します。単一の負の二項分布では「ユーザー全体の異質性」を 1 つのパラメータに集約しますが、混合モデルを使うと「ライト層が○%、ヘビー層が○%」といったユーザー構造を可視化できます。フリークエンシー分布の「なぜこの形になるのか」を解釈しやすくなる点が利点です。

フリークエンシー分布とは

「各ユーザーが何回広告に接触したか」という分布をフリークエンシー (frequency; FQ) 分布といいます。典型的なフリークエンシー分布には以下の特徴があります。

  •  0 が非常に多い
    • 母集団の大半は広告に接触しない
  • 急激に減衰
    • 広告に  1 回だけ接触したユーザー( FQ=1)が最も多く、 FQ=2 以降のユーザー数は急激に減衰する
  • 右に裾が長い
    • ごく少数のユーザーが非常に多くの回数接触する場合がある

この分布を統計モデルで表現できれば、「あと○○万回配信できたら何人リーチが増える」といった予測が可能になります。

シミュレーションデータの生成

フリークエンシー分布を推定するため、シミュレーションデータで検証してみましょう。以下のような 3 タイプのユーザーが混在する母集団(100万人)を想定します(ユーザータイプ・構成比・パラメータの数値は全て仮定です)。

フリークエンシー分布は過分散(分散が平均より大きい)を示すことが多く、ポアソン分布では表現できません。負の二項分布はこの過分散を扱えるため、広告接触回数のモデリングに適しています。負の二項分布のパラメータには  \mu \theta があり、 \mu は平均、 \theta は過分散を制御するパラメータです。 \theta が小さいほど分散が大きくなり、 \theta \longrightarrow \inftyポアソン分布に収束します。

ユーザータイプ 構成比  \mu  \theta 特徴
ライト 60% 0.1 0.5 広告にほとんど接触しない
レギュラー 30% 1.0 0.5 平均 1 回程度接触する
ヘビー 10% 3.0 0.5 頻繁に広告に接触する

負の二項分布の分散は  \mu + \frac{\mu^{2}}{\theta} で計算されるため、 \theta が小さいほど分散が大きくなります。今回は簡単のため、全てのユーザータイプで  \theta は一律  0.5 としました。

なお、私は最近 R にハマっているので、以降は全て R を用いて実験をしています。

Code

set.seed(42)

n_population <- 1000000

# 真のパラメータ
true_params <- tribble(
  ~component, ~prior,  ~mu, ~theta,
  "ライト",     0.60,  0.1,    0.5,
  "レギュラー", 0.30,  1.0,    0.5,
  "ヘビー",     0.10,  3.0,    0.5,
)

sim_data <- true_params |>
  slice_sample(n = n_population, weight_by = prior, replace = TRUE) |>
  mutate(
    user_id = row_number(),
    imp = rnbinom(n(), mu = mu, size = theta)
  )

成分ごとの統計量を確認します。avg_fq は理論上の  \mu に、variance \mu + \frac{\mu^{2}}{\theta} に近い値となるはずです。

Code

sim_data |>
  summarise(
    each_uu = n(),
    each_imp = sum(imp),
    reach_uu = sum(imp > 0),
    avg_fq = each_imp / each_uu,
    variance = var(imp),
    landing_fq = each_imp / reach_uu,
    .by = component
  ) |>
  arrange(each_imp) |>
  gt::gt() |>
  gt::fmt_integer(columns = 2:4) |>
  gt::fmt_number(columns = 5:7, decimals = 2)

component each_uu each_imp reach_uu avg_fq variance landing_fq
ライト 600,076 59,908 52,227 0.10 0.12 1.15
レギュラー 300,033 300,699 127,029 1.00 3.01 2.37
ヘビー 99,891 300,734 62,062 3.01 21.35 4.85

可視化してみましょう。接触回数が  0 回のユーザーがほとんどなため、可視化からは除外し、縦軸を対数表記にしています。

Code

sim_data |>
  filter(imp > 0) |>
  mutate(component = factor(component, levels = c("ライト", "レギュラー", "ヘビー"))) |>
  bind_rows(
    sim_data |> filter(imp > 0) |> mutate(component = "全体")
  ) |>
  mutate(component = factor(component, levels = c("全体", "ライト", "レギュラー", "ヘビー"))) |>
  ggplot(aes(x = imp, fill = component)) +
  geom_histogram(binwidth = 1, alpha = 0.5) +
  scale_x_continuous(breaks = scales::breaks_width(10)) +
  scale_y_log10(labels = scales::comma) +
  facet_wrap(~ component, ncol = 1) +
  labs(x = "接触回数", y = "人数")

全体としては右に裾の長いフリークエンシー分布になっています。ライト層は数回の広告接触に留まるのに対し、ヘビー層には広告にたくさん接触しているユーザーが存在することがわかります。なんとなくそれっぽいデータが生成されましたね。

全体の統計量についても確認します。今回はシミュレーションデータなので上記のように内訳がわかりますが、実際の広告配信後に得られるデータは以下のようなものになります。

Code

sim_data |>
  summarise(
    total_uu = n(),
    total_imp = sum(imp),
    reach_uu = sum(imp > 0),
    avg_fq = total_imp / total_uu,
    variance = var(imp),
    landing_fq = total_imp / reach_uu,
    max_fq = max(imp)
  ) |>
  gt::gt() |>
  gt::fmt_integer(columns = 1:3) |>
  gt::fmt_number(columns = 4:6, decimals = 2)

total_uu total_imp reach_uu avg_fq variance landing_fq max_fq
1,000,000 661,341 241,318 0.66 3.88 2.74 79

つまり、母集団サイズ、総インプレッション、リーチ人数、そしてフリークエンシー分布(接触回数ごとの人数)です。この情報だけから、背後にあるユーザー構造(ライト・レギュラー・ヘビー)とその構成比を推定できるでしょうか。

単一の負の二項分布によるフィッティング

まず、単一の負の二項分布でフリークエンシー分布をモデリングしてみます。

ここでは glmmTMB パッケージを使用します。 glmmTMB は一般化線形混合モデル(GLMM)をフィッティングするためのパッケージで、負の二項分布を含む様々な分布族をサポートしています。今回は混合効果を使わないシンプルなケースですが、weights 引数で集計データを扱える点が便利です。weights = cnt とすることで、「接触回数 imp のユーザーが cnt 人いる」という集計データをそのまま渡せます。 実務では、ベイズモデリングを使うと推定の不確実性を信用区間で表現できて有用なことが多いですが、今回は真のパラメータがわかっているシミュレーションなので、計算の速い頻度論的アプローチで進めます。

Code

freq_dist <- sim_data |> count(imp, name = "cnt")

fit_single <- glmmTMB::glmmTMB(
  data = freq_dist,
  formula = imp ~ 1,
  family = glmmTMB::nbinom2,
  weights = cnt
)

summary(fit_single)

 Family: nbinom2  ( log )
Formula:          imp ~ 1
Data: freq_dist
Weights: cnt

      AIC       BIC    logLik -2*log(L)  df.resid
1941961.4 1941965.5 -970978.7 1941957.4        57


Dispersion parameter for nbinom2 family (): 0.174

Conditional model:
             Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.413487   0.002695  -153.4   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

モデルは正常に収束しました。推定されたパラメータを確認します。

Code

single_params <- get_parameters(fit_single) |>
  mutate(value = exp(Estimate)) |>
  select(Component, value) |>
  pivot_wider(names_from = Component, values_from = value) |>
  rename(mu = conditional, theta = dispersion)

single_params |>
  gt::gt() |>
  gt::fmt_number(decimals = 2)

mu theta
0.66 0.17
  •  \mu の推定値

    • 母集団平均は約  0.66 なので、正しく捉えられています。
  •  \theta の推定値

    • 真の  \theta は成分ごとに  0.5, 0.5, 0.5 ですが、推定値は  0.17 でした。

    • 単一分布で混合分布の過分散を表現しようとした結果、 \theta が不自然に小さくなってしまいました。

このパラメータを使って、推定されたフリークエンシー分布と実際の分布を比較してみましょう。

Code

freq_dist |>
  mutate(
    total_cnt = sum(cnt),
    expected = total_cnt * dnbinom(imp, mu = single_params$mu, size = single_params$theta),
    residual = cnt - expected
  ) |>
  filter(imp <= 20) |>
  ggplot(aes(x = imp, y = residual)) +
  geom_col(fill = "steelblue") +
  geom_hline(yintercept = 0, color = "coral") +
  scale_x_continuous(breaks = scales::breaks_width(1)) +
  scale_y_continuous(labels = scales::comma) +
  labs(x = "接触回数", y = "残差(実測 - 推定)")

接触回数が 1 回の部分で大きな残差が生じており、単一の負の二項分布ではフリークエンシー分布の構造を十分に捉えられていないことがわかります。

混合負の二項分布によるフィッティング

単一の負の二項分布では残差が大きく、フリークエンシー分布の構造を十分に捉えられていませんでした。ここでは、複数の負の二項分布を混合したモデルを試してみます。混合負の二項分布のフィッティングには、flexmixパッケージを使用します。flexmix は有限混合モデルをフィッティングするためのパッケージで、countreg パッケージの FLXMRnegbin と組み合わせることで混合負の二項分布を推定できます。

成分数を 2〜4 で試し、BIC で比較します。BICベイズ情報量規準)はモデルの当てはまりと複雑さのバランスを評価する指標で、値が小さいほど良いモデルとされます。

stepFlexmix の主な引数は以下の通りです。

  • k: 試す成分数。ベクトルで複数指定可能。

  • model: 各成分の分布。FLXMRnegbin() で負の二項分布を指定。

  • weights: 集計データの頻度ウェイト

  • nrep: 初期値を変えて繰り返す回数。EMアルゴリズムは初期値依存なので、複数回試行して最良の結果を採用

  • control: minprior は成分の最小構成比。これを下回る成分は除外される

Code

tidy_flexmix <- function(fit) {
   flexmix::parameters(fit) |>
    t() |>
    as_tibble() |>
    rename(log_mu = `coef.(Intercept)`) |>
    mutate(
      component = row_number(),
      prior = flexmix::prior(fit),
      mu = exp(log_mu),
      .before = 1
    )
}

set.seed(42)

fit_mix <- flexmix::stepFlexmix(
  data = freq_dist,
  formula = imp ~ 1,
  k = 2:4,
  model = countreg::FLXMRnegbin(),
  weights = ~ cnt,
  control = list(iter.max = 500, minprior = 0.01),
  nrep = 20,
  verbose = FALSE
)

tibble(
  k = 2:4,
  BIC = sapply(fit_mix@models, BIC)
) |>
  gt::gt() |>
  gt::fmt_integer()

k BIC
2 1,936,738
3 1,936,448
4 1,936,502

 k=3BIC が最小となっています。 k=4 では改善せずむしろ悪化しており、3 成分が最適であることを示しています。今回のシミュレーションでは真の成分数が 3 だったので、正しく特定できています。 BIC が最小だった、 k=3 のモデルのパラメータを確認します。

Code

fit_best <- flexmix::getModel(fit_mix, which = "BIC")
mix_params <- tidy_flexmix(fit_best)
mix_params |>
  gt::gt() |>
  gt::fmt_number(columns = 2:5, decimals = 2)

component prior mu log_mu theta
1 0.12 2.67 0.98 0.46
2 0.20 1.22 0.20 0.66
3 0.67 0.12 −2.12 0.40

真のパラメータと比較したのが以下です。

真の成分 構成比  \mu  \theta 推定 構成比  \mu  \theta
ライト 0.60 0.1 0.50 Comp3 0.67 0.12 0.40
レギュラー 0.30 1.0 0.50 Comp2 0.20 1.22 0.66
ヘビー 0.10 3.0 0.50 Comp1 0.12 2.67 0.46

完全には一致しませんでしたが、構造の傾向は捉えられています。 \mu の大小関係(ライト < レギュラー < ヘビー)は正しく識別されており、構成比もライト層が多数を占めるという特徴を反映しています。ただし、レギュラー層の構成比が過小推定され、その分ライト層に吸収されています。中間的な成分は境界が曖昧になりやすく、隣接成分と混同されやすい傾向があります。

混合負の二項分布の残差確認

推定されたパラメータを使って、フリークエンシー分布の残差を確認します。

Code

freq_dist |>
  crossing(mix_params) |>
  mutate(prob = prior * dnbinom(imp, mu = mu, size = theta)) |>
  summarise(cnt = max(cnt), prob = sum(prob), .by = imp) |>
  mutate(
    total_cnt = sum(cnt),
    expected = total_cnt * prob,
    residual = cnt - expected
  ) |>
  filter(imp <= 20) |>
  ggplot(aes(x = imp, y = residual)) +
  geom_col(fill = "steelblue") +
  geom_hline(yintercept = 0, color = "coral") +
  scale_x_continuous(breaks = scales::breaks_width(1)) +
  scale_y_continuous(labels = scales::comma) +
  labs(x = "接触回数", y = "残差(実測 - 推定)")

単一の負の二項分布と比較して、残差が大幅に改善されています。 FQ=1 付近の大きなズレが解消され、全体的に残差が小さくなっています。 FQ=3, FQ=4 で若干の過大推定がありますが、母集団 100 万人に対して誤差 200 ~300 人程度なので実用上は問題ないレベルです。

リーチ予測への応用

推定したパラメータを使って、任意のインプレッション数に対するリーチを予測できます。混合負の二項分布では、リーチ率(1人以上に接触する確率)は以下のように計算されます。

 \displaystyle
        \text{リーチ率} = 1 - \sum_{i} \pi_i \cdot P(X=0 | \mu_i, \theta_i)

ここで  \pi_i は各成分の構成比、 P(X=0) は負の二項分布で接触回数が  0 となる確率です。

インプレッション数を変化させたときのリーチ予測を行うには  \mu をスケーリングします。配信量が 2 倍になれば、各ユーザーへの接触機会も2倍になると仮定し、 \mu を比例させてリーチカーブを描いてみました。

Code

calc_reach <- function(target_imp, params_df, total_uu, actual_imp) {
  scale <- target_imp / actual_imp

  params_df |>
    mutate(
      scaled_mu = mu * scale,
      p_zero = prior * dnbinom(0, mu = scaled_mu, size = theta)
    ) |>
    summarise(p_zero = sum(p_zero)) |>
    pull(p_zero) |>
    {\(p) total_uu * (1 - p)}()
}

freq_dist |>
  summarise(
    actual_imp = sum(imp * cnt),
    actual_reach = sum(cnt[imp > 0]),
    total_uu = sum(cnt)
  ) |>
  crossing(target_imp = seq(10000, 1000000, by = 10000)) |>
  mutate(
    predicted_reach = pmap_dbl(
      list(target_imp, total_uu, actual_imp),
      \(target_imp, total_uu, actual_imp) calc_reach(target_imp, mix_params, total_uu, actual_imp)
    ),
    reach_rate = predicted_reach / total_uu
  ) |>
  ggplot(aes(x = target_imp, y = predicted_reach)) +
  geom_line(color = "steelblue") +
  geom_point(aes(x = actual_imp, y = actual_reach), color = "coral", size = 3) +
  scale_x_continuous(labels = scales::comma) +
  scale_y_continuous(labels = scales::comma) +
  labs(x = "インプレッション数", y = "リーチ人数")

点は実測値(約66万 imp → 約24万リーチ)で、予測カーブが実測値を通過しており、モデルの妥当性が確認できます。また、カーブの形状からリーチの逓減効果も見て取れます。 インプレッション数を増やしても、リーチの伸びは徐々に緩やかになります。これは一部のヘビー層が繰り返しインプレッションを吸収するためで、混合モデルがこの構造を捉えていることを示しています。

このように、パラメータさえ推定できれば「○○万 imp でリーチ何人?」という問いに即答できるようになります。

まとめ

今回は、フリークエンシー分布を混合負の二項分布でモデリングする手法を紹介しました。シミュレーションを通じて、以下のことが確認できました。

  • 単一の負の二項分布では、異なるユーザー層が混在するフリークエンシー分布を十分に表現できない
  • 混合負の二項分布を用いることで、ライト・レギュラー・ヘビーといったユーザー構造を識別できる
  • 推定したパラメータから、任意のインプレッション数に対するリーチ予測が可能になる

この手法を実データに応用することで、リーチ予測やユーザー構造の定量的な比較が可能になるほか、ターゲティング戦略やフリークエンシーキャップ設定の検討に活用できそうです。

なお、今回はシミュレーションデータを使用しましたが、実際のキャンペーンデータに適用する際には、配信期間やターゲティング条件によるパラメータの変動など、より突っ込んだ検討が必要になります。

We’re Hiring!

TVer では、データサイエンスの力で広告事業の成長を支えるメンバーを募集しています。今回紹介したようなリーチ予測モデルの構築・改善や、広告配信の最適化など、チャレンジングな課題に取り組んでいます。 また、広告データ基盤も現在絶賛整備中のため、データエンジニアの募集も行っています。

ご興味のある方は、ぜひカジュアル面談からでも気軽にお話しましょう!

計測から始める品質とスピードの両立 - TVerの開発組織改革2年間の記録

この記事は Tverアドベントカレンダー2025 25日目の記事です。24日目の記事は @tomat_oooさんのTVerでテレビの体験をつくる!5つの壁とUIデザインの工夫でした。

サービスプロダクト本部 本部長の脇阪(@tohaechan)です。

techblog.tver.co.jp

1年前に上記のような記事を書きました。

当時は技術統括(TVerサービス開発部門内のVPoEみたいなポジション)として、主に技術戦略や組織マネジメントに責任を持っていました。 そこからPdMやデザイナーも含めた開発組織の本部長となったこともあり、これまでの仕事に加えてプロダクト成長にもより強くコミットすることとなりました。 そこで本記事では、プロダクト成長のためにどのような組織戦略、技術戦略を立てて実現したのかを共有したいと思います。

品質とスピード

FY25の注力ポイント
まず今年度サービスプロダクト本部の方針として掲げたのが 品質とスピードの両立 です。

昨年末の記事でも課題を書きましたが、機能開発のスピードは期待するほどのスピードが出ず、品質に関しても様々なトラブルが発生しその解消に追われて開発が後手後手に回るという状況でした。

一部の開発チームでは変更障害率の計測をしていたのですが、その数字はよくありませんでした。 実際、年末年始は怒涛のhotfixリリースをして胃が痛かったです…。しかも特定の領域で多く発生しているというようなことはなく、iOS, Android, Web, バックエンド、インフラとまんべんなく問題が発生していました。 体感3割くらいは緊急の不具合対応に追われており、当初予定していたリリーススケジュールがずるずる遅延していくという悪循環です。

このころ組織の人数としては約1年で2倍になり、育ってきた環境が異なるメンバーが増え、TVerというプロダクトや組織の課題感の認識もバラバラという課題感もありました。

「クソコードすぎるから事故るんだ!リアーキテクチャだ!!!(意訳)」「開発のスピードが遅すぎる!!!(意訳)」「まずは落ちまくるインフラの品質を担保すべき(意訳)」

ざっくりわかりやすく意訳すると上記のような感じで、人によってバラバラです。 それぞれの課題感が間違っているわけではないものの、人によって課題感が異なるので優先順位付けの際に揉めたり話が噛み合わなかったりします。 まずは開発組織全員の認識を揃え、同じ方向を向かせたい。そしてある程度覚えやすく認知しやすい方針にしたい。その思いから「品質とスピード」をスローガンに掲げることにしました。 品質とスピードはトレードオフの関係にあると考えられがちですが、品質を高めることで結果としてスピードを上げることができると考え、このようなメッセージにしました。

品質とスピードの両立の実現に向けて

これまでも品質とスピードの向上は各チームで取り組んではいましたが、 一方で「目指すべき理想形の状態」を定量的に示せていないことで認識のズレが起こっていました。

「インシデントが多い」「開発がなんとなく遅い」「リリース回数が少ない」といった定性的な課題感はあるものの、具体的にどの程度の問題なのか、改善が進んでいるのかを判断できない状態でした。 各チームの取り組みで改善できることには限界があり、組織全体でプロセスや手段を変えていく必要があるとも感じていました。

そこで品質とスピードのスローガンとともに、定量目標を設定しました。

  • インシデント発生件数
    • インシデントレベルを定義し、レベルごとの発生件数をn件以内にする
  • 平均修復時間
    • ポストモーテムで平均修復時間を計測し、平均修復時間をn時間以内にする
  • リリース頻度
    • 各デバイスごとの一ヶ月以内のリリース頻度を定義し、それ以上のリリースを行う
  • リードタイム短縮
    • FY25はまずは計測から始める

このように各指標の定義を明確にして、計測することから始めました。

課題と対策1: インシデント管理 && 平均修復時間の改善

まずはインシデントについて。インシデント管理において大きく3つの課題がありました。

  1. インシデント定義が曖昧
    • インシデントの重大度の判断が、人やチームによって異なる
    • インシデント改善タスクの優先度を決められない(あるいは、誤った優先度を設定している)
  2. インシデント対応を各チームバラバラに実施
    • 他のチームでどのようなインシデント対策を行っているのか知らない
    • インシデントが発生したことすら知らない
    • チーム横断的に対応した方がよいインシデントもあるが、対応できていない場合がある
  3. 再発防止&恒久対応をやりきっていない
    • 暫定対応や緩和措置の一時的な止血対応が、そのまま再発防止&恒久対応になっている
    • いつかちゃんとやろうと思っていても、機能追加に追われたり新しいインシデントへの対応でしっかりとした再発防止&恒久対応ができずに埋もれていく

こういった課題を解決するため、インシデント管理委員会を設立し、全チームから1人ずつ集めてインシデントの管理について話し合いを進めました。 全チームを呼んだのは全チームが自分事とし、現実的な管理ができるよう議論してもらうためです。

1のインシデント定義が曖昧だったところに対しては、本部全体で統一的なインシデントレベルを定義します。 過去1年のインシデントを手作業で洗い出し(各チームのポストモーテムであったり、Slackの障害報告であったりを地道にサルベージしました)、 インシデントを「アプリ」、「広告」、「ログ計測」などのカテゴリに分類しました。 このカテゴリ別にレベルを分類していくのですが、例えばアプリであれば、影響ユーザー数と機能重要度の掛け算でレベルを決めることにしました。もう少し具体的に言うと「コンテンツを再生できないユーザー数がxx万以上」であればインシデントレベルSというような形です。

このような定義を行い、本部目標として「インシデントレベルSを0件、Aをn件以内に抑える」ということを通期の目標として追っていくこととしました(件数に関しては前年発生件数から現実的な目標を算出)

許容できるリスクの明確化と段階的ロールアウト

あらゆるインシデントを起こさないのが理想的ではありますが、ソフトウェア開発でそれは不可能に近いです。テストに多くの時間を割けば限りなく少なくすることはできるかもしれませんが、スピードとの両立は難しくなります。

そこで重要になるのが、インシデントレベルに影響ユーザー数を含めることで許容できるリスクが明確になったことです。 例えば「影響ユーザー数が1000人未満ならインシデントレベルB」という定義があれば、新機能のリリース時に「まずは1000人未満に開放してフィードバックを得る」という判断ができるようになります。

この明確な基準により、過度に品質を作り込むことが無くなりました。 従来は「万が一何か起きたら大変だ」という心理的安全性の欠如から、リリース前に完璧を目指して長時間のテストや検証を行っていました。しかしインシデントレベルの定義により「このレベルなら許容できる」という共通認識が生まれ、スピードを上げることができるようになったのです。

具体的には、Feature Flagを使用して段階的にロールアウトしていく方法を全デバイスで標準化しました。

昨年のiOSDCでiOSの事例を発表していますが、Android、Web、コネクテッドTV、バックエンドの全てでこの考え方を適用させています。

バックエンドの事例に関してはこちらの登壇資料もご確認ください。

運用としては、数%ずつの段階開放を行い、クラッシュ数やサーバのエラー数、事業KPIへの影響などを観測します。 さらに、仮に問題が発生したとしてもインシデントレベルがB未満に収まるように開放率をコントロールする運用を心がけていました。 これにより、許容できるリスクの範囲内で新機能をリリースし、実ユーザーの反応を早期に確認できるようになりました。

この手法により、仮に何か問題が発生したとしてもすぐ0%に切り戻せる運用が確立し、実際に途中で切り戻して事なきを得たケースも何度かありました。 また、影響範囲を小さくしてリリースすることで、実ユーザーから早期にフィードバックをもらえるようになり、プロダクトの改善サイクルも大幅に向上しています。

今ではほとんどの機能リリースが段階的ロールアウトすることが当たり前になっており、品質とスピードの両立を実現する重要な仕組みとなりました。

インシデント情報の共有と透明性の向上

2のインシデント対応の課題に関しては、まずは本部全体でポストモーテムのテンプレートを作成し、一箇所に集約しました。

合わせて目標の一つである平均修復時間を計測できるように、「平均検出時間(MTTD)」「平均認知時間(MTTA)」「平均原因特定時間(MTTK)」「平均修正時間(MTTF)」「平均確認時間(MTTV)」をポストモーテムに含めることとします。

続いてインシデントが発生したことや、どのようなインシデント対策が行われているかを知らないという課題に対し、本部の正社員が全員いるチャンネルにSlackワークフローを2つ作成しました。

1つ目は「インシデント疑い報告」で、インシデントかどうかはわからないが、何らか調査を始めたときにこのワークフローを呼び出し、実際調査に当たってるチャンネルやスレッドを共有し全員が認知できるようにしました。

2つ目は「ポストモーテム作成報告」で前述のポストモーテムを作成したら共有するためのものです。 これに加えて本部の毎月の定例で、ポストモーテムとして良かった事例をインシデント管理委員会から共有し、本部全体に対してポストモーテムの重要性や対応してくれた人に感謝を示す場を設けて運用しています。

再発防止の徹底

3の再発防止&恒久対応をやりきっていない課題に関しては、ポストモーテムが整備されたことで管理しやすくなったため、開発ディレクターを中心にタスク管理を行うことでカバーしています。

課題と対策2: リードタイムの短縮 && リリース頻度

こちらの課題もまずは計測から始めました。

note.com

こちらの記事でも少しだけ触れていますが、バリューストリームマッピングを実施し エンジニア、QA、PdM、デザイナー、ディレクターそれぞれの視点で、リリースまでにどういうプロセスがあり、そこにどれだけの時間がかかっているかをMiroで可視化していきました。 各視点でおおよそ2時間強かかるなかなか重い作業ではありましたが、開発プロセスが可視化できて非常に意味のある取り組みだったかと思います。

それぞれの視点で見ていくと、大きくコストがかかっていたのは各職種間での連携です。

チーム固定化による品質と生産性の向上

これまでのチームビルディングはプロジェクトごとに人員がアサインされる方式でした。この方式には以下のような課題がありました:

  1. チームが成熟しにくく、内部品質が悪化する

    • プロジェクト都度でメンバーが入れ替わるため、未成熟なチームワークのまま開発が行われる
    • チーム内でのコードレビューやナレッジ共有が十分に機能せず、内部品質が悪化しやすい
    • プロジェクトごとにチームビルディングをやり直すコストが発生
  2. 同時並行プロジェクトによる認知負荷の高さ

    • リーダーが横断的に複数プロジェクトの詳細を把握する必要があり、認知負荷が高すぎる
    • メンバーも複数のプロジェクトに跨って参加することが多く、コンテキストスイッチのコストが大きい
    • 同時並行で動くプロジェクト数が多すぎることが、品質や生産性を下げる大きな要因となっていた

これらの課題に対し、職能別の組織をクロスファンクショナルなチームにして固定化することで解決を図ります。

チーム固定化により以下のような効果を狙いました: - チームメンバーが固定されることで、チームが成熟しやすい環境をつくる - 同時並行で動くプロジェクト数を制限し、認知負荷を下げる - 基本的にはチーム内のみ詳細を見ておけば良い状態を目指し、横断的な把握の負担を減らす

実はチーム固定化自体は2024年の早い段階から実施したかったのですが、人が十分に採用できていないことや、既存プロジェクトがありなかなかタイミングが合わず実現できてませんでした。 しかしエンジニアも増え、PdMやデザイナーも含めて同じ組織になるこのタイミングで実行するしかないとなり、ついに実現できました。 上記の決起会の記事にも「長年の悲願だった固定スクワッドチーム体制への変更が本運用開始〜」とあるように、マネージャー目線では悲願of悲願で、決起会やその後の本部の定例などでスクワッドチームの代表者が一丸となったチームの成果を発表する姿を見ると、マネージャー陣はうれしくてニヤニヤしてしまうというのが最近の恒例だったりしますw

チームの固定化でコミュニケーションの質を上げリードタイムの短縮は着実に改善されていったわけですが、各チームでの開発がそれぞれ進むとチーム間でどう連携をしてリリースしていくかという次の悩みが生まれることが予想されました。 これに関してはリリーストレインで解決することを事前に決めていました。

リリーストレイン(Release Train)とは、アジャイル開発において、複数の開発チームが連携し、電車のように決まったスケジュール(頻度)で定期的にソフトウェアをリリースする仕組みです メルカリなどで導入され、リリース遅延の防止、チーム間の同期、品質の安定化、ビジネス部門との連携強化などを目的とし、間に合わなかった機能は次の「列車」に乗せる(先送りする)イメージです。 (Geminiによる概要)

スクワッドチームは3チームあるのですが、隔週でリリースするという決め事の中で、間に合わなかったものは次のリリースに回すという運用をすることにしました。 この結果、安定して月に2回以上の機能リリースを実現できるようになりました。

このようにアウトプットが加速すると、今度はQAのリソースが不足する懸念が生まれてきました。 生産性が高まったからこそ生まれたうれしい悲鳴ではあるのですが、QAがボトルネックになってリリースができないという事態は避けなければなりません。

テスト自動化によるQAの効率化

これに関しては先ほどのバリューストリームマッピングの結果や不具合分析から改善点を抽出し、「SET(Software Engineering Test)チームによるテスト自動化の文化づくり」により改善していくこととなります。 リグレッションテストに大きな工数がかかっていることがわかったため、SETチームを組成しまずはWebとiOSからE2Eテストを開発していきました。QAやSETだけがテストをするというのではなく、各エンジニアがユニットテストを書くような文化づくりも行ってもらいました。 その結果大幅にテスト工程を削減でき、品質とスピードの両立に大きく貢献しています。

課題と対策3: 生成AIの活用

生成AIの活用に関してはあくまで手段であって目的ではないのですが、年初から他社での活用事例が多く出てきており、ある程度トップダウンで方向性を示さなければあっという間に周回遅れになりそうな危機感があり、期初の戦略に含め活用を推進してきました。 春先からClaudeやDevinの活用を始め、6月には生成AIをテーマにした開発合宿を実施、その結果プロダクトへの生成AIの適用なども順次始まっています。 今回のアドベントカレンダーでも多くのAI活用事例が書かれていますが、エンジニアだけでなくPdMやデザイナーも多くがAIを中心とした開発を進めています。 しかし、まだまだAI活用が他社よりリードできているとは全く思ってません。むしろ少し遅れてるくらいの認識でいます。 来年はAIエージェントの開発も含め、AIを活用しより品質とスピードを高めていきたいと考えています。

まとめ: 品質とスピードのその先、アウトプットからアウトカムへ

これらの課題を解決した結果、期初に立てた本部目標は概ね達成できており、着実に品質とスピードが上がってきているのを実感しています。 しかし、プロダクト開発において重要なのはアウトプットではなくアウトカムだともよく言われます。 アウトプットを高めることに費やした約2年間で、ようやく競合他社と比較しても目劣りしないレベルのアウトプットを出せる開発組織になったと自負していますが、ここからはアウトカムを得るフェーズになったと思っています。 PdMやデザイナーを含めたスクワッドチームは、このアウトカムを全員で得るために様々な創意工夫を行える体制でもあります。 実際、今年はショート動画のリリースや、各種出面のパーソナライズなど、プロダクト開発でのKPIへの寄与が着実にできた一年でもあります。 来年はさらなる飛躍の年にしていくので、みなさまTVerをこれからもよろしくお願いいたします。年末年始はTVerで動画をお楽しみください。 良いお年を!

Firebase MCPでモバイルアプリのクラッシュ対応を自動化する

この記事はTVer Advent Calendar 2025 シリーズ1 の 22日目の記事です。21日目の記事は@togoeさんの「デザインシステムを「1から作り直したけど撤退した話」〜TVerデザインシステムV2お蔵入りから学んだこと〜」でした。

はじめに

TVerAndroidアプリエンジニアの根岸です。

みなさんは、モバイルアプリのクラッシュ対応に日々どれだけ時間を割いているでしょうか?アプリのクラッシュ状況を監視し修正するのは重要な活動ですが、新機能の開発をしながら行うのはなかなか大変なので少しでも楽になれたら良いなと考えています。

そんな課題を解決するために、本記事では、Firebase MCPサーバーを利用して、モバイルアプリのクラッシュ対応を行うClaude Codeのカスタムコマンドを紹介します。

Firebase MCPサーバーは比較的新しい機能で、AIエージェントがFirebaseの各種サービスに直接アクセスできる機能です。本記事ではその中でもCrashlytics連携に焦点を当て、クラッシュの分析から修正PRの作成までを一気通貫で行うカスタムコマンドを構築していきます。Firebase MCPサーバーは現在試験運用版ではありますが、実運用できる機能であると判断し採用しました。

前提

ここでは以下の環境やツールの利用を想定して記載していきます。

  • Androidアプリのクラッシュ対応を行う
    • iOSアプリなどでも応用可能です
  • AIツールとしてClaude Codeを利用できる
    • 他のAIコーディングツールでも応用可能です
  • GitHubでIssueやコードの管理を行う
  • ghコマンドでGitHub関連の操作を行える

Firebase MCPサーバー

Firebase MCPサーバーには、クラッシュの数や内容などを参照できるMCP ツールが定義されています。

これらのツールを活用することで、Crashlytics Consoleを開くことなく、ターミナル上でクラッシュ情報を取得・分析できるようになります。

セットアップ

MCP を介した Crashlytics の AI アシスタンスのページにて各種AIツールごとの導入手順がまとめられているので、参考にしてセットアップします。

カスタムコマンドの作成

それでは、クラッシュ対応ワークフローを自動化するカスタムコマンドを作成していきましょう。ここでは、fix-crashlytics-issue.mdとしてカスタムコマンドを作成します。

コマンドの概要

/fix-crashlytics-issueコマンドは、以下のワークフローを自動実行します:

事前チェック → Issue ID入力 → 情報取得 → 診断 → GitHub issue作成
→ Crashlyticsにリンク追加 → ブランチ作成 → 修正実装 → PR作成

ワークフロー詳細

以降、実際のカスタムコマンドの内容を抜粋して紹介します。

0. 事前チェック

コマンド実行時、最初に環境が整っているかを確認します。

### 0. 事前チェック(Prerequisites Check)

**このステップは最初に必ず実行し、すべてのチェックに合格しない場合は処理を中断すること。**

#### チェック項目:

1. **Firebase MCP接続確認**
   - `firebase_get_environment` を実行
   - チェック内容:
     - ✅ Authenticated User が設定されているか
     - ❌ 未認証の場合: 「Firebase MCPにログインしてください。`firebase login`を実行するか、Firebase MCPサーバーの設定を確認してください。」

2. **Gitリポジトリ確認**
   - `git status` を実行
   - チェック内容:
     - ✅ Gitリポジトリ内で実行されているか
     - ✅ 作業ツリーがクリーンか(未コミットの変更がないか)
     - ⚠️ 未コミットの変更がある場合: 警告を表示し、続行するか確認
     - ❌ Gitリポジトリでない場合: 「Gitリポジトリ内で実行してください。対象プロジェクトのディレクトリに移動してから再実行してください。」

3. **GitHub CLI (gh) 確認**
   - `gh --version` を実行
   - チェック内容:
     - ✅ ghコマンドが存在するか
     - ✅ ghが認証済みか(`gh auth status` で確認)
     - ❌ ghコマンドが存在しない場合: 「GitHub CLI (gh) がインストールされていません。https://cli.github.com/ からインストールしてください。」
     - ❌ gh未認証の場合: 「GitHub CLIにログインしてください。`gh auth login`を実行してください。」

#### チェック結果の表示形式:

## 事前チェック結果

| チェック項目 | 状態 | 詳細 |
|-------------|------|------|
| Firebase MCP | ✅ | {user}でログイン中 |
| Gitリポジトリ | ✅ | クリーンな状態 |
| GitHub CLI (gh) | ✅ | v{version} 認証済み |

すべてのチェックに合格しました。

**いずれかのチェックが失敗した場合は、エラー内容を表示して処理を終了すること。**

いずれかのチェックが失敗した場合は、具体的なエラーメッセージと対処法を表示して処理を中断します。事前にチェックすることで、途中でエラーになって困る...という事態を防げます。

1. Crashlytics URLの入力

事前チェック完了後、対話形式でCrashlytics ConsoleのURLを入力してもらいます。

### 1. Crashlytics URLの入力

事前チェック完了後、ユーザーにCrashlytics ConsoleのURLを入力してもらう。

#### 入力形式:
- **URL**: Crashlytics ConsoleのフルURL
  - 例: `https://console.firebase.google.com/project/{project-id}/crashlytics/app/android:{app-id}/issues/{issue-id}?time=...`

#### URL解析:
URLから以下の情報を抽出する:
- **アプリID**: URLの `/app/android:` の後の部分(例: `android:1:123456789012:android:abc123def456``1:123456789012:android:abc123def456`- **Issue ID**: `/issues/` の後の32文字の16進数(例: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`#### 処理:
1. ユーザーに入力を促す:
   Firebase Crashlytics ConsoleのURLを入力してください:
   (例: https://console.firebase.google.com/project/xxx/crashlytics/app/android:xxx/issues/xxx)
2. URLからアプリIDとIssue IDを抽出
3. 抽出に失敗した場合はエラーメッセージを表示:
   - 「URLの形式が正しくありません。Firebase Crashlytics ConsoleのフルURLを入力してください。」
4. `crashlytics_get_issue` を実行してissue情報を取得(抽出したアプリIDとIssue IDを使用)
5. 取得成功: 処理を続行
6. 取得失敗: エラーメッセージを表示
   - 「Crashlytics issue (ID: {issueId}) が見つかりません。URLを確認してください。また、アプリID ({appId}) へのアクセス権限があるか確認してください。」

URLをそのままペーストするだけでOKなので、Crashlytics Consoleから簡単に連携できます。アプリIDもURLから取得するため、複数のアプリを扱う場合でも設定変更は不要です。

2. TodoListの作成

### 2. TodoListの作成
TodoWriteツールを使って以下のタスクリストを作成:
1. Crashlytics情報取得
2. 問題の診断と修正プラン作成
3. GitHub issue作成
4. CrashlyticsにGitHub issueリンクを追加
5. 修正実装の継続確認
6. ブランチ作成
7. 修正実装
8. コミット作成
9. Draft PR作成

※ステップ5で「Issue起票のみで終了」が選択された場合、ステップ6以降はスキップされる

TodoWriteツールを使うことでAIが自身でタスクを明確に管理してくれるようになります。

3. Crashlytics情報取得

### 3. Crashlytics情報取得(ステップ1で取得済みの情報を使用)
- `crashlytics_get_issue`でissue情報を取得
- `crashlytics_batch_get_events`でサンプルイベント(スタックトレース)を取得
  - issue情報のsampleEventフィールドを使用
- 影響規模の取得(`crashlytics_get_top_issues`を使用):
  - **直近1時間**: filterのintervalStartTime/intervalEndTimeを現在時刻から1時間前〜現在に設定
  - **直近24時間**: filterのintervalStartTime/intervalEndTimeを現在時刻から24時間前〜現在に設定
  - 両方のissueIdフィルタに対象issue IDを指定して取得

影響規模を時間範囲別に取得することで、「今まさに急増しているクラッシュなのか」といった緊急度を判断できるようになっています。直近1時間/24時間以内の発生件数に応じて緊急度を決定しているので、このような設定にしていますが、チームの運用ルールによっては直近1ヶ月などの少し長めの期間での発生傾向を調査することもできます。

4. 問題の診断と修正プラン作成

### 4. 問題の診断と修正プラン作成
- スタックトレースから該当ファイルを特定
- 関連するファイルをReadで読み込んで分析
- 問題の根本原因を分析:
  - 最大3つの可能性を列挙
  - それぞれの妥当性を評価
  - 最も可能性の高い原因を選択
- 修正プランを作成:
  - **原因**: 根本原因の説明
    - Fault: このコードベースの問題か、依存ライブラリの問題か
    - Complexity: simple / moderately simple / moderately hard / hard / Investigation Required
  - **修正内容**: 具体的な修正手順(ファイル名と変更内容)
  - **テスト方法**: 修正の検証方法

AIが複数の可能性を検討した上で、最も可能性の高い原因を提示してくれます。AIが分析した結果が間違いである可能性もあるので、どのような可能性があるか列挙し、その中でどれを選択して修正したのか提示してもらうと、人間が別の可能性を調査するときにも役立ちます。

5. ユーザー確認

### 5. ユーザーに確認(診断結果)
修正プランをユーザーに提示し、以下を確認:
- 診断結果が妥当か
- GitHub issueを作成してよいか

**承認されなかった場合はここで終了**

修正プランをユーザーに提示し、承認を得ます。診断結果に自信がない場合は、修正を実装せずプランのみ提示するようにしています。人間の判断を挟むことで、誤った修正を防ぎます。

また、「修正は人間がすぐに行えるがGitHub Issueの作成や内容の記載が面倒」な場合には、issue作成だけAIにお願いすることも可能です。特にモバイルアプリはUI関連のコードに起因したクラッシュの場合には、修正後の動作確認を人間が行うことも多いと思います。そうした時に、全てをAIに任せず、人間と適切に分業できるように選択肢を用意しています。

6. GitHub issue作成

診断結果を含むGitHub issueを作成します。

### 6. GitHub issue作成
`gh issue create` コマンドでissueを作成:

**タイトル形式:**
[Crashlytics] {issue.title}

**本文形式:**
## Crashlytics Issue情報

- **Issue ID**: {issue.id}
- **影響規模**:
  - 直近1時間: {hourlyUsersCount}人 / {hourlyEventsCount}回
  - 直近24時間: {dailyUsersCount}人 / {dailyEventsCount}回
- **発生バージョン**: {firstSeenVersion} → {lastSeenVersion}
- **エラータイプ**: {errorType}
- **Crashlytics URL**: {issue.uri}

## エラー内容

{issue.subtitle}

## スタックトレース

{スタックトレースの主要部分}

## 診断結果

### 原因
{根本原因の説明}
- **Fault**: {このコードベースの問題 or 依存ライブラリの問題}
- **Complexity**: {simple/moderately simple/moderately hard/hard}

### 修正内容
{修正手順}

### テスト方法
{検証方法}

### その他の可能性
{他の原因候補}

Crashlyticsの情報と診断結果がまとまっているので、後からissueを見返したときにも分かりやすいです。人間が手作業でissueを作成する場合以下のような課題があったため、AIが作成してくれるメリットは大きいです。

  • 人によって書き方や情報量がバラバラ
  • 全ての項目を埋めるのに時間がかかる

7. CrashlyticsにGitHub issueリンクを追加

### 7. CrashlyticsにGitHub issueリンクを追加
`crashlytics_create_note`を使って、CrashlyticsのissueにGitHub issueへのリンクをノートとして追加する。

**ノート内容:**
GitHub Issue: https://github.com/your-org/your-repo/issues/{issue番号}

これにより、Crashlytics Console上からもGitHub issueを参照できるようになります。双方向にリンクされるので、どちらからでも追跡可能です。

Firebase CrashlyticsのノートにGitHub Issueへのリンクが記載される

8-10. ブランチ作成 → 修正実装 → PR作成

  • ブランチ名: issue/{GitHub issue番号}
  • コミットメッセージ: #{issue番号} fix: {修正内容}
  • PRはDraftで作成

実行例

実際に実行するとこんな感じになります:

$ claude
> /fix-crashlytics-issue

## 事前チェック結果
| チェック項目 | 状態 | 詳細 |
|-------------|------|------|
| Firebase MCP | ✅ | user@example.comでログイン中 |
| Gitリポジトリ | ✅ | クリーンな状態 |
| GitHub CLI (gh) | ✅ | v2.40.0 認証済み |

すべてのチェックに合格しました。

Firebase Crashlytics ConsoleのURLを入力してください:
> https://console.firebase.google.com/project/my-app/crashlytics/app/android:x:xxxxxxxxx:xxxxxxx:xxxxxx/issues/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

アプリID: x:xxxxxxxxx:xxxxxxx:xxxxxx
Issue ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Issue情報を取得中...
スタックトレースを分析中...

## 診断結果

### 原因
ArrayIndexOutOfBoundsExceptionが発生。

- **Fault**: このコードベースの問題
- **Complexity**: simple

### 修正内容
HogeHoge.ktの`list.get()`を呼び出す前に、インデックスがリストの範囲内にあるかチェックを追加する。

この修正プランで進めてよいですか? [y/n]
> y

GitHub issue #123 を作成しました(ラベル: Firebase Crashlytics)
Crashlyticsにリンクを追加しました
ブランチ issue/123 を作成しました
修正を実装中...
コミットを作成しました
Draft PR #123 を作成しました

完了しました!
PR: https://github.com/org/repo/pull/123

Crashlytics ConsoleのURLを入力するだけで、PRまで作成されました!

まとめ

Firebase MCPを活用することで、クラッシュ対応の以下のフローを自動化できました。

  1. クラッシュ情報の取得・分析
  2. 診断結果を含むGitHub issue作成
  3. CrashlyticsとGitHub issueの相互リンク
  4. 修正ブランチ・コミット・PRの作成

これにより、Crashlytics ConsoleとGitHub、エディタを行き来する手間が削減され、クラッシュ対応の効率が大幅に向上します。

ぜひみなさんも試してみてください。

TVerバックエンドの現在地と2026年へのロードマップ ── 土台を固め、ユーザー体験を深化させる1年

TVer サービスプロダクト本部バックエンドEMの和田(@tench_oo)です。

2024年から2025年にかけて、TVerのバックエンドチームは、急増するトラフィックへの対応と、より高度な視聴体験の提供という二つの大きな課題に向き合ってきました。以前のブログでは、AIツールの導入による「開発のあり方の変化」についてお話ししましたが、今回はもう少し広い視点で、私たちが今どこに立ち、来年に向けてどのような準備を進めているのかを共有できればと思います。


1. 2025年の技術的取り組み:柔軟性と安定性の両立

今年、私たちが注力してきたのは、将来のサービス拡大を見据えた「足腰」の強化です。

アーキテクチャへの移行とパフォーマンスの追求

現在、私たちはAPIの**「新アーキテクチャ」への移行を段階的に進めています。

TVerには、大規模なイベント時に一瞬で数百万のアクセスが集中するという、非常にユニークで難易度の高いスパイク特性があります。これまでは、システムの安定を最優先してオンメモリキャッシュ**を強く効かせてきましたが、一方でユーザーごとのきめ細やかな情報の出し分け(パーソナライズ)を実現する上では、技術的な制約もありました。

アーキテクチャでは、キャッシュ戦略を再定義し、CDNキャッシュを戦略的に活用することで「スパイクアクセスへの耐性」を維持しながら、バックエンドでの動的な処理能力を向上させることに注力しています。安定性を犠牲にせず、ユーザー一人ひとりに最適な体験を届けるためのパフォーマンスチューニングを、現在も粘り強く続けています。

techblog.tver.co.jp

Spannerによるパーソナライズ基盤の構築

番組数が増え続けるなかで、ユーザーが自分の好みに合った番組にスムーズに出会える仕組みは、もはや不可欠なものとなっています。

膨大な視聴履歴データを安全かつスケーラブルに扱うため、私たちは 「Spanner」を新しいデータストアとして採用 し、その基盤整備を進めてきました。リレーショナルデータベースの信頼性と、クラウドネイティブな拡張性を両立させることで、データの整合性を保ちながらも、高速なパーソナライズを実現する土台を整えています。

techblog.tver.co.jp

画像配信の改善とマルチデバイス対応

TVerは、PCやスマートフォン、CTV(コネクテッドTV)だけでなく、 今年新たにサポートを開始したPlayStation5 など、非常に多様なデバイスで利用されています。それぞれのデバイスに最適な画像を届けるため、専用の画像配信CDNを導入しました。

フロントエンド側で動的にリサイズ指定ができるようにし、 WebP等の効率的なフォーマットを積極的に活用 することで、通信量の削減と表示速度の改善を図っています。現在はWeb版から展開していますが、PS5を含めた各デバイスへも順次適用を進め、プラットフォーム全体の視聴体験の底上げを目指しています。


2. 組織としての変化:より「プロダクト」に近い開発へ

技術的な進化を支えるのは、やはりチームのあり方です。今年は「開発のスピード」だけでなく、「コミュニケーションの質」にも焦点を当てました。

職能を超えた「ワンチーム」の組成

これまではバックエンドやフロントエンドといった職能別の動きが中心でしたが、今年は特定のKPI(重要指標)に向き合うクロスファンクショナルなチームを立ち上げました。

PdM、エンジニア、デザイナー、QAがひとつのチームとして、同じ目標に向かって議論を重ねることで、認識の齟齬が減り、より本質的な課題解決に集中できる環境になったと感じています。

AI開発ツールと人間の役割

以前のブログでも触れた通り、GitHub Copilotに加え、Claude CodeやDevinといったAIエージェントの導入も進めています。

AIに任せられる定型的な作業は任せ、エンジニアは「アーキテクチャの設計」や「複雑なドメインロジックの整理」といった、人間にしかできない領域に時間を使う。そうした役割の再定義が、チーム全体の生産性を底上げしています。

Embedded SREと地道な対話

「開発して終わり」ではなく、システムの信頼性を共に支える文化を作るため、Embedded SRE の体制を強化しました。アプリ担当とSREがタッグを組み、オブザーバビリティ(O11y)の改善を現場目線で進めています。

また、リモートワークができる環境の中で、あえてオフラインで集まる 「プチ合宿」 も開催しました。顔を合わせて将来の構想を語り合う時間は、日々の開発において、数字やドキュメントだけでは伝えきれない「熱量」や「さまざまな課題」を共有する大切な機会となっています。


3. 2026年へのロードマップ:期待に応え続けるために

2026年に向けて、私たちは以下のような領域に注力していく予定です。

  1. Spannerを活用した1to1コミュニケーションの深化構築した基盤を活かし、プッシュ通知やレコメンドを通じて、ユーザー一人ひとりに寄り添った「体験の繋がり」を強化します。
  2. セレンディピティのためのコンテンツ発見性向上単に「検索で見つかる」だけでなく、ユーザーがまだ自覚していない「新たな好きな番組」に出会えるような、 セレンディピティ(偶然の出会い) を生むためのデータ構造やメタデータ提供基盤の再定義を行います。
  3. A/Bテスト基盤による改善サイクルの加速「何がユーザーにとっての正解か」を客観的に判断できるよう、A/Bテスト基盤を整備します。データに基づいた確かな改善を積み重ねていく文化を、さらに強固にしていきます。

最後に

TVerのバックエンドは、放送という「揺るぎない信頼性」が求められる世界と、通信という「柔軟で爆速な変化」が求められる世界の交差点にあります。

私たちが挑んでいるのは、単なるWebサービスの開発ではなく、「テレビの次の10年」を定義するエンジニアリングです。新アーキテクチャという土台ができ、Spannerという武器を手に入れた今、2026年はさらに面白い挑戦ができると確信しています。この巨大なプラットフォームを、自分の手で進化させたい。そんな熱意を持つ仲間と、これからも切磋琢磨していければと思います。

TVerとテレビと私2025(今回は車載多め) 

1、はじめに

この記事は、TVerアドベントカレンダー20日目の記事です。

qiita.com

19日目の記事は@datahaikuninjaさんの「Pub/Sub で Worker Pool パターンを実装し、BigQuery リバース ETL ジョブの同時実行数を制御する」でした。

皆さん、こんにちは、 コネクテッドTV(以下 CTV)領域を中心に担当してきましたが、現在はアライアンス領域にも守備範囲を広げております、 井出と申します。 今年は、KDDIさんとのpovoのキャンペーンなども担当しておりました。

絶賛、「じゃあ、あんたが作ってみろよ」ロス(特に南川さんロス)でふらふらとキーボードを叩いています。

さ、気を取り直して書いていきます。

去年書いた記事はこちらです。

techblog.tver.co.jp

そもそも、CTVってなんやねんという方向けの補足は上にも記載ございますので、是非みてください。 あ、でも1つアップデートがありまして、PlayStation5®︎に対応しました!

TVer、PlayStation®5に対応開始 TVer初、ゲーム機にアプリが登場 | TVer INC.

入社当初の 2023 年から準備してきた案件で、個人的にも念願のリリースです。 ぜひ実際に触っていただき、フィードバックをいただけると嬉しいです。

2、今日は何の話を?

今日は少し視点を変えて、 PC・スマホ・テレビに続く “第4のスクリーン” とも言われる車載におけるエンタメ体験 について触れてみたいと思います。 後半では、TVer の CTV 戦略の現在地についてもご紹介します。 なお、車載領域の話は一般的な業界情報が中心で、TVer に特化した内容ではありませんのでご了承ください。

3、自動車に乗りながら、エンタメを楽しむには

① インフォテインメントシステムとは

インフォテインメントシステムは「Information(情報)」と「Entertainment(娯楽)」を統合した車載向けシステムで、 地図・車両状況の確認から、動画・音楽再生までを一体的に担います。 近年、自動車が 5G や車載 Wi-Fi などの高速・安定通信を備えるようになったことで、 “移動中の時間をどれだけ豊かにできるか” が車内UXの重要テーマ になっています。

② インフォテインメントシステムに関わるプレイヤー

車載エンタメは、以下のような多層構造で成り立っています。

  • 自動車メーカー
  • 車載システムを開発する企業(従来の Tier1 に相当)
  • OS を提供する企業(Google Automotive OS / QNX / 独自 OS など)
  • 動画ブラウザや再生エンジンを提供する企業
  • 動画配信サービス
  • 車載向けのアプリ配信・UX レイヤーを横断提供する企業(例:Xperi)

スマートフォンやテレビに比べ、関係者が多く、エコシステムが複雑なのが特徴です。

③-1 自動車メーカー

特に海外の自動車メーカー(例:BMW など)では、テレビチューナーの搭載が少ないこともあり、 YouTubeNetflix の視聴需要が早期から高かった と言われています。 また、自動車は「映像体験の場」である前に「安全に移動するための機械」であり、 動画視聴には家庭用デバイスにはない 厳格な安全要件 が存在します。

車載に特有の安全要件(一般論)

  • 運転中の動画視聴制限(前席は停車中のみ許可、など)
  • 走行中の操作制限(タッチ操作やメニュー階層の制約)
  • 地域ごとの法規制(欧州 UN-R、北米 FMVSS など)
  • UI の文字サイズや視認性要件
  • クラッシュ時のフェイルセーフ(アプリが固まらないこと)

これらは、自動車メーカーが最も慎重に対応する領域です。

③-2 車載システム開発会社

Bosch、Continental、Harman、Panasonic Automotive、Desay SV などが代表的です。 メーカー単位、時には車種単位で契約し、車載システムの開発を担っています。

③-3 OSベンダー

車載OSには多様な選択肢があります。

  • Google Automotive OS(GAOS)
  • BlackBerry QNX
  • 自動車メーカーが独自に構築した OS

興味深いのは、 「OSはGAOSだが、アプリストアは自動車メーカーの独自運営」 といったケースが多い点です。 また、LG が WebOS ベースの車載プラットフォームを開始するなど、多極化が進んでいます。

LG Vehicle Solution | LG Mobility

③-4 動画ブラウザ

車載で多く使われる再生エンジンは以下です。

しかし、家庭用ブラウザと比べて制約が大きいのが特徴です。 車載ブラウザの主な制約

  • DRM が L3 制限になりがち(高画質出力に影響)
  • メモリ・CPU の制限が厳しい
  • Cookie / localStorage に制約がある場合がある
  • バックグラウンド制御がOSに強く依存する

動画サービス側は、これらを踏まえて再生システムを最適化する必要があります。

③-5 その他横断提供ベンダー

例として Xperi のように、 「アプリ配信管理」「DRM」「レコメンド」「番組メタデータ」など、 エンタメ領域をまとめて自動車メーカーに提供する企業も存在します。

4、動画配信サービスは車載に展開するには?

インフォテインメントシステム上にサービス展開するためには、大きく2つのやり方があります。

①ネイティブアプリでの展開

Google Automotive OS が広がり、 YouTube や Prime Video などがネイティブアプリを提供し始めています。 ただし、車載アプリは 審査が非常に重く、期間も長い のが特徴です。

車載アプリ審査で見られるポイント(一般論)

  • 運転中の操作・視聴の制御が正しいか
  • UI の視認性・フォーカス遷移
  • メモリ使用量・クラッシュ耐性
  • 起動時間・復帰時間
  • 映像/音声が走行中に不具合を起こさないか

家庭用CTVの審査とはレベルが異なります。

②ブラウザベースでの展開

多くのサービスは、車載ブラウザでの展開が主流です。

  • 車載向けに最適化した CTV アプリを流用 するパターン
  • PC/タブレット向け UI を調整 するパターン

など様々な形があります。 ブラウザ対応は柔軟ですが、DRM/帯域/制約に応じたチューニングが必要です。

mobi-times.com

prtimes.jp

5、車載特有のネットワーク事情

車載ネットワークは、家庭用環境より 圧倒的に不安定 です。

ネットワークの特徴としては以下があげられます。

  • トンネル・山間部・高架などで通信が途切れやすい
  • 車載アンテナはスマホより干渉を受けやすい場合がある
  • 車内 Wi-Fi は複数人数で帯域が競合
  • 常に基地局間のハンドオーバーが発生

OTT 側で必要な工夫としては以下が考えられます。

車載では、安定して“止まらず見られる”ことが最重要 になります。

6、車載エンタメの代表的なユースケース

現時点で特に多い利用シーンは、以下の3つです。

  • 後席キッズ視聴
    アニメや子ども向け番組の需要が高く、車載エンタメの王道ともいえる利用ケース。

  • 長距離移動・渋滞時の視聴(一時停車中)

 家族利用が中心で、テレビ的な「ながら視聴」に近い使われ方。

  • 停車中のパーキングエンタメ

 北米・中国を中心に伸びている領域で、休憩中に動画や音楽を楽しむ利用が増加。

日本では 後席の子ども向け利用(1) と 長距離移動中の利用(2) が特に強く、 海外は 停車中のエンタメ(3) の伸びが顕著と言われています。

7、車載エンタメの今後

自動運転時代の車内UXは、未来像として、 以下のような構想が議論されています。

  • 車内全体がディスプレイ化
  • AR HUD に映像や案内を重ねる
  • 視聴しているコンテンツに応じた移動体験の連動
  • 座席ポジションに合わせた画面補正
  • “移動×メディア視聴” を前提とした広告 UX

車内が「第3の居住空間」へ変わっていく中で、 動画サービスの役割はますます重要になっていく領域です。

8、TVerのCTV状況

TVerのCTVデバイス対応状況

スマートテレビで11社、ストリーミングメディアプレイヤーで2社、プロジェクターで3社、セットトップボックスで3社 が昨年時点での状況でしたが、PS5®についに対応し、ゲーム機領域にも参入できました。

この記事をご覧になっている方々のお持ちのデバイスも、もしかしたら、対応しているかもしれません。 ぜひ、TVerをCTVデバイスでお楽しみください!

TVerにおけるCTVの立ち位置のその後

リリース当初 1.9% ほどだった CTV のデバイス別再生割合は、 2023年1月には 31%、現在は 約38% にまで伸長しています。

【TVer】2024年度の動向をまとめた「数字で見るTVer広告」発表 | 株式会社TVerのプレスリリース

TVerを使う3人に1人以上は、CTVを利用して、視聴しているということになります。

また、再生数も、

prtimes.jp

11月に過去最高の1.9億回を突破しました。 再生数も増加しており、2億回に迫る勢いです。

9、おわりに

私自身、仕事を通じてエンドユーザーにより良い体験を届けることを大切にしています。 CTV に加えて幅広い領域に携われるようになり、新たな挑戦に日々やりがいを感じています。 現在、TVerでは一緒に働いてくださる仲間を募集しています。 ご興味をお持ちいただけましたら、ぜひお気軽にお問い合わせください。

herp.careers

最後までお読みいただきありがとうございました。 また別のテーマで記事を書ければと思います。 今後とも TVer をよろしくお願いいたします!

次回は @togoeさんの「デザインシステムを「1から作り直したけど撤退した話」〜TVerデザインシステムV2お蔵入りから学んだこと〜」です。お楽しみに!!!