-
Notifications
You must be signed in to change notification settings - Fork 2
Closed
Labels
Description
Note: このIssueは 2026-02-18 にレビュー結果(Stage 1, Stage 3, Stage 5)を反映して更新されました。
詳細: dev-reports/issue/302/issue-review/
概要
ワークツリーのファイル管理機能において、mp4ファイルのアップロードとブラウザ内再生(プレビュー)を可能にする。現在はアップロード可能なファイル形式に動画が含まれておらず、mp4ファイルを保存・閲覧できない。
背景・課題
開発中のアプリケーションのデモ動画をワークツリー内に保存・管理したいが、現在のUPLOADABLE_EXTENSIONSにmp4が含まれていないためアップロードできない。デモ動画をプロジェクトディレクトリに手動でコピーする必要があり、CommandMateのUI上で一元管理できていない。
提案する解決策
既存のアップロード・ファイル表示パイプラインを拡張し、mp4形式をサポートする。
主要な変更点
UPLOADABLE_EXTENSIONSにmp4のバリデータを追加(MIME:video/mp4、magic bytes検証)FileContent型にisVideoフラグを追加- ファイル表示API(GET
/api/worktrees/[id]/files/[...path])に動画ファイル判定ロジックを追加 VideoViewerコンポーネントを新規作成(HTML5<video>タグ、コントロール付き)FileViewerコンポーネントに動画表示の分岐を追加next.config.jsのbodySizeLimitを'16mb'に引き上げ、CSPヘッダーにmedia-srcを追加- upload APIのサイズ検証順序を最適化(
file.sizeチェックをarrayBuffer()前に移動)
設計方針
- ファイルサイズ上限は15MB(mp4専用の上限。既存の画像等は5MBのまま)。デモ動画を想定
- Base64 data URI方式で配信(15MB以下なのでストリーミング不要)
- 性能に関する注意: 15MBのバイナリをBase64エンコードすると約20MB(約1.33倍)のデータ量になる。レスポンスの読み込みに数秒かかる可能性があるため、
VideoViewerにローディングインジケーターを実装する。低スペック端末での動作も考慮し、将来的に頻繁な利用が想定される場合はストリーミング方式への移行を検討する
- 性能に関する注意: 15MBのバイナリをBase64エンコードすると約20MB(約1.33倍)のデータ量になる。レスポンスの読み込みに数秒かかる可能性があるため、
- mp4のみ対応(webm, mov等は対象外)
ImageViewerと同じパターンでVideoViewerを実装(統一性のある設計)- HTML5
<video>タグのcontrols属性を使用し、ブラウザネイティブの再生コントロールを利用する(カスタムコントロールは不要) - MP4 magic bytes仕様: MP4はISOBMFF構造を持ち、先頭4バイトがボックスサイズ、offset 4-7が
ftypシグネチャ。magicBytes: [{ bytes: [0x66, 0x74, 0x79, 0x70], offset: 4 }]で検証する src/config/video-extensions.tsをimage-extensions.tsと同じパターンで新規作成し、動画判定ユーティリティを独立管理する(isVideoExtension()、VIDEO_EXTENSIONS定数、getMimeTypeByVideoExtension()等)- CSP media-src:
blob:URIは現時点では不要(Base64 data URI方式のため)。将来ストリーミング方式に移行する場合はblob:の追加を検討する - bodySizeLimitの適用範囲:
next.config.jsのexperimental.serverActions.bodySizeLimitはServer Actions専用であり、Route Handler(upload API)には適用されない可能性がある。実装時に15MBのmp4ファイルで実アップロードテストを行い、制限に達する場合はRoute Handler固有の設定(route segment config等)を追加する - upload APIのサイズ検証最適化:
file.sizeチェックをarrayBuffer()呼び出し前に移動することで、サイズ超過ファイルの早期拒否を行い、不要なメモリ消費を防止する(15MB上限引き上げに伴うメモリ効率改善) - page.tsxの型統一方針:
src/app/worktrees/[id]/files/[...path]/page.tsxのローカルFileContent型はsrc/types/models.tsのFileContent型のimportに切り替える(DRY原則・型乖離解消)。これによりisImage/isVideo等のフラグが自動的に追従され、今後のフィールド追加時にも型の不整合が発生しない
実装タスク
-
src/config/video-extensions.tsを新規作成(image-extensions.tsパターンに準拠:VIDEO_EXTENSIONS定数、isVideoExtension()、getMimeTypeByVideoExtension()、magic bytes定義) -
src/config/uploadable-extensions.tsにmp4バリデータを追加(maxFileSize: 15MB、magic bytes: offset 4でftyp[0x66, 0x74, 0x79, 0x70]を検証) -
src/types/models.tsのFileContentインターフェースにisVideo?: booleanフラグを追加(オプショナル、後方互換性維持) -
src/app/api/worktrees/[id]/files/[...path]/route.tsに動画ファイル表示ロジックを追加(isVideoExtension()による分岐、画像パターンと同じ構造) -
src/app/worktrees/[id]/files/[...path]/page.tsxのローカルFileContent型をsrc/types/models.tsのFileContent型のimportに切り替え(DRY原則・型乖離解消)、動画・画像ファイルの両方に対してVideoViewer/ImageViewerを使った表示分岐を実装する -
src/components/worktree/VideoViewer.tsxを新規作成(ローディングインジケーター付き) -
src/components/worktree/FileViewer.tsxに動画表示分岐を追加し、canCopyロジックを修正(!content.isImage && !content.isVideoで動画ファイルにコピーボタンが表示されないようにする) -
next.config.jsのexperimental.serverActions.bodySizeLimitを'16mb'(15MB + overhead)に更新する -
next.config.jsの CSPヘッダーにmedia-src 'self' data:を追加する -
src/app/api/worktrees/[id]/upload/[...path]/route.tsでupload APIのサイズ検証順序を最適化する(file.sizeチェックをarrayBuffer()前に移動し、サイズ超過ファイルの早期拒否でメモリ効率を改善) -
src/app/api/worktrees/[id]/upload/[...path]/route.tsで15MBのmp4アップロードが実際に動作するかを検証し、bodySizeLimitがRoute Handlerに適用されない場合はRoute Handler固有の設定を追加する - ユニットテスト追加:
tests/unit/config/uploadable-extensions.test.tsにmp4バリデーションテスト追加(isUploadableExtension、validateMimeType、validateMagicBytes、getMaxFileSize)tests/unit/config/video-extensions.test.tsを新規作成(image-extensions.test.tsパターン準拠:isVideoExtension、getMimeTypeByVideoExtensionテスト)
- 結合テスト追加:
tests/integration/api/file-upload.test.tsにmp4アップロードのバリデーション結合テスト追加tests/integration/api-file-operations.test.tsにGET APIでの動画ファイル取得テスト追加
受入条件
- mp4ファイルをUIからアップロードできること
- アップロードしたmp4ファイルがファイルツリーに表示されること
- mp4ファイルをクリックするとブラウザ内で再生(プレビュー)できること(再生/停止コントロール付き)
- 15MBを超えるmp4ファイルのアップロードが拒否されること
- 不正なファイル(拡張子をmp4に偽装した非動画ファイル)がmagic bytes検証(offset 4で
ftypシグネチャ)で拒否されること - 動画ファイル選択時にコピーボタンが表示されないこと
- 動画読み込み中にローディングインジケーターが表示されること
-
/worktrees/[id]/files/path/to/video.mp4への直接URLアクセスで動画が正しく再生されること(FileViewerPage対応) -
/worktrees/[id]/files/path/to/image.pngへの直接URLアクセスで画像が正しく表示されること(FileViewerPageでのImageViewer統合。page.tsxのローカル型をmodels.tsのimportに切り替えることで対応) - 既存のアップロード機能(画像、テキスト等)に影響がないこと
- 全既存テストがパスすること
影響範囲
変更対象ファイル
| ファイル | 変更内容 |
|---|---|
next.config.js |
bodySizeLimitを'16mb'に更新、CSPヘッダーにmedia-src 'self' data:追加 |
src/config/uploadable-extensions.ts |
mp4バリデータ追加(15MB上限) |
src/types/models.ts |
FileContentにisVideo?: booleanフラグ追加(オプショナル、後方互換性維持) |
src/app/api/worktrees/[id]/files/[...path]/route.ts |
動画ファイル判定・Base64変換ロジック追加 |
src/app/api/worktrees/[id]/upload/[...path]/route.ts |
サイズ検証順序最適化(file.sizeチェックをarrayBuffer()前に移動)、15MB対応の検証 |
src/app/worktrees/[id]/files/[...path]/page.tsx |
ローカルFileContent型をsrc/types/models.tsのimportに切り替え、動画・画像ファイルの表示分岐をVideoViewer/ImageViewerで実装 |
src/components/worktree/VideoViewer.tsx |
新規作成 - HTML5動画プレーヤー(ローディングインジケーター付き) |
src/components/worktree/FileViewer.tsx |
動画表示分岐追加、canCopyロジック修正 |
新規作成ファイル
| ファイル | 内容 |
|---|---|
src/config/video-extensions.ts |
動画拡張子定義(VIDEO_EXTENSIONS)・magic bytes・MIME定義・isVideoExtension()・getMimeTypeByVideoExtension()(image-extensions.tsパターン準拠) |
src/components/worktree/VideoViewer.tsx |
動画再生コンポーネント |
tests/unit/config/video-extensions.test.ts |
動画拡張子ユーティリティのユニットテスト |
関連コンポーネント(変更不要だが影響確認が必要)
src/config/binary-extensions.ts- mp4は既に直接リテラルとして登録済み(変更不要)。ただしvideo-extensions.ts新規作成に伴い、image-extensions.tsのIMAGE_EXTENSIONSスプレッドと同様にVIDEO_EXTENSIONSのスプレッド統合パターンを将来的に検討する(webm等の拡張子追加時の一貫性確保のため)src/components/worktree/WorktreeDetailRefactored.tsx- アップロードUIはUPLOADABLE_EXTENSIONSを動的参照しているため自動対応。なお、input要素のaccept属性は拡張子のみで指定しているが、モバイルブラウザでの動画ファイル選択に問題が見つかった場合はMIMEタイプ(video/mp4)の併記を検討する(実装時テストで確認)src/lib/file-search.ts- バイナリ除外リストにmp4が既に含まれている(変更不要)src/components/worktree/FileTreeView.tsx- FileIconコンポーネントのcolorMapにmp4用エントリが未定義(デフォルト色text-gray-400で表示される)。動画ファイルを視覚的に区別するためにmp4用のアイコン色追加(例:text-purple-500)はNice to Haveとして検討
レビュー履歴
Stage 1 レビュー (2026-02-18)
Must Fix:
- FINDING-001:
next.config.jsのbodySizeLimit更新を実装タスク・影響範囲に追加 - FINDING-002: CSPヘッダーの
media-srcディレクティブ追加を実装タスク・影響範囲に追加
Should Fix:
- FINDING-003:
FileViewer.tsxのcanCopyロジック修正(isVideo除外)を実装タスク・受入条件に明記 - FINDING-004: MP4 magic bytes仕様(offset 4で
ftyp=[0x66, 0x74, 0x79, 0x70])を設計方針・実装タスクに追記 - FINDING-005:
video-extensions.tsを候補から確定に変更、image-extensions.tsパターン準拠の設計を明記 - FINDING-006: 15MB Base64の性能注意事項(約20MBデータ量、ローディングインジケーター必要)を設計方針に追記
- FINDING-007:
binary-extensions.tsのVIDEO_EXTENSIONSスプレッド統合パターン検討事項を影響範囲に追記
Stage 3 影響範囲レビュー (2026-02-18)
Must Fix:
- FINDING-S3-001:
bodySizeLimitはServer Actions専用でRoute Handlerに適用されない可能性 - 設計方針にbodySizeLimit適用範囲の注意事項を追記、実装タスクに15MB実アップロードテストとRoute Handler固有設定の検討を追加 - FINDING-S3-002:
page.tsxのローカルFileContent型がisVideo未対応 - 変更対象ファイルにpage.tsxを追加、実装タスクにローカル型のisVideo対応を追加、受入条件に直接URLアクセスでの再生確認を追加
Should Fix:
- FINDING-S3-003: テスト対象の網羅性不足 - 実装タスクのテスト項目を具体的なファイル名・テストケースに分解
- FINDING-S3-004: FileTreeView.tsxのFileIconにmp4用アイコン色未定義 - 影響確認セクションにNice to Haveとして記載
- FINDING-S3-005: CSPのmedia-srcにblob: URIが不要であることの確認 - 設計方針にblob不要の根拠と将来方針を追記
- FINDING-S3-006: FileContent型のisVideoフラグの後方互換性 - 実装タスクにオプショナルフラグであることを明記
- FINDING-S3-007: upload APIのfile.sizeチェックをarrayBuffer()前に移動する最適化 - 設計方針と実装タスクにサイズ検証順序最適化を追記、変更対象ファイルにupload APIを追加
Stage 5 レビュー (2026-02-18)
Should Fix:
- FINDING-S5-001: page.tsxのローカルFileContent型をmodels.tsのimportに統一する方針を明確化 - 設計方針に「page.tsxの型統一方針」セクションを追加、実装タスクをimport切り替え方式に更新、変更対象ファイルの説明を更新
- FINDING-S5-002: page.tsxでの画像・動画ファイル表示の両方の対応を明確化 - 実装タスクにVideoViewer/ImageViewer両方の統合を明記、受入条件に画像の直接URLアクセス表示確認を追加
Nice to Have:
- FINDING-S5-003: WorktreeDetailRefactored.tsxのinput accept属性にMIMEタイプ併記の検討 - 関連コンポーネントの説明に実装時テストでの確認事項として追記
Reactions are currently unavailable