Communitygithub.com

mikey-relevanceai/record-demo

UIの変更を示す、人間が操作しているように見えるMP4ウォークスルーを録画し、PRに添付します。ヘッドレスPlaywrightを使用したWebアプリと、実際のディスプレイまたはウィンドウキャプチャを使用したElectronデスクトップアプリに対応しています。

record-demo とは?

このスキルは、UI変更のデモンストレーションビデオを録画するための包括的なフレームワークを提供します。主な特徴は、カーソルの曲線パス、キーストロークごとのタイピング、意図的なポーズなど、人間らしい操作を再現し、機械的な操作感を与えないことです。 対応プラットフォームは2つあります。Webアプリ向けには、PlaywrightベースのヘッドレスChromiumを使用し、DOMカーソルを描画して記録します。デスクトップアプリ(Electron)向けには、実際のディスプレイまたはウィンドウキャプチャを使用し、ネイティブメニューやファイルダイアログなど、レンダラープロセスの外側の動作も記録できます。 このスキルの真の価値は、その厳格なルールセットにあります。録画前に必ずリハーサルを行うこと、実際のコントロール名をプローブしてからスクリプトを作成すること、固定のタイムアウト(waitForTimeout)ではなく、実際の要素の状態を待つこと、そして録画後にフレームと終了ステータスを検証することなどが挙げられます。これらのルールは、一度破られてテイクが無駄になった経験に基づいており、品質の高いデモを効率的に生成するために重要です。

対応✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/mikey-relevanceai/record-demo/tree/main/skills/record-demo

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

プレビュー

スキル README より

alt

ドキュメント

デモを録画する

人間がアプリを使用しているように見えるウォークスルーを録画します。曲線のカーソルパス、キーストロークごとのタイピング、意図的なポーズなど、機械がUIを高速で操作しているようには見えません。

以下のルールは、すべての録画、すべてのプラットフォームに適用されます。 これらのルールがプラットフォームリファレンスではなくここに記載されているのは、それぞれのルールが一度破られてテイクを無駄にしたことがあり、また、一つのメカニズムの横にしかルールを置かないと、次にそのルールを読む人が見落とすからです。

プラットフォームを選ぶ

  • Webアプリ - reference/web.md。Playwrightを使用したヘッドレスChromiumで、ページにDOMカーソルを描画します。オペレーターの画面には何も表示されないため、変更がブラウザで確認できる場合はこちらを優先します。
  • デスクトップアプリ - reference/desktop.md。デモに実際のElectronシェル(ネイティブメニュー、ファイルダイアログ、トレイ、複数ウィンドウ、レンダラーの外部のもの)が必要な場合に使用します。Linuxにはバンドルされたランナーがあります。macOSはウィンドウIDで単一ウィンドウを録画し、まだランナーはありません。

変更が両方で確認できる場合、Webアプリで録画します。

入力

最初のテイクの前にこれらを確立します。プロジェクトから読み取れるもの(README、package.jsonのスクリプト、Electronのメインプロセス)はそこから読み取り、見つからないものは推測せずにユーザーに確認します。

  • Web: 実行中のアプリのURL。レコーダーに PR_RECORDER_BASE_URL として渡します(例:http://localhost:3000)。アプリは、変更を含むチェックアウトからすでに実行されている必要があり、未コミットの編集も含まれます。同じブランチの新しいチェックアウトにはそれらの編集は含まれず、gitは同じブランチを二回チェックアウトすることを拒否します。また、デモに必要な状態になっている必要があります。フローにサインインユーザーやシードデータが必要な場合、それはプロジェクトのセットアップが提供するものであり、レコーダーの責任ではありません。ただし、キャプチャ開始前に確認してください。確認しないと、サインイン画面のテイクができあがります。
  • デスクトップ:
    • DEMO_APP_DIR - アプリの起動コマンドが実行されるディレクトリ。
    • DEMO_WINDOW_TITLE - メインウィンドウの正確なタイトル。X11ウィンドウとレンダラーページの両方を見つけるために使用されます。
    • DEMO_LAUNCH_CMD - オプション。{port} でリモートデバッグを有効にしてアプリを起動するシェルコマンド。デフォルトの pnpm dev --remoteDebuggingPort {port} --noSandbox は electron-vite に適しています。

スキルが存在する場所

このドキュメントでの <skill-dir> は、この SKILL.md が読み込まれたディレクトリを意味します。Claude Codeでは ${CLAUDE_SKILL_DIR} であり、プロジェクト、個人、プラグインのインストールのいずれでも機能します。それ以外の場所では、スキルが読み込まれたパスを使用します。Codexの場合は、リポジトリ内の .agents/skills/record-demo フォルダまたは ~/.agents/skills/record-demo です。一度解決して絶対パスを使用します。スクリプトはスキルがどこにインストールされているかを決して想定しません。

本番テイクの前にリハーサルを行う

実際に出荷するテイクを録画する前に、フロー全体を最初から最後まで実行します。デモは書かれるものではなく、発見されるものです。コントロール名は予想通りではない、ボタンはラベルと違う動作をする、プラットフォームが落ち着くまでに予想より時間がかかる、といったことが起こります。それをカメラの前で知ることになると、視聴者はあなたがそれを発見する過程を見ることになります。

リハーサルは安価で、再録画も安価です。間違った方向に進んだテイクを出荷したり、レビュアーに真ん中の8秒を無視するように頼むことは、そうではありません。

最初に実際のコントロール名をプローブする

存在が確認されておらず、名前が示す通りの動作をするか確認していないコントロールに対してスクリプトを作成しないでください。 アプリを一度ロードし、アクセシブルな名前をダンプし、スクリーンショットを撮ります。

const names = await page
  .getByRole("button")
  .evaluateAll((els) =>
    els.map((e) => (e.getAttribute("aria-label") || e.textContent || "").trim()).filter(Boolean),
  );
console.log(JSON.stringify(names));
await page.screenshot({ path: "/tmp/probe.png" });

そしてスクリーンショットを読みます。ダンプは名前が存在することを教えてくれます。コントロールが何であるかを教えてくれるのは画像だけです。これが問題になる4つのケース:

  • 予想とは異なる名前。 スイッチャーのアクセシブルな名前は、現在選択されているアイテムの名前であり、「プロジェクトを選択」ではありませんでした。
  • 聞こえと違う名前。 サイドバーの Files ボタンはセクションのトグルであり、クリックするとどこにも移動せずにセクションが折りたたまれました。それがテイクに出荷されました。
  • 別の名前に一部として含まれる名前。 getByLabel("First message") が、ラベルに「first message」を含む近くのオプションにも一致したため、入力がフィールドに到達せず、エラーも発生しませんでした。exact: true を渡すか、ロールと名前の両方で一致させてください。
  • テキストのように見えるがそうではないもの。 スクリーンショットから読み取ったピッカーの見出しは、入力フィールドのプレースホルダーだったため、getByText では決して一致しませんでした。スクリプトを作成する前に、ロケーターが解決されることを確認してください。

複数の要素が同じ名前を共有する場合(アイテムがサイドバー、ページヘッダー、パンくずリストに表示される場合)、.first() でスコープを絞ります。

人間が操作するようにドライブする

可視ロールまたはテキスト(getByRole、getByText、getByLabel、getByPlaceholder)でコントロールを見つけます。CSSセレクター、テスト専用属性は決して使用せず、録画のためにコントロールを見つけられるようにアプリにフックを追加しないでください。デモスクリプトは使い捨てでPRごとのものです。リポジトリの外に保管してください。

デモのためにアプリ、スキル、またはプロダクションコードを決して変更しないでください。 デモがアプリの変更を必要とする場合、デモが間違っています。

時間で待機しない

waitForTimeout(9000) で「エディターの読み込みを待つ」ことは、見られるけれども退屈なデモの最大の原因です。常に最悪のケースを支払うことになり、その秒数のすべてがファイルに含まれます。実際に待っているもの(最初に操作するコントロール)を待つことで、アプリの準備ができた瞬間にデモが続行され、失敗した場合にはロケーターの名前を明示して大声で失敗し、半構築のページをドライブしません。

固定のポーズは、ペーシングのためだけに使用します。アクションの後のビートで、視聴者が何が変わったかを理解するためのものです。秒単位、十秒単位ではなく、待機の代わりとして決して使用しないでください。

書き込まれたファイルは証拠にならない

レコーダーはスクリプトがスローされたときに部分的なファイルをフラッシュし、一部のキャプチャツールは終了時にその時点の内容を書き込みます。したがって、ファイルが存在するだけでは何の意味もありません。テイクを信じる前に:

  • 終了ステータスとstderrを確認し、エラーがあればそれを読みます。通常、一致しなかったロケーターの名前が示されています。
  • 出力パスをすでに保持している古いキャプチャがないか確認します。 以前の試行から実行中のままのキャプチャがまだファイル名を所有しており、静かに間違ったものの録画を生成します。
  • フレームを確認します。 コンタクトシート、最終フレーム、および不確かなトランジションを抽出して確認します。

スクリプトではなくデモを検証する

クリーンな終了はスクリプトが実行されたことを意味し、機能が動作したことを意味しません。両方を確認します:

  • 視覚的 - 変更がフレーム内の画面に、要求された状態で表示されていること。
  • 機能的 - 永続化された状態が実際に変更されたこと。UIから推測するのではなく、データベースまたはAPIから読み取って確認します。

主張がレイアウトに関する場合(2つのペインが並んでいる、パネルがエッジにドッキングされているなど)、バウンディングボックスからアサートします。要素が存在することは、それらがどこにあるかについては何も語りません。

最終状態を約3秒間保持して視聴者がそれを確認できるようにし、その後、ffprobe で出力ファイルのコーデック、寸法、および期間を検証してから引き渡します。

証拠を保持する

テイクが成功するまで、失敗ログ、部分的なテイク、スクリーンショットを保持します。出荷できるものができた後にのみ、使い捨ての状態を削除します。捨てられた中間生成物は、テイクが失敗した理由の唯一の記録であることがよくあります。

録画中のマシンを妨害しない

ローカル録画は、人が実際に使用しているコンピューター上で実行されます。

  • アプリに独自の使い捨てプロファイルを与え、オペレーターの実際のプロファイルには決して触れません。
  • デモに必要なものは、最初の起動の前にシードします。そうしないと、初回起動画面がユーザーの前に表示されます。
  • 開始したすべてのプロセスを所有し、終了したら停止します。特にキャプチャは、スクリプトが戻った後も実行し続けます。
  • 長時間実行されるプロセスは、フォアグラウンドラッパー内の末尾の & ではなく、ハンドルを保持するバックグラウンドタスクとして開始します。ラッパーが終了すると、サーバーも終了します。
  • プロセスが期待する方法で停止します。SIGKILLで強制終了された開発サーバーはクリーンアップトラップをスキップし、書き換えられたenvファイルと古いポートファイルを残しました。開始したプロセスにシグナルを送信し、クリーンアップさせます。決してパターンキル(pkill -f next)はしないでください。共有マシンでは、他の人のサーバーも強制終了します。
  • デモ対象のアプリが通信するバックエンドを確認します。ある開発ランチャーは、特に指示がない限りプロダクションAPIをデフォルトで使用していたため、デモのクリックが実際のデータを書き込む可能性がありました。最初のテイクの前に、ローカルまたは開発用のバックエンドを指すように設定します。
  • デモが依存する外部のもの(サインインが必要なCLI、稼働している必要があるサービスなど)は、ディスプレイを取得したりキャプチャを開始したりする前に事前チェックします。そうすることで、欠落している依存関係がテイクの途中ではなく数秒で失敗します。ツールが起動したことを証明するためだけに、メッセージの送信などの副作用のあるアクションを決して実行しないでください。
  • テイクがユーザーの画面、ウィンドウマネージャー、または入力を必要とする場合は、それを伝えて、奪うのではなく要求します。

ファイルをPRに添付する

gh はバージョン2.99.0以降、ビデオ自体をアップロードします。

gh pr comment <number> --body-file ./note.md --attach ./demo.mp4

--attach は gh pr create、gh pr edit、および gh issue の同等のコマンドでも機能します。コマンドごとに最大50ファイルまで繰り返し可能で、user-attachments CDNにアップロードされるため、GitHubはビデオをインラインでレンダリングします。

知っておくべき4つのこと:

  • 代替テキストは画像のみです。 './shot.png#エラー状態' は画像の代替テキストを設定します。ビデオに同じ構文を使用すると、cannot set alt text on video として拒否されます。ビデオはパスのみで添付します。
  • ローカルパスをすでに参照している本文は書き換えられます。 ![alt](./demo.mp4) を希望の場所に書き込むと、gh がアップロードされたURLに置き換えます。それ以外の場合は、添付ファイルが本文の最後に追加されます。
  • 本文フラグなしの gh pr edit --attach は既存の本文を保持し、それに追加するため、後からPRの説明にデモを追加できます。
  • 依存する前にバージョンを確認してください。 2.99.0より古い gh には --attach がなく、APIを介してCDNに到達する他の方法もありません。その場合は、ユーザーが自分でPRにファイルをドラッグできるようにファイルパスを伝えることにフォールバックします。

関連スキル