OBS Studio アーキテクチャ

OBS Studio の内部アーキテクチャの分析。ソースコード(GitHub obsproject/obs-studio)を基に構成要素と設計判断を整理したもの。

4 層アーキテクチャ

OBS Studio は 4 つのレイヤーに分離されている。

┌──────────────────────────────────────────────┐
│  Frontend (Qt UI)                            │
├──────────────────────────────────────────────┤
│  Plugins (38個)                              │
│  キャプチャ / エンコーダ / 出力 / フィルタ等       │
├──────────────────────────────────────────────┤
│  libobs (C コアライブラリ)                     │
│  Source / Scene / Encoder / Output / Service  │
├───────────┬──────────┬───────────────────────┤
│ libobs-   │ libobs-  │ libobs-              │
│ metal     │ opengl   │ d3d11                │
│ (macOS)   │ (Linux)  │ (Windows)            │
└───────────┴──────────┴───────────────────────┘

各レイヤーの責務:

レイヤー責務実装言語
Frontendユーザーインターフェース。シーン管理・配信制御・プレビュー表示C++ (Qt)
Pluginsすべての具体的機能。キャプチャ・エンコード・出力・フィルタ等C / C++
libobsコア抽象型の定義、映像/音声パイプラインの駆動、モジュールシステムC
レンダリングバックエンドGPU 描画の実装。libobs の graphics/ API を各 GPU API で実装C / Obj-C

この分離の要点は コア(libobs)が具体的な機能を一切持たない こと。画面キャプチャも、H.264 エンコードも、RTMP 送出も、すべてプラグインが担う。libobs は「Source とは何か」「Encoder とは何か」という型の定義と、それらを駆動するパイプラインだけを提供する。

6 つのコア抽象

libobs が定義する基本型。すべてプラグインとして差し替え可能。

抽象C 型役割実装例
Sourceobs_source_t映像/音声の入力。フィルタやトランジションも Source画面キャプチャ、カメラ、画像、テキスト
Sceneobs_scene_t複数 Source を位置・スケール・回転つきで配置するコンテナ— (libobs 組み込み)
Encoderobs_encoder_t映像/音声の圧縮x264, NVENC, VideoToolbox
Outputobs_output_tエンコード済みデータの出力先RTMP 配信、MP4 録画
Serviceobs_service_t配信サービスの接続情報Twitch, YouTube, カスタム RTMP
Displayobs_display_tプレビューウィンドウのレンダリングコンテキスト— (libobs 組み込み)

各型には弱参照版(obs_weak_source_t 等)が用意され、オブジェクト破棄後の安全な遅延アクセスを可能にしている。

Scene と Display は libobs 自身が実装を持つが、他の 4 型(Source / Encoder / Output / Service)は原則としてプラグインが実装を提供する。

コアデータフロー

[Source] ─→ [Scene 合成] ─→ [Canvas/Display] ─→ プレビュー表示
                 │
                 ↓
            [Encoder] ─→ [Output] ─→ ファイル / RTMP / WebRTC
                            ↑
                        [Service](配信先の接続情報)
  1. Source が映像/音声フレームを生成(同期 or 非同期)
  2. Scene が複数 Source をレイヤー順に GPU 上で合成し、1 フレームを生成
  3. 合成結果が Encoder に渡されて H.264 / HEVC / AV1 等に圧縮
  4. Output がエンコード済みデータをファイルやネットワークに送出
  5. Service が配信先(Twitch, YouTube 等)の接続パラメータを Output に供給
  6. 同時に、合成結果は Display 経由で UI のプレビューウィンドウにも描画される

Output は Encoder を直接参照し、Encoder が生成したパケットを pull する構造。Service は Output に接続情報を渡すだけで、データフローには直接関与しない。

スレッドモデル

OBS は最低 3 つの主要スレッドで動作する。

スレッド駆動元責務
ビデオスレッドobs-video.cレンダリングループ。全 Source の描画 → Scene 合成 → Encoder へ転送 → Display 更新
オーディオスレッドobs-audio.c音声ミキシング。各 Source の音声をサンプル単位で混合 → フィルタ適用 → Encoder / モニタリングへ
UI スレッドFrontend (Qt)ユーザー操作の受付、プレビュー描画の要求

ビデオスレッドとオーディオスレッドは独立して動作し、タイムスタンプで同期をとる。Encoder は両方のスレッドからデータを受け取り、mux して Output に渡す。

GPU エンコードの場合は obs-video-gpu-encode.c が介在し、レンダリング結果を GPU メモリ上のまま直接エンコーダに渡す最適化パスが存在する(CPU へのダウンロードを回避)。

レンダリングバックエンド

ライブラリGPU API対象 OS
libobs-metalMetalmacOS
libobs-openglOpenGLLinux, macOS (レガシー)
libobs-d3d11Direct3D 11Windows

libobs の graphics/ サブシステムが統一 API を定義し、各バックエンドがそれを実装する。この抽象層が提供する機能:

Scene 合成、フィルタ適用、プレビュー描画のすべてがこの抽象層を通る。プラグインも graphics/ API を通じて描画するため、バックエンドの違いを意識しない。

コードベースの規模

ディレクトリ主要言語概要
libobs/Cコアライブラリ。約 60 ファイル + サブディレクトリ群
plugins/C / C++38 プラグイン。各プラグインが独立ディレクトリ
frontend/C++ (Qt)UI 実装
libobs-metal/Obj-C / MetalmacOS レンダリング
libobs-opengl/COpenGL レンダリング
libobs-d3d11/C++D3D11 レンダリング
deps/各種外部依存ライブラリ
shared/C / C++プラグイン・フロントエンド間で共有されるユーティリティ

全体で C 51.8%、C++ 36.9%。CMake ベースのビルドシステム。

設計上の注目点

「すべてが Source」の統一モデル: 映像入力、音声入力、フィルタ、トランジション、Scene 自体がすべて obs_source_t として統一されている。フィルタは Source にチェーンされるだけの Source であり、トランジションは 2 つの Source 間を補間する Source。この統一により、パイプラインの組み合わせが自由になる。

コアの薄さ: libobs は型の定義とパイプラインの駆動だけを行い、具体的な映像処理・プロトコル実装を一切持たない。画面キャプチャひとつとっても、macOS は ScreenCaptureKit、Windows は DXGI/GDI、Linux は X11/PipeWire と完全に異なるが、それらはすべてプラグイン側に閉じている。

プラグイン間の疎結合: プラグイン同士は互いを知らない。すべて libobs のコア抽象型を介して間接的に連携する。mac-capture と mac-videotoolbox が協調して動作するのは、libobs が Source → Encoder のデータフローを仲介するからであり、両者が直接通信しているわけではない。

GPU エンコードの最適化: レンダリング結果を CPU にダウンロードせず GPU メモリ上のままエンコーダに渡すパスがある。これは配信のレイテンシと CPU 負荷の両方に効く重要な最適化。

押さえどころ(カード化候補)

関連

Graph