WebRTCを使用したブラウザ間ファイル転送の構築:TransP2Pを構築して学んだこと

これはTransP2Pが内部でどのように動作するかに関する技術的な深い掘り下げ記事です——WebRTCの内部動作、ブラウザストレージの特性などの技術的な詳細が含まれます。使い方ガイドだけが必要な場合は、代わりにチュートリアルを確認してください。
要約: 私は完全にブラウザ内で動作するP2Pファイル転送ツールを構築しました。インストール不要、サーバー中継不要、アカウント不要。以下は、WebRTCデータチャネル、再開可能な転送、およびブラウザストレージの混乱した領域について学んだことです。
ほとんどのファイル転送ツールは同じパターンに従います:サーバーにアップロード、リンクを取得、受信者がそのサーバーからダウンロード。少なくともしばらくの間、あなたのファイルは誰か他の人のインフラストラクチャ上に置かれます。
私は異なるアプローチを試してみたかった:ファイルがブラウザをまったく離れない場合はどうなるだろうか?
この質問がTransP2Pにつながりました——WebRTC上に構築されたブラウザベースのP2Pファイル転送ツールです。この記事では、技術的な決定、予想以上に難しかった部分、そしてほとんど誰も話していない2つのブラウザストレージパスについて説明します。
基本的なアーキテクチャ
理論的にはフローは単純です:
- 両方のデバイスがサイトを開く(インストール不要、アカウント不要)。
- WebSocketシグナリングサーバーがSDPオファー/アンサーとICE候補の交換を支援します。
- 直接のWebRTCデータチャネルが確立されます。
- ファイルはチャンクに分割され、データチャネルを介して送信されます。
- レシーバーはチャンクを再構築し、ファイルを保存します。
シグナリングサーバーはファイルデータに決して触れません。接続が確立されると、接続の維持のみを支援します。
すべてをチャンク化する——必要がない場合でも
早期に報われた決定:再開可能な転送が有効かどうかに関係なく、すべてのファイルが転送中にチャンク化されます。
代替案——ファイルを1つのblobとして送信する——は単純に見えますが、すぐに問題が発生します。大きなファイルはメインスレッドをブロックし、ネットワークのわずかな問題で最初からやり直す必要があります。
チャンク化を使用する場合、各ピースは通常64 KBです。送信者はデータチャネルを介してチャンクをストリーミングします。レシーバーはそれらをメモリにバッファリングし、ダウンロード時にディスクに書き込みます。これにより最高の速度が得られます——転送自体の間に中間的なディスクI/Oがないためです。ボトルネックはディスクではなく、データチャネルのスループットです。
再開可能な転送の問題(およびなぜ2つの解決策があるのか)
再開可能な転送は興味深い部分でした——ブラウザの違いが2つの完全に分離した実装を強制しました。
目標
転送が中断された場合(ネットワークが切断された、ユーザーがタブを閉じた)、レシーバーは中断した場所から再開できる必要があり、ゼロから始める必要はありません。
コアアイデアは単純です:どのチャンクが受信されたかを追跡し、再接続時に送信者にチャンクNから開始するように指示します。
しかし、それらのチャンクをどこに保存するかが難しい部分です。ブラウザは生のディスクアクセスを許可していないからです。そして、すべてのブラウザが同じAPIを提供するわけではありません。
パス1:OPFS + File System Access API(Chrome、Edge、Firefox)
現代のChromiumベースのブラウザと新しいFirefoxバージョンは、Origin Private File System(OPFS)をサポートしています。OPFSを使用すると、サンドボックス化されたオリジンプライベートディレクトリにファイルを書き込むことができ、Web Workersと共に使用するとメインスレッド外で書き込みが行われるため高速です。
私の実装:
- ファイルチャンクは、Web Workerからのwritable streamを使用してOPFSに直接書き込まれます。これによりブラウザのメモリ制限が完全に回避されます——ギガバイト単位のファイルを処理できます。
- ファイルメタデータ(チャンク数、受信済みチャンクインデックス、ファイル名、総サイズ)はIndexedDBに保存されます——小さく、構造化され、クエリ可能だからです。
再接続時に、レシーバーはIndexedDBをクエリして、そのファイルの転送が完了したかどうかを確認します。完了していない場合、シグナリングチャネルを介して最後に正常に受信されたチャンクインデックスを送信者に送信します。送信者は先をスキップし、そのチャンクから開始します。
パス2:IndexedDBのみ(Safari / iOS)
SafariはWeb WorkersからのOPFSアクセスをサポートしておらず、iOSではFile System Access APIが完全に利用できません。つまり、メインスレッド外でディスクにストリーミングすることはできません。
Safariユーザーの場合、フォールバックはすべてにIndexedDBを使用することです——ファイルチャンクとメタデータの両方です。
これは機能しますが、上限があります。IndexedDBはディスクにフラッシュする前にデータをメモリに保存するため、非常に大きなファイルは最終的にSafariのメモリ制限に達します。特にiOSでは制限が厳しく、ファイルサイズは事実上制限されており、転送開始前にサイズ警告を表示することでエクスペリエンスが段階的に低下します。
理想的ではありませんが、正直です。ツールはブラウザが何ができて何ができないかを明確に示し、黙って失敗するのではなく、ユーザーに知らせます。
シグナリング:最小限に保つ
シグナリングサーバーの唯一の仕事は、WebRTC接続が確立されるまで、ピア間でSDPとICE候補を中継することです。このためにWebSocketを使用しています——単純で広くサポートされており、低遅延です。
サーバーはユーザーを認証しません(アカウント不要)、アクティブなセッションを超えてメッセージを保存せず、何が転送されているかを知りません。データチャネルが開くと、シグナリングサーバーは転送とは無関係になります。
本番環境では、NAT背後のピアが接続できるようにSTUN/TURNサーバーが必要です。UDPがブロックされているシナリオのために、パブリックSTUNサーバーとセルフホスティングされたTURNサーバーを組み合わせて使用しています。
ブラウザのメモリ制限を回避する
これが最も驚いた部分です:データチャネル自体にメモリ問題はない——レシーバーのストレージ戦略に問題があるのです。
2 GBのファイルを受信し、ArrayBufferで再構築しようとすると、ブラウザがクラッシュします。鍵は、着信チャンクをメモリに全体のファイルを保持せずに直接ストレージ(OPFSまたはIndexedDB)にストリーミングすることです。
OPFS + Web Workerを使用すると、これは見事に機能します——メインスレッドは応答性を維持し、ファイルは単一のメモリ内オブジェクトとして存在することはありません。これがTransP2Pがサポートされているブラウザでマルチギガバイトのファイルを処理できる理由です。
SafariとiOS Safariはこれを実行できません。これが2つのパスの問題に戻ってくる原因です。「ブラウザで動作する」と「すべてのブラウザで同様に動作する」は2つの異なることであるという良い思い出です。
非同期モード:P2Pが不可能な場合
両方のピアが同時にオンラインの場合、P2Pは素晴らしいです。しかし、まだオンラインでない人にファイルを送信したい場合や、接続が続けて失敗する場合もあります。
このため、TransP2Pにはオプションのサーバーキャッシュモードがあります。サーバーにファイルをアップロードし(暗号化され、サーバーに送信されることのないランダムに生成されたキーを使用)、ダウンロードリンクまたはコードを取得し、後で受信者がそれを取得します。ファイルは自動的に期限切れになります——設定された時間後またはダウンロード回数に達した後のいずれかです。
これはサーバーリソースを消費するため有料機能ですが、暗号化設計によりサーバーはファイル内容を見ることができません。暗号化キーはクライアント側で派生され、ダウンロードリンクのフラグメント(#の後の部分)に埋め込まれるため、サーバーには全く到達しません。
早く知っておきたかったこと
ICE候補の収集に時間がかかります。 接続がスタックしていると仮定しないでください——通常はあと数秒必要です。ユーザーにフィードバックを表示してください。
モバイルブラウザはデスクトップブラウザではありません。 iOS Safariは現代のブラウザの中で最も厳しい制限を持っています。ローンチ後ではなく、早い段階でテストしてください。
データチャネルの信頼性と速度の間にトレードオフがあります。 ordered: trueは順序保証を提供しますが、パケット損失時にストールする可能性があります。ファイル転送の場合、ordered: trueとチャンクレベルのチェックサムを選択しました——実際にストールすることはまれであり、順序のバグの方が悪いからです。
人々は「P2P」を理解していません。 最大のUX課題は技術的なものではありませんでした——ファイルがアップロードされずに転送される理由を説明することでした。同様のものを構築する場合は、「動作原理」のコピーに時間を費やしてください。
試してみる / コードを見る
TransP2Pは無料で使用できます(P2Pモードは完全に無料;サーバーキャッシュは有料)。アカウント不要、インストール不要:
サイトには、P2Pファイル転送が実際にどのように機能するかとクラウドベースのファイル転送の隠されたプライバシーリスクに関するいくつかの長めの記事もあります——非技術的な側面に興味がある場合、これらは一般の読者向けに書かれています。
WebRTCデータチャネルで何かを構築したことがある場合、どのようなトレードオフをしたか聞きたいです——特に大きなファイルの処理について。2026年でもブラウザストレージの状況はまだ混乱しており、より多くの実地報告が誰もかに役立つでしょう。
この記事は元々TransP2Pの作者によって書かれました。P2Pツールやブラウザベースのファイル転送を開発している場合は、気軽に連絡してください。