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
複雑なライブ配信ロジックをステートマシンでシンプルにした話
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Naka
May 25, 2026
Programming
80
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
複雑なライブ配信ロジックをステートマシンでシンプルにした話
Naka
May 25, 2026
Other Decks in Programming
See All in Programming
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
120
Hono + Inertia + React で LP を構築した話
oukayuka
2
190
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
270
PHPプロジェクトの結合バランスを可視化する #php_night
kajitack
0
150
業務時間外もAIに働いてもらう話
colorful12
3
9.4k
AIと壁打ちしながら進めるコスト管理
fufuhu
2
1.8k
わからない話を追いかけたら、プログラミング言語を作る側にいた
ydah
3
580
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
260
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
280
高専、大学編入、そして未踏へ〜プロダクト開発とキャリアの歩み - Technical College, University Transfer, and On to “Mitou” / My Journey in Product Development and Career
pkmiya
0
120
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
470
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
330
Featured
See All Featured
Done Done
chrislema
186
16k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.5k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
510
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
390
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
sira's awesome portfolio website redesign presentation
elsirapls
0
360
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Transcript
© DMM © DMM 複雑なライブ配信ロジックを ステートマシンでシンプルにした話 合同会社DMM.com オンラインサロン開発部 仲純平 2026/05/20
© DMM 自己紹介 2 仲 純平 合同会社DMM.com オンラインサロン開発部 iOSエンジニア •
DMMオンラインサロン や SALON LIVE の開発 • 完全初心者からピアノを始めました
© DMM 本日の発表 01 SALON LIVE について 02 ステートマシン化に至った経緯 03
ステートマシン設計 04 導入後の変化とまとめ
© DMM SALON LIVE とは Protocol RTMP Library HaishinKit (Swift製
OSS) 複雑な状態遷移が特徴 接続・切断・再接続・品質変更・バックグラウンド 復帰など、状態が頻繁に切り替わる 4 SALON LIVE DMMオンラインサロンのオーナー専用ライブ配信アプリ トーク レッスン Q&A オーナーから会員に配信 など
© DMM 配信レイヤーの構造 UI LAYER StreamViewController (配信画面) LOGIC LAYER RTMPCoordinator
RTMPClient StreamConfigurator CORE LAYER HaishinKit 旧 RTMPManager RTMPCoordinator 配信開始ボタンひとつの裏で 膨大な状態を制御する司令塔 複雑なロジックがここに集約されます 5 旧 RTMPManager
© DMM きっかけ: HaishinKit メジャーアップデート 2.x 主要な変更点 ライブラリの抜本的刷新 • モジュールの分割
HaishinKit / RTMPHaishinKit • 中核クラスの actor 化 RTMPConnection / RTMPStream 等 • Swift Concurrency 前提 非同期処理の安全性が必須に 配信制御の暗黙の前提が次々と露わに ライブラリの形が変わることで、 自分たちのコードの複雑さが浮き彫りに。 6
© DMM 既存コードの "つらさ":旧 RTMPManager 536行 / 1クラスに集中 3つのつらさ ①
状態が暗黙的 ブール値の組合せで状態が散らばり、現在のフェーズが判別不能 connection.connected + host/key + previousObserverStatus + reconnectTimer の組み合わせでしか分からない ② 並行イベントが読めない 複数の経路から再接続が走り、どの処理が本流か分からない 再接続が最低4経路から走る(ネットワーク復帰 / 3秒Timer / IOエラー / publish リトライ) ③ 責務の過剰な混在 UI通知、配信操作、トラッキング、解放処理が密結合 7
© DMM なぜステートマシンを選んだか 先輩エンジニアとの議論で見えた活路 当初はAPI追従のみを目的としていたが、レビューでの「状 態がコードに表現できていない」というフィードバックを機に 方針を転換しました。 「コードが本質的に複雑なのではなく、ロジックの本 来の形をコードが表現できていなかった」 状態とイベントを書き出すと、実は驚くほどシンプルに整理
できることが判明。これを機に、設計を根本から直す決断 をしました。 アップデートを「設計を直す絶好のチャンス」へ 状態を設計の主役に据える ステートマシン化への方針切り替え 8
© DMM 状態・イベントの設計 9
© DMM 状態・イベントの設計 10
© DMM 状態・イベントの設計 11
© DMM Router の設計 Router (純粋関数) Logic Formula (Event, State)
-> State? • 遷移の「表」として定義 どのイベントで次にどの状態へ行くか のみを決定 • 副作用の分離 実際の処理(API実行等)はここには 書かない 12
© DMM 副作用 13 // RTMPCoordinator — 状態に応じた副作用 func executeTask(state:
State, emit: @escaping (Event) -> Void) async { switch state { case .preparing: await prepare(emit: emit) // カメラ・ミキサー初期化 case .liveStreaming(_, _, _, .connecting(.handshaking)): await handshake(emit: emit) // RTMP接続 case .liveStreaming(_, _, _, .publishing): await withTaskGroup(of: Void.self) { group in group.addTask { await self.observeNetwork(emit: emit) } // ネットワーク状態監視 group.addTask { await self.observeRTMPConnection(emit: emit) } // RTMP接続状態監視 // … } case .liveStreaming(_, _, _, .disconnecting): await disconnect(emit: emit) // 切断 default: break } }
© DMM Before / After:何が変わったか フラグベースの暗黙的な管理 • ブール値の組合せによる状態散在 • 散在したif文/switch文の遷移分岐
• 処理全体に分散した副作用の実行 • コールバック地獄による並行処理 • 状態遷移のユニットテストが困難 ステートマシンによる一意な管理 • 階層 enum による状態の一意な定義 • ルーターの表として読める遷移フロー • 副作用を一つのメソッドに完全集約 • withTaskGroup による明示的並行処理 • 純粋関数化により 500行超のテストを完備 14 Before After
© DMM 学び・今後の展望 Learn 01 破壊的変更を 好機と捉える ライブラリの破壊的変更は、既存設 計の負債を解消し、抜本的に作り直 す絶好のきっかけとなります。
Learn 02 enum による 状態の可視化 状態を enum で明示的に定義するこ とで、議論やレビューが図解ベース で進められるようになり、開発効率 が向上します。 Learn 03 純粋関数と テストの親和性 ルーターを純粋関数として切り出す ことで、ユニットテストによる品質担 保が容易になり、堅牢な基盤を構築 できます。 今回の再設計を活かし、「読める・テストできる・壊れにくい」強固な配信レイヤーを追求していきます。 15
© DMM まとめ HaishinKit のメジャーアップデートを機に、 配信ロジックを State・Event・Router と 汎用 StateMachine
で再設計した 結果として、 「読める・テストできる・壊れにくい」 強固な配信レイヤーを実現 16
© DMM ご清聴ありがとうございました