Skip to content

【openscreen】macOS録画終了時に有効なMP4を保存失敗として取り残さない #4

Open

Description

@nanameru

課題 / 目的

macOS版OpenScreen 1.10.0で録画停止後に保存失敗が表示され、エディターが開かない事象が発生した。
利用者の録画データを失わないため、ネイティブhelperの停止通知が失敗しても、完成済みで読み取り可能なMP4が残っている場合は録画セッションとして救済する。

観測事実

  • 発生環境: macOS arm64 / OpenScreen 1.10.0
  • 失敗した録画本体は recordings/recording-1788352573602.mp4 として残っている。
  • ffprobe でH.264動画、34.231667秒、18,933,868 bytesとして読み取れる。
  • 対応する .session.json と .mp4.cursor.json は作成されず、プロジェクトも作成されていない。
  • 同じ起動セッションで行った約7秒の再現用録画は正常終了し、MP4、カーソルsidecar、session manifest、projectが作成された。
  • 直前診断はhelper出力を保持しておらず、元のhelper終了理由は確定できていない。

対象範囲

  • macOSネイティブ録画の停止・保存処理
  • 停止通知失敗時に残ったMP4の安全な妥当性判定
  • 妥当なMP4をsession manifestへ接続し、エディターへ渡す救済経路
  • 成功、救済、救済不可を区別する回帰テスト
  • 診断ログに救済結果と元の停止エラーを残す

対象外

  • Windows / Linux録画経路の変更
  • 録画・編集UIのデザイン変更
  • 不完全または書き込み中のMP4を無条件で開くこと
  • 自動マージ、リリース、公開

完了条件

  • 正常なmacOS停止経路は従来どおりsession manifestを作成してエディターを開く
  • helperが停止通知に失敗しても、helperが終了済みで完成したMP4と判定できる場合は録画を救済する
  • 小さすぎる、不完全、または書き込み中のファイルは救済しない
  • 救済時は元のエラーと救済結果を診断可能なログへ残す
  • 回帰テスト、app/test TypeScript typecheck、lint、関連テストが通る
  • 実機macOSでrecord → stop → editor表示を確認する

実装計画

  1. macOS録画停止結果とMP4妥当性判定をNode-pure moduleへ分離する
  2. 失敗する回帰テストを追加する
  3. stop-native-mac-recording に安全な救済分岐を追加する
  4. テスト・typecheck・lintを実行する
  5. macOS実機で短時間録画を行い、保存物とエディター表示を確認する
  6. Draft PRを作成し、人間レビュー前で停止する

テスト / CI計画

  • unit: MP4 atom判定(正常、moov欠落、mdat欠落、切断atom、小容量)
  • unit: helper終了済みのみ救済し、稼働中は救済しない判断
  • targeted Vitest
  • npx tsc --noEmit
  • npx tsc -p tsconfig.test.json --noEmit
  • npm run lint
  • 必要に応じて npm run test
  • macOS desktop E2Eの録画停止・エディター表示

リスク / 停止条件

  • 不完全なMP4を救済するとエディター側で二次障害になるため、構造確認なしのsize-only判定は採用しない。
  • helperが生存中のファイルは書き込み中の可能性があるため救済しない。
  • 同じ原因で品質ゲートが2回失敗した場合は原因と再開点を記録して停止する。
  • merge、release、deployは人間承認まで行わない。

ナレッジログ

  • 2026-09-02: インストール済み1.10.0を確認。失敗録画のMP4本体は正常に読めるが、sidecar / manifest / projectが欠落している。
  • 2026-09-02: 同一環境で短時間録画は成功。恒常的な画面収録権限・保存先権限の問題ではない。
  • 2026-09-02: Cursor Context ScoutはCursor APIキー未設定のため利用できず、rgで停止処理とテストを手動特定した。

Beads TODO

Issue確定後に同期する。

Activity

  1. nanameru commented on Sep 2, 2026

    @nanameru
    OwnerAuthor

    実行計画メモ\n\n- test-board.yaml に回帰ケース TC-001 を追加しました。\n- Beads epic / TODO同期を試みましたが、このworktreeでは embeddeddolt: store is read-only となり依存関係作成で停止しました。細分化計画はIssue本文とローカル計画JSONを正本として継続します。\n- 次の作業: 失敗するMP4救済判定テストを追加します。

  2. nanameru commented on Sep 2, 2026

    @nanameru
    OwnerAuthor

    実装・検証ログ

    • getopenscreen/openscreen の最新 upstream/main を起点に実装
    • helper の stop 通知失敗時、helper 終了後に限り、mp4box で実映像track・sample tableを解析して完成済みMP4を救済
    • atom名だけの偽MP4を救済しない回帰テストを追加
    • 正常停止、救済成功、helper生存、無効出力の停止判定をテスト
    • 実際に取り残された録画 recording-1788352573602.mp4 は救済可能、偽MP4は拒否と確認
    • npm test: 188 files / 2246 passed / 2 skipped
    • app/test TypeScript typecheck: 成功
    • npm run lint: 成功(既存warning 15件)
    • npm run build-vite: 成功
    • test-board impact: TC-001を特定、対象テスト成功

    CLI実録画は開発版ElectronにScreen Recording権限がなく get-sources で停止したため、権限を持つパッケージ版でのE2Eを続行します。

  3. nanameru commented on Sep 2, 2026

    @nanameru
    OwnerAuthor

    完了ログ

    Draft PR: getopenscreen#571

    実機検証

    署名済みApple Silicon版を /Applications/OpenScreen.app に配置し、LaunchServices経由で5秒のCLI録画を実行しました。

    • MP4: recording-1788354727988.mp4(H.264 / 2880x1800 / 193 frames / 5.083秒)
    • cursor sidecar: 作成済み
    • session manifest: 作成済み
    • project: /tmp/openscreen-e2e/issue-4-launchservices.openscreen
    • OpenScreen info: media存在を確認して成功

    旧アプリは /Applications/OpenScreen.backup-20260902.app に退避済みで復元可能です。

    品質ゲート

    • local full test: 188 files / 2246 passed / 2 skipped
    • typecheck / lint / production Vite build: 成功
    • reviewer指摘4件(偽MP4 false positive、停止処理テスト不足、型定義位置、YAML不正)を全件修正
    • Draft PR上の実行済みchecks: 2/2 pass(full CIはDraftのため未起動)

    残作業

    • 人間レビュー後にReady for reviewへ変更し、upstream full CIを実行
    • mergeは人間判断
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions