PLAY DEVELOPERS BLOG

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

iOSDC Japan 2026 参加レポート

こんにちは。技術基盤部 SDK開発グループの藤森です。

9月11日から13日にかけて開催されたiOSDC Japan 2026に参加してきました。PLAYは去年に続いてシルバースポンサーとして協賛し、今年はTシャツスポンサーにもなっています。

iOSDC Japan 2026とは

iOS関連技術をコアのテーマとした、ソフトウェア技術者のためのカンファレンスです(公式サイト)。2026年は有明セントラルタワーホール&カンファレンスで開催され、トークセッションはニコニコ生放送でオンライン配信もされました。

PLAYのスポンサー協賛

Tシャツスポンサーとして、iOSDCのTシャツにPLAYのロゴも掲載していただきました。

会場にはPLAYのステッカーも並んでいました。

聴講したセッション

Day1: 映像変換サーバーなしで端末内でHLSを生成してライブ配信

fortee.jp

speakerdeck.com

撮影中のiPhoneでHLSのセグメントを作り、その場で公開先へ送るという話です。 動機は、撮影が終わってからまとめてアップロードする時間を減らすことでした。撮影しながらセグメントを送っておくことで、停止後の大きなアップロードを減らし、残るのは最後の送信と終了処理だけにする、という考え方です。

一般的なライブ配信では、端末でエンコードした映像をRTMPなどでサーバーへ送り、サーバー側で配信用に変換してセグメント化し、CDNから配信します。このセッションの構成は、映像を受信し続けて変換するサーバーをなくし、iPhoneがカメラとマイクの入力をAVAssetWriterでエンコードしてセグメントに分け、S3へHTTP PUTするというものでした。AVAssetWriterが作るのはセグメントのデータだけで、保存とHTTP送信とplaylistの組み立てはアプリの担当です。視聴者はCDN経由でそのplaylistを追いかけます。

セグメントは約2秒ごとに生成され、保存に成功したセグメントだけがplaylistに載ります。 配信が終わると、サーバー側にはinit.mp4とplaylistとセグメントが、iPhone側には1本のMP4が残る、とのことでした。

動画配信は普段の業務でも扱っているので、録画しながら配信も進めるこの構成は興味深かったです。

Day1: 「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜

fortee.jp

speakerdeck.com

AI家計簿アプリ「ワンバンク」の話です。プリペイドカードを扱うサービスなので、カード番号など「写ってはいけない」ものが写った画像がアップロードされることがあります。タイトルの「守り」とは、LLMで新しい価値を作るのではなく、こうした情報が外へ出ていくのを防ぐために使う、という意味でした。

サーバー側では、アップロードされた画像にカード番号が写っていないかを、Amazon Rekognitionで2段階に調べています。画像にカードのような物が写っているかを見る物体認識と、画像の中の文字を読み取るOCRで、どちらかが引っかかればその画像の処理を止めます。それでも改善の余地が3つある、という整理でした。実行ごとに料金がかかること、アップロードのたびに外部通信を伴う処理が挟まること、そして防げるのはサーバーへの保存までで、アプリからの伝送そのものは止められないことです。そこで、サーバー側の防御は残したまま、アプリ側にもオンデバイスLLMで防御を足すことにしたそうです。iOSについては、iOS 27で画像入力に対応したFoundation Modelsのプロンプトに画像をAttachmentとして添え、カード番号が読めるかを受け取るコードを紹介していました。

iOS 27で追加されたAttachmentの実用的な使い道を聞けたのは新鮮でした。

Day2: Heart of Swift Concurrency

fortee.jp

speakerdeck.com

Swift Concurrencyの言語仕様は膨大ですが、核となる考え方はシンプルだ、というところから始まるセッションです。その核はコンパイラがデータ競合を防ぐことで、それを支えるのがisolation domainとSendableの2つでした。

仕組みは2つの規則でできています。

  • すべての関数と変数は、コンパイル時に決まるisolation domain(どこにも隔離されていない/actorに隔離/global actorに隔離)を持つ。可変な状態には、そのdomainの中からしか触れない
  • domainをまたいで渡せるのは、原則としてSendableな型だけ。純粋な値型はコピーされるので共有されず、actorは中の状態が直列に守られているので、どちらもSendable。可変な状態をそのまま持つクラスはSendableにできない

静的に決まるisolation domainとSendable準拠という型の情報だけで、コンパイラはデータ競合が起きうる箇所をコンパイルエラーにしています。型で保証するというSwiftらしい仕組みです。

actorの中で処理が直列に実行されることは知っていましたが、その部分がSerialExecutorというprotocolとして切り出されていて、actorのunownedExecutorを実装すれば手持ちのシリアルキューに差し替えられることは初めて知りました。

Concurrencyと上手く付き合う方法として、アプリの設計の指針も紹介されました。@MainActorでやって困らないことは@MainActorでやる、というものです。外に出すのは、画像処理や巨大なデータのデコード、カメラのフレーム解析のような、メインスレッドの時間を食う重い処理です。
もう1つの指針は、不必要にいろんなものをactorにしないことです。actorを増やすと、それだけisolation domainの境界を越える場面が増えます。境界を越えるたびに、同期で済ませたかった処理がawait付きの非同期になり、渡す値にはSendableが求められます。

この指針には共感しました。アプリは、イベントループがユーザー操作やシステムからのイベントを受け取って状態を更新していく状態機械で、その主体はメインスレッドです。イベントに応じる処理はもともと@MainActorで動いています。軽い処理まで別のactorに隔離すると、isolation domainの境界を越えるactor hopが増えてパフォーマンスが悪化するので、隔離するのは重い処理に限るべきと考えていました。

最後に、AIエージェントにConcurrencyを書かせるときのTipsも紹介されました。 swift-evolution・swift-migration-guide・swift-bookのリポジトリを手元にcloneしてコンテキストとして渡すことと、Xcode MCPのDocumentationSearchを使うことです。 こちらは実際に試してみたいです。

おわりに

並行するトラックがあるので聴けたのは一部でしたが、端末内でHLSを生成するライブ配信から、オンデバイスLLMの活用、Swift Concurrencyの基礎となる考え方まで、幅広く学ぶことができました。日々の業務にも活かしていきたいと思います。

スポンサーとしてTシャツにロゴを載せてもらいつつ、参加者としてもたっぷり学べた3日間でした。運営の皆さん、スピーカーの皆さん、ありがとうございました。