ウォークスルー動画 は何をしますか?
「この機能を説明して」という依頼を、短いMP4動画に変換します。実アプリの画面、音声による説明、字幕、人間のように動くカーソル、そして説明中の要素を囲むリングが含まれます。ユーザーが指示を出し、レビューします。それ以外はすべてこちらの作業です。
この作業には、他のどの工程よりも重要なレビューゲートが1つあります。録画の前に、ユーザーがナレーションを承認することです。 文言の変更はスクリプトでは数秒、動画では数分のコストです。間違った主張は、紙の上で訂正する方がはるかに低コストです。
必要なもの
- アプリのソースコード、および開いてサインインできるインスタンス(ローカルまたは開発/ステージング環境)。本番環境では決して録画しないでください:実際のボタンをクリックしてしまいます。
- アプリのプロジェクト内のPlaywright(
node_modules/playwrightまたは@playwright/test)。E2Eテストがあるプロジェクトのほとんどはすでにインストールされています。ない場合:npm i -D playwright && npx playwright install chromium。 - PATHに
ffmpegとpython3が通っていること。 - 最終的な音声用のテキスト読み上げキー(Murf または ElevenLabs)。キーがない場合、
--provider sayでmacOSの音声を使用します。これは下書きとしては問題ありません。references/voices.mdを参照してください。
これらの条件を最初に確認し、不足しているものがあれば明確に伝えてください。ユーザーにAPIキーをチャットに貼り付けるよう依頼しないでください。代わりに、環境変数またはgitで無視されるファイルに設定し、その場所を教えてもらってください。
ワークフロー
1. 概要を聞く
4つの情報が必要です。リクエストにすでに含まれていないものだけを質問してください。
- 目標と対象者。 「新しい権限ページについてCTOと認識を合わせる」ための動画と、「新しいメンバーにアプリの公開方法を教える」ための動画は異なります。対象者が、長さ、語彙、説明の度合いを決定します。
- フロー。 何を、どの順序で表示するか。ユーザーがフローを指定した場合は、それを改善し、変更内容とその理由を説明してください。より良い順序、不足しているステップ、価値のないステップなど。ユーザーは、リストの書き起こしではなく、動画を求めています。
- 長さ。 デフォルトは60〜120秒、トピックは1つです。フローにそれ以上必要な場合は、2本の動画を提案してください。
- 音声。 プロバイダと音声(好みがある場合)。それ以外の場合はデフォルトを使用します。
2. 何も書く前に、実際のアプリでフローを実行する
アプリを起動し、デモアカウントでサインインして、フローの各ステップをPlaywrightまたはブラウザで自分で実行してください。ナレーションが主張する各項目が真実であることを確認しています。
ここに、このスキルの価値の大部分があります。機能はしばしば記憶や仕様書から説明されますが、アプリは少し異なる動作をすることがあります。アプリがユーザーの言う通りに動作しない場合は、観察した結果を伝えて停止してください。それをごまかすナレーションを書いたり、静かにステップを削除したりしないでください。
その際、ボタンやメニューの正確なラベルをメモしてください。ナレーションは画面上の言葉を使用する必要があります。
3. デモデータを準備する
空っぽまたは不完全なアカウントでのウォークスルーは、バグレポートのように見えます。ストーリーに必要なものを作成します:組織、異なるロールを持つ数人のユーザー、信頼できる名前のアイテム。架空の名前(Acme、Northwind、example.com)のみを使用してください。これらの動画は転送されます。
作成または変更したすべてのもののリストを保持してください。ステップ9で元に戻します。
4. ナレーションを書き、レビューのために停止する
これをテーブルとして書き、動画の出力先の隣に <nn>-<slug>.script.md として保存します。
| # | 画面 | ナレーション | ~秒 |
|---|---|---|---|
| 1 | タスクリスト(静止)。リストにリング。 | こちらがチームのタスクリストです。/ チームメンバー全員が同じタスクを見ることができます。 | 5 |
| 2 | カーソルを **タスクを追加** に移動、フォームが開く。名前を入力し、**タスクを保存** をクリック。 | 追加するには、「タスクを追加」を選択し、/ 名前を付けて、/ 保存します。 | 7 |
/ マークは、シーンのナレーションを字幕行に分割します。書き始める前に references/narrative.md を読んでください:ペース、行の長さ、Before/Afterカード、およびこれらの動画をわかりにくくする間違いについて説明しています。
テーブルをユーザーに表示し、待機します。予想される合計時間を伝えてください。フローを変更した場合は、ここでその旨を伝えてください。ユーザーが承認した場合のみ続行します。変更を求められた場合は、修正したテーブルを再度送信してください。
5. 音声を生成する
承認されたナレーションを scenes.json に書き込みます。1行につき1エントリ、/ マークで行を分割します。
[{ "id": "02", "lines": ["追加するには、「タスクを追加」を選択し、", "名前を付けて、", "保存します。"] }]
python3 scripts/tts.py scenes.json --audio-dir work/audio --provider murf
これにより、シーンごとに1つのクリップと durations.json が書き込まれます。音声は意図的に録画の前に作成されます。各シーンは、そのクリップの長さの間画面に保持されるため、最初にクリップの長さが存在している必要があります。再実行すると、テキストが変更されたシーンのみが再生成されます。
6. 録画スクリプトを作成し、ドライランを実行する
example/record.cjs をコピーし、そのシーンをこのフロー用に書き換えます。scripts/walkthrough.cjs は次のヘルパーを提供します。
| ヘルパー | 用途 |
|---|---|
scene(id, async () => {...}) | ナレーション付きの1シーン。字幕を表示し、音声が終了するまで保持します。 |
clickAt(locator) | カーソルを要素に移動し、押下を表示し、クリックします。locator.click() ではなくこれを使用してください。そうしないと、目に見える原因なしに動作が発生します。 |
moveTo(locator) | クリックせずに何かを指し示します。 |
typeInto(locator, text) | フィールドをクリックし、読みやすい速度で入力します。 |
ring(locator) / ring(null) | 音声が説明しているものをハイライトし、話題が変わったら削除します。 |
step('2/4 ステップ · 保存') | 左下のラベルで、視聴者に現在位置を知らせます。 |
card({ title, subtitle }) | フルスクリーンのタイトルカード。終了シーン用。 |
card({ before, after }) | Before/After比較。card(null) で非表示。 |
login: async (page) => {...} | record() のオプション。カメラに映らないうちにサインインし、動画がストーリーの開始地点から始まるようにします。 |
CSSよりもロールとラベルのロケーター(getByRole、getByLabel)を優先してください。これらのロケーターはスタイル変更に強く、ナレーションで使用する名前と同じです。データが環境によって異なる可能性がある場合は、実行時に画面上の名前を読み取ってください。
まず dry で実行します。
node record.cjs <app-repo> work/rec work/audio/durations.json dry
ドライランでは何も録画されず、音声の待機もしないため、間違ったセレクターはフルテイクではなく数秒のコストで済みます。すべてのシーンが実行されるまで修正します。
7. 録画とアセンブル
node record.cjs <app-repo> work/rec work/audio/durations.json
python3 scripts/mux.py --rec work/rec --audio-dir work/audio --output walkthrough-videos/<nn>-<slug>.mp4
レコーダーは、各シーンのクリップ長と、そのアクションにかかった時間を表示します。音声が終了した後に数秒の無音がフラグされたシーンは、説明に対してアクションが多すぎます。アクションをトリミングするか、ナレーションに説明を追加してください。
mux.py はMP4、対応する.srt、および <name>.sheet.jpg を書き込みます。
8. ユーザーより先に自分で確認する
コンタクトシート(各シーンの1フレーム)を開きます。リングが間違った要素にあったり、欠けていたりしないか、字幕が説明中の要素を覆っていないか、シーンが間違った画面でないか、DevToolsのバッジやエラートーストが写り込んでいないか、実際の個人データが映っていないかを確認します。シートではサイズが小さすぎて確認できない場合は、ffmpegで個々のフレームを取得してください。
その後、次の情報とともに動画を引き渡します:長さ、承認されたナレーションから変更があった場合はその内容、確認できなかった事項。
ユーザーが変更を希望する場合は、まずナレーションに戻ります。 テーブルを修正し、表示し、承認を得てから、変更された部分のみを再生成します。ほとんどのフィードバック(「速すぎる」「何が変わったかわからなくなった」「フィルターについても言及して」)はスクリプトに対するものであり、録画だけで修正すると、スクリプトと一致しなくなった動画が生成されます。
9. 元に戻す
ステップ3のリストと、録画自体がクリックしたもの(切り替えた設定、作成または削除されたアイテム、デモアカウントの状態)を使用して、テイクが変更したものを元に戻します。その後、何が復元され、何を意図的に残したか(例えば、次の動画用に残したシードデータ)をユーザーに伝えます。元に戻せないものがあれば、その旨を伝えてください。
ファイル
納品物はユーザーが見つけられる1つの場所にまとめます。デフォルトではプロジェクト内の walkthrough-videos/ です。
walkthrough-videos/
03-add-a-task.mp4
03-add-a-task.srt
03-add-a-task.script.md
作業ファイル(scenes.json、音声、生の録画、録画スクリプト)は、リポジトリの外またはgitで無視されるフォルダに保持してください。これらは大容量であり、録画スクリプトはアプリのライフサイクルの一瞬のセレクターを保持しています。スクリプトと.srtは保存する価値があります。これらにより、次回の改訂は小さな編集で済みます。
うまくいかないこと
- ネイティブコントロールが録画されない。 ネイティブの
<select>ドロップダウン、ファイルピッカー、ブラウザダイアログは、ブラウザがページの外に描画します。moveToでコントロールを指し示し、selectOption/setInputFilesで値を設定し、ナレーションで選択された内容を説明します。 - ナビゲーション後にオーバーレイが消える。 ページが読み込まれるたびに再作成され、現在のステップと字幕が復元されます。ページが
document.bodyを完全に置き換える場合は、それが落ち着いた後に再度step()を呼び出します。 - シーンがページの準備ができる前に開始される。 シーンの対象が準備できるのを待ってから(
await locator.waitFor())、scene()を呼び出します。scene()の中ではなく外で待機することで、読み込み時間がナレーションで埋められるのを防ぎます。 - 最初の数秒が空白ページになる。
mux.pyは最初のシーンの前をすべてトリミングします。scene('01')の前にナビゲーションと待機を行います。 - カメラにサインインが映り込む。
loginオプションを使用します。誰もパスワードフィールドを見る必要はなく、共有される動画に認証情報が表示されてはなりません。