RSVP速読リーダーをVue 3で作り始めた記録:画像2枚の企画書、最低字数5字の判断、Codexレビュー上限1万行

開発misc-dev

RSVP速読リーダーをVue 3で作り始めた記録:画像2枚の企画書、最低字数5字の判断、Codexレビュー上限1万行

朝7時すぎ、クリップボードに保存した画像2枚を Claude Code に貼り付けた。 どちらも速読表示の画面で、1枚は止めたところを、もう1枚は流しているところを写している。 RSVP リーダーと呼ばれる種類の表示で、文章を小さなかたまりに切り、画面の同じ位置へ次々に出していく。 これを作る企画を立てるところから、この日は始まった。

この時点では、2枚の画像はまだ計画書の外にあった。

画像2枚から計画書へ

svg-diagram スキルを読ませたうえで、計画書を書いてもらった。 全体構成の図を SVG で作り、本文と判断事項5件を書き、Codex のレビューを通してから見せる流れである。 Codex の判定は「承認」で、致命的な指摘はなかった。

判断事項は、計画書の HTML に埋め込んだ回答フォームで選ぶ。 8899番のポートは別のセッションが使っていたので、そこには触れずに8901番で立ち上げてもらった。

ここで、ふと引っかかった。 Vue って、Vue 3 の次に Vue 4 のようなものが出ていなかったか。 npm で確かめてもらうと、Vue 4 はまだ出ていなかった。 あとで作った雛形も、Vue 3.5、Vite 8、TypeScript 6 の組み合わせになった。

せっかくなので、渡した画像2枚は計画書の中に参照画像として入れておいてもらった。 入れた先は「1. 何を作るか」の節で、参照画像1が停止中、参照画像2が再生中の画面である。 参照画像1では、下半分にルビ付きの全文パネルが出ていて、「ある日の」がハイライトされている。

人物辞書に kuromoji は使わない

判断事項の4番目は、登場人物の辞書をどう作るかだった。 自由記述欄には、アプリの中では作らないと書いた。 開発環境で Claude Code や Codex(サブスクリプションの枠内)に本の本文を読ませ、作品ごとに JSON を作らせる。 本文は Turso に置いた蔵書 DB から取ってくる。

形態素解析の kuromoji を入れる案もあった。 ただ、1回の処理にどれくらいかかるかは分からないものの、たぶんサブスクリプションの枠内でできそうだし、LLM に読ませるほうが正確ではないかと考えた。 kuromoji でやった場合の精度と比べてみたい気持ちはある。 とはいえ、それほど精度は高くない気がしている。

そこで、いったん kuromoji は入れないことにした。 代わりに、蔵書 DB から1冊を書き出す開発用スクリプトと、その本の人物辞書を作る手順を、スキルとして計画に加えてもらった。 改訂した計画書も、Codex の再レビューは「承認」だった。

Phase 0 と Phase 1:雛形から青空文庫の変換まで

Phase 0 では、Node と pnpm のバージョンと、Vite の雛形ツールが対話なしで動くかどうかを確かめてもらった。 雛形からデモ用の部品を除いて新しいリポジトリへ移し、Vitest と BudouX を足した。 テストと型検査込みのビルドが通り、dev サーバーの画面にもコンソールエラーは出なかった。 GitHub の非公開リポジトリに push し、公開範囲が PRIVATE になっていることも確かめてもらった。

Phase 1 の素材は、青空文庫の『蜘蛛の糸』である。 最初に、「2,868字」が見出し(一、二、三)を含んだ数なのかを実測させ、字数の数え方を決めた。 続いて青空文庫テキストの変換を書いてもらった。 ルビは、明示する形と、直前の漢字にかかる省略形の両方を扱う。 外字、見出し、冒頭の記号説明、末尾の底本情報も処理の対象にした。

その先は、人名の位置探し、BudouX による分割、かたまりの組み立て、表示時間の計算と続く。 テストは38件から48件まで増えた。 計画書の完了条件5つをすべてテストで確かめてから、c23679a をコミットして push した。

Codex レビューの上限を1万行に上げる

ここで作業を止めて、Codex コミットレビューの設定を変えた。 差分の行数の上限が7,000行になっていたが、この値にはあまり意味がないと感じたので、1万行に上げてもらった。 すると Claude Code から、制限時間も今の比率(7,000行で420秒)に合わせて600秒にしてはどうかという提案があり、それにも乗った。

ゲートのスクリプトは、別のセッションのレビューが動いている最中だった。 手順書は実行中のレビューに影響しないので先に直させ、スクリプト本体は別セッションのレビューが終わるのを待ってから書き換えさせた。

ついでに、今回のコミットも念のためレビューに通してもらった。 外字の対応表のコミット(3a1dc14)は、レビューが飛ばされていたものである。 Codex の判定は「指摘事項なし」だった。

Phase 2:一文は短すぎないほうがいいのか

Phase 2 は再生の最小版である。 判断を含む処理(再生時計、残り時間の累積、時刻の表示形式、速度の範囲制限)は純粋関数にしてテストし、Vue の側は画面とタイマーだけにした。

1枚目の表示は参照画像と同じ状態になった。 「ある日の」が出て、下に「1 / 2,868字 残り 約2:22」とある。 速度は1,500字/分である。 再生を始めて約7秒後には「143 / 2,868字 残り 約2:15」になり、残り時間も7秒ぶん減っていた。

ここで一つ疑問が湧いた。 ものによっては、一文がだいぶ短すぎる。 5文字に満たないかたまりがあると、文の意味をとるのがかえって遅くなる気がする。 最低文字数のようなものは設定しないのかと聞いた。

設定はすでにあった。 既定値は、元にした投稿と同じ「3字以上」で、まだ画面には出していなかった(Phase 3 の設定パネルで出す予定だった)。 『蜘蛛の糸』で最低字数を変えたときの違いを、かたまりの数、平均の長さ、5字未満の割合、全体の時間、冒頭の区切りの表にしてもらった。 すると、最低字数を変えても全体の時間は変わらなかった。 これは面白かった。

5字で進めることにした。 もう一つ気になったのは、冒頭の「極楽の蓮池のふちを」である。 ここは1つのかたまりで出てほしい。

原因は、5字未満のかたまりを次へつなぐだけの作りにあった。 読点をかたまりの終わりとして扱うように変え、2文節ずつまとめる処理でも同じ扱いにそろえてもらった。 操作バーに最低字数の選択欄を置き、区切り直しても読んでいる位置が保たれるようにしてもらった。

テストは70件になった。 画面を読み込み直すと、「極楽の蓮池のふちを、」が1つのかたまりで出た。 ヘッダーのキー操作の説明で「↑↓」だけが青い記号で出ていることには、再生の確認中に Claude Code が気づいていた。 Windows の絵文字フォントで描かれているらしい。 一度直させたあとも青っぽく見えたので、拡大して確かめさせた。 狭い画面で文字を自動で縮める処理も足し、390px のスマホ幅はエミュレーションで確かめてもらった。 既定の最小字数を5字にして、6cb1ca4 をコミットして push した。

Phase 3:参照画像と同じ画面になるまで

Phase 3 で作ったのは次の4つである。

  • 停止中の全文パネル(ルビ付き、現在位置のハイライト、クリックでその位置へ移動)
  • 人名に色を付けた表示と、ラベルの行
  • 2段の操作バー
  • Shift+←→ による段落単位の移動

全文パネルのクリックは、3段落目の53か所をすべて押して確かめてもらった。 どれもクリックした文字を含むかたまりへ移り、ずれは0件だった。 テスト91件と型検査が通り、2b5457b をコミットして push した。

朝に貼った2枚の画像は、ここで完了条件として効いてきた。 停止中は参照画像1、再生中は参照画像2と同じ状態になることを画面で確かめて、Phase 3 を閉じた。

Phase 4 以降は明日へ

続きは明日やることにして、Phase 4 からは Google タスクに回した。 その前に、計画書に「9. 進捗と再開のしかた」を追記させ、コミットして push した。 Phase 4〜6 は、翌日(9月28日)が期日の Google タスク3件として登録した。 期日と本文が入っていることも、1件ずつ確かめてもらった。

学びメモ

  • 最低字数を変えても、『蜘蛛の糸』全体の再生時間は変わらなかった。「極楽の蓮池のふちを、」をひとかたまりにできるかどうかは、読点の扱いで決まった
  • 画像2枚を計画書に参照画像として入れておくと、Phase 3 でそのまま完了条件になった
  • 人物辞書は、kuromoji ではなくサブスクリプション内の LLM に本文を読ませて作る方針にした

kuromoji でやった場合との精度の比較は、やってみたいと言ったまま手を付けていない。

#RSVP#速読#Vue#BudouX#kuromoji#Codex#Claude Code