そもそも何を作ろうとしていたのか
今回のテーマは、番組のメンバーシップ限定配信の環境をフルスクラッチで自作したものの、沼にはまって最終的に全部捨てたという話です。
結果から言うと、配信基盤は作り終わり、すでにプレミアム回を2本配信済みだと話されています。ここでは、その裏側の設計と葛藤が語られます。
クワハラさんがやりたかったことは4つあったそうです。普段の配信基盤にはArt19ポッドキャストの配信・ホスティングサービス。音声ファイルを各ポッドキャストアプリにRSS形式で届ける役割を担う。を使っていて、そこにプレミアム限定エピソードも追加して運用したいと考えていました。
公式サイトで通常回とプレミアム回を時系列でまとめて表示し、Apple Podcastなどのアプリでもプレミアム回を購読できるようにする。そして解約したら即座に聞けなくする、という4点です。
新聞の朝刊は誰でも読めるんだけど、有料版だけ届く号外がある。それをアプリでも自然に読めるようにしたいねみたいなイメージで思ってたんですね。
今回は外部サービスに頼らず、フルスクラッチで作ってみようと考えたそうです。以前から個人開発をしたい欲があり、これを機にまだ触れていない技術にもチャレンジしようとしたと話されています。
フェーズ1〜2、フィード結合とURL流出の壁
Art19にはオルタネイトフィード限定フィードとも呼ばれる、決まった相手だけに配信を届けるための専用のRSSフィード。会員限定配信などに使われる。という機能があり、これを使う前提でスタートしました。
フェーズ1は、通常フィードと限定フィードの2つを取得して、時系列に混ぜて並べるだけ、というシンプルな発想でした。しかし、そう簡単にはいきませんでした。
1つ目の壁は、Art19の埋め込みプレイヤーが限定フィードのエピソードに対して404を返すことでした。仕方なく、ブラウザ標準の音声再生機能であるオーディオタグで直接再生する方式に切り替えます。
2つ目の壁はより深刻でした。この方式ではRSSに書かれた音声ファイルの場所を直接読み取る必要がありますが、サイトをビルドするとその場所がJavaScriptにそのまま埋め込まれてしまいます。
つまり、ブラウザの開発者ツールを開けば、限定フィードのURLが誰でも見えてしまう。URLさえ知っていればお金を払っていない人でもエピソードが見えてしまうため、プレミアム配信の基盤としては破綻していると判断され、ボツになりました。
フェーズ2〜3、サーバー移行と外部サービスの比較
フェーズ2では、フィード取得の処理を裏側のサーバーであるFirebase Cloud FunctionsGoogleが提供するFirebaseの機能の一つ。サーバー側で任意の処理を動かせる仕組みで、ブラウザに見せたくない処理を隠すのに使われる。に移し、ブラウザ側にフィードの場所を見せない構成にしました。
サーバー側では会員かどうかのチェックも実装しました。しかし、返ってくる音声ファイルのURL自体が、コピーすればそのままアクセスできる直リンクだったのです。
会員がそのURLをSNSなどで共有すれば、結局お金を払わずに聞けてしまう。フィードの場所は隠せても根本問題は変わらないため、これもボツになりました。
フェーズ3では、外部サービスを真剣に比較します。SupercastやMemberful、Patreonといったサービスが検討されました。
| サービス | 費用 | 特徴 |
|---|---|---|
| Supercast | 月額固定費なし、売上5.5%+決済手数料 | 会員ごとに専用フィードを発行 |
| Memberful | 月額25ドル固定+決済手数料 | 会員ごとの専用フィードを発行、個人には固定費が重い |
| Patreon | 手数料5〜12% | ポッドキャスト専門ではなく不要なオプションが多い |
Memberfulは多くのポッドキャストが使っており最初に注目したものの、月額25ドルの固定費が無名の配信者には重いと感じたそうです。
いや、毎月二十五ドルですよ。それ払うんだったらAIに金払いますよね。
他番組の実例として、Rebuild.fmやbackspace.fmも参考にしたと話されています。専用サイト経由のダウンロード方式や、Ghostというブログサービスでプレミアム配信を運用する方法があったそうです。
Supercastも一度検討したものの、ランニングコストが高いのがどうしても嫌で、改めて自作する方向に切り替えます。ここから本格的な沼にはまっていきました。
フェーズ4〜5、認証方式の限界とプロキシの自作
フェーズ4では、Art19の認証経路を調べ、サポートに相談すると2つの方法が提案されました。
決まった合言葉をURLにつけてアクセスを許可する。ただし全会員共通なので、一人でも漏らすと全員アウトになる。
リクエストごとに本人証明を送る仕組み。だがブラウザの音声再生やポッドキャストアプリは追加情報を付けられず、直接聞けない。
合言葉方式は、漏洩すれば全員が聞けてしまい、合言葉を変えると全会員のフィードURraLまで無効になるため断念しました。
JWTJSON Web Tokenの略。リクエストのたびに「これは私です」と示す証明書のような情報を一緒に送る認証の仕組み。を使う身分証明書方式も、ポッドキャストアプリからは追加情報を付けられず、直接聞けないという致命的な問題がありました。
どちらの方式もアプリから直接聞ける条件を満たせず、結局は間に立って通行手形をチェックするプロキシを自分で用意するしかない、という結論に至ります。
フェーズ5では、Cloudflare Workers世界中に配置されたサーバー上で、瞬時に起動する小さなプログラムを動かせるサービス。起動の待ち時間がほぼゼロなのが特徴。で認証プロキシを自作しました。クワハラさんはこれを初めて使ったそうですが、使いやすかったと話されています。
ランニングコストも結構安かったし、欲しい機能は本当に揃っていてスピードも速いので良かったんですよね。
高速なデータ保存の仕組みであるKVも内蔵されており、アクセス許可の判定が一瞬で終わる点も魅力だったそうです。無料枠も1日1万リクエストと、コスト的にも困らなさそうだと判断されました。
全体の構成は二段構えです。Firebaseで会員登録と決済管理を行い、Cloudflare WorkersとKVでリクエストのたびにアクセス可否を判定します。期限付きの署名入りURLとKVの二重チェックで、URLが流出しても即座に無効化できる仕組みになりました。
技術的には、これでやりたいことをすべて実装できる設計に到達したのです。
フェーズ6、全部捨ててSubstackへ一本化
フェーズ6では、頑張って実装した設計を全部捨てました。捨てた理由は技術的な問題ではなく、維持コストと、それ以上に大きいセキュリティ管理の負担でした。
運用コストの試算では、金額自体はPatreonやSupercastより低く、飲めなくはない範囲だったそうです。それでも金額よりずっと重かったのが、セキュリティの負担と運用し続けるコストでした。
FirebaseとCloudflare Workersという2つの異なるサービスを組み合わせているため、片方が壊れるともう片方とずれるリスクがあります。署名鍵の交換、有効期限の管理、決済通知の重複対策や再送設計など、手間が積み重なっていきます。
そして個人運営である以上、その全責任を最後は一人で背負わなければいけない。昨今のサプライチェーン攻撃やライブラリへの攻撃が増えていることもあり、その恐怖が強かったと話されています。
本来僕がやりたかったのは、あくまで配信であって、インフラの運用がしたいわけではない。それを背負うコストをかけたくなかったんですよね。
最終的に、配信の全機能をSubstackに一本化することにしました。手数料は売上の10パーセントで、音声の保管も認証も会員管理も配信もすべてSubstackが持ってくれます。
一番悩んだのはLISTENと連携するroomというサービスだったそうですが、昔から使い慣れていたSubstackを選んだと話されています。
なぜSubstackだと構成がシンプルになるのか
Substackを決め手にしたのは、有料エピソードの扱い方でした。無料エピソードには音声ファイルの場所が書かれていますが、有料エピソードにはその情報が書かれていないのです。
つまりサイト側は「音声の場所が書かれていなければ有料」というシンプルな条件で判定できます。認証も署名も高速データ保存も一切不要になり、構成が大きくシンプルになりました。
Firebase+Cloudflare Workers+KVで、署名入りURLの発行、会員判定、認証プロキシなどを自前で運用する二段構えの構成
Art19とSubstackの公開情報をサイトで時系列表示するだけ。無料回はブラウザで再生、有料回はSubstackにリンクし、認証も再生も外部に任せる
自作したものは、ちょっとした通信の許可設定を残して、あとはほぼ全部消したそうです。音声取り付け係の仕組み、会員データの高速保存、会員登録やデータベースと決済の連携などを削除しました。
受け入れたトレードオフは、決済手数料が上がったこと、再生画面を自由にデザインできなくなること、アクセス解析が細かく見られなくなることなどです。これらは配信が軌道に乗るまでの保険料や勉強代として、一旦受け入れると割り切っています。
ブラウザだけで完結する認証は基本的に不可能で、間に立つプロキシが必ず必要になる。会員データの管理場所とアクセス判定の場所を分ける設計は、試行錯誤の末にたどり着いたもので、大きな学びになったと振り返っています。
設計を丸ごと捨てる判断には葛藤もあったそうです。苦労して作ったものを壊すのは、サンクコストのようなもったいなさがあるからです。
もちろんコードはAIに書かせたとはいえ、何度もやり直したり、ここの設計とか脆弱性あるんじゃないの、とかさんざっぱらやったので、頑張って作ったものを捨てるってもったいないというか。
まとめ
メンバーシップ配信の基盤をフルスクラッチで作ろうとしたクワハラさんは、フィード結合、サーバー移行、認証プロキシの自作と段階的に沼へはまり、最終的にすべて捨ててSubstackに一本化しました。技術的には実現できても、個人が背負うべきものではないという結論に落ち着いた回です。
- 通常回と限定回を混ぜるだけの構想だったが、URL流出や認証の壁が芋づる式に出てきた。
- ブラウザだけで完結する認証は不可能で、間に立つプロキシを必ず用意する必要がある。
- Cloudflare Workersなど新しい技術に触れられたことは大きな学びになった。
- 決め手は、有料回に音声の場所が書かれないSubstackの仕様で、判定が一気にシンプルになった。
- 認証・課金・配信インフラは、個人であれば外部サービスに任せた方が無難という結論に至った。
