これは何?
Video Chain Player というWebアプリを作りました。「動画の必要な部分だけをつなぎ合わせて、一つの体験として再生・共有できる」アプリです。
🔗 試してみる: https://video-chain-player.sloth255.com/
- 開始・終了時間を指定して動画をクリップ
- 複数のクリップを**チェーン(キュー)**して連続再生
- チェーンの状態をURLにエンコードして1つのリンクで共有
ワークアウトフロー、講義のハイライト、コンピレーション動画など、「この部分だけ見せたい」という体験にぴったりです。
ユーザーができること
- クリップ作成: URL/IDと開始・終了時間を入力して動画を追加
- 並び替え: ドラッグ&ドロップでシーケンスを調整
- プレビュー: その場で再生してタイミングを確認
- 共有: URLをコピーして送信(受け取った相手も同じチェーンを開ける)
- 多言語対応: URLで言語を切り替え(例:
?lang=ja)
技術スタック
| 領域 | 技術 | 備考 |
|---|---|---|
| フロントエンド | React 18 + TypeScript | UIの保守性と型安全性 |
| ビルド/開発サーバー | Vite | 高速HMR、快適なDX |
| ルーティング | React Router v6 | パス + クエリで状態を表現 |
| 状態管理 | Zustand | 軽量、URL同期に適している |
| ドラッグ&ドロップUI | @dnd-kit | 並び替えの実装 |
| 動画プレイヤー | react-youtube(IFrame Player API) | 簡単な埋め込み再生 |
| i18n | i18next + react-i18next | 全UIテキストの翻訳 |
| 翻訳ロード | i18next-http-backend | /public/locales/... からランタイムフェッチ |
| 言語検出 | i18next-browser-languagedetector | 優先順位:?lang= / localStorage / ブラウザ |
| アナリティクス | GA4(gtag) | SPAのpage_view + カスタムイベント |
| ホスティング | S3静的サイト + CloudFront | CDN配信 |
| IaC | AWS SAMテンプレート | S3/CloudFrontをコードで管理 |
| CI/CD | GitHub Actions + OIDC | 長期キーなしでデプロイ |
| テスト | Vitest + Testing Library | コンポーネント/ロジックのテスト |
| Lint/フォーマット | ESLint + Prettier | 破壊的変更の防止 |
アーキテクチャと実装のポイント
1) ZustandのステートをURLに同期して即座に共有
共有の手間を最小化するため、チェーンの必要な情報をURLにエンコードする設計にしました。
- サーバーサイドのストレージ不要(アカウント不要)
- 受け取った側はリンクを開くだけで同じ状態を再現できる
URLが肥大化すると共有しにくくなるため、URLにエンコードする情報を最小化しました。
- 動画の
idとstart/end時間のみをエンコード - タイトルやサムネイルは後から補完して表示(URLの肥大化を防止)
最小エンコードの例:
// URLには必要最小限の情報(id/start/end)のみエンコード
const minimalSegments = segments.map(({ id, start, end }) => ({ id, start, end }));
また、共有リンクには再生位置(どのクリップを再生中か)を含めないことで、「リンクを開くと最初から再生される」を保証しています。
2) HTTPバックエンドによるランタイムi18nロード(ビルド非依存)
最初はビルド時に翻訳JSONをインポートすることも検討しましたが、静的ホスティングやCIとの互換性を高めるため、/public/locales/{{lng}}/translation.json からHTTPでフェッチする方式を採用しました。
- 言語ファイルを追加するだけでメンテナンスが容易
- ビルドプロセスが翻訳のインポートに依存しない
3) URLのバリエーションに幅広く対応(watch / Shorts / embed)
「標準URLのみ対応」では不便なため、入力パターンを拡張しました:
- 標準のwatch URL
- Shorts
- 埋め込みURL
結果として「貼り付けるだけ」で成功する率が上がり、まとめて登録する際もずっと楽になりました。
4) デプロイ:S3 + CloudFront、CI:GitHub Actions(OIDC)
静的サイトなのでデプロイはシンプルです:
- S3(静的ホスティング)
- CloudFront(CDN)
CI/CDはGitHub Actionsで自動化:ビルド → S3同期 → CloudFrontキャッシュ無効化。
ポイントはOIDCで、長期キーを保存せずにデプロイできます(Secretsを最小化しながら環境レベルの制御を維持)。
静的サイトでもCloudFrontを前に置くことでキャッシュによる高速ロードが得られます。
まとめ
Video Chain Playerは「クリップ × 連続再生 × URL共有」にフォーカスし、以下を重視しました:
- URLに状態をエンコードして共有の摩擦を最小化
- i18n + 言語URLの同期で受け取った側も同じ言語で見られる
- デプロイやアナリティクスも含めた「本番運用レベル」に仕上げる
技術的には:
- Viteによる高速な開発
- ZustandのステートをURLに同期して共有しやすく
- i18nextのHTTPバックエンドで軽量な翻訳管理
- OIDCによるセキュアなデプロイ
これらを一気に組み合わせた「フル稼働スタック」を構築できたのが最大の収穫でした。
