スクショ1枚からSynthesia風ピアノロールWebアプリを作ってもらった日
きっかけは雑な依頼だった。YouTubeでよく見る、暗い背景に音符バーが降ってきて鍵盤に届くと光るあの動画のスクリーンショットを1枚貼り付けて、「ピアノアプリってちょっと作ってもらいたいんですけど、できますかね」とだけ聞いた。
返ってきた答えは「できますよ」。画像を見ただけで「いわゆるSynthesia風のピアノビジュアライザーですね。Web Audio APIで音を合成すれば外部音源なしで作れます」と構成まで言い当ててきた。仕様書はゼロ。画像1枚と一言だけでプロジェクトが始まった。
できあがったもの
/piano-roll として公開済み。
- 音符バーが画面上部から降ってきて、鍵盤の上端に届いた瞬間に音が鳴り、鍵盤が光る
- 88鍵すべてをCanvasで描画。青が右手、金色が左手
- 音はWeb Audio APIでリアルタイム合成。音源ファイルは1つも置いていない
- バーに運指番号(1=親指〜5=小指)を表示できるトグル付き
- 内蔵曲は「エリーゼのために(主部・約1分)」「カノン」「きらきら星」の3曲
- テンポ(50〜150%)・音量・シークバーあり
実装は3ファイル構成にしてもらった。鍵盤レイアウト計算や時間変換は純粋関数として app/utils/pianoRoll.ts に切り出し、曲データは app/data/piano-roll/songs.ts、Canvas描画とWeb Audioの副作用は app/pages/piano-roll.vue に集約。この分離のおかげで、まず31本のユニットテストが一発で通った。
試行錯誤1: 再生時計がほぼ止まっていた
ブラウザでの動作確認に入ったところで、最初のつまずきが出た。再生ボタンを押しても、再生位置がほとんど進まない。
調べてもらった経過がログに残っている。
- 「時間の進み方が想定より速い可能性があります。正確に計測します」
- 「再生位置がほぼ進んでいません。AudioContextの状態を直接確認します」
- 「新しいAudioContextは正常に動くのに、ページ側の時計がほぼ止まっています。もう一度詳しく観察します」
新しく作ったAudioContextは正常に時を刻むのに、ページが持っている時計だけ止まっている——という切り分けを、ブラウザのコンソールを直接叩いて進めてくれた。私がやったのは画面を眺めていることだけで、計測も切り分けも全部任せた。
試行錯誤2: devサーバーが古いコードを配信し続ける
運指番号の描画とトグルを追加してもらった後、今度は「追加したはずの要素が画面に見つからない」問題が出た。これも切り分けの過程が面白かった。
- 「devサーバーが古いコードを配信しています。サーバー側の状態を確認します」
- 「Viteは新コードを配信しています。比較のため他ページのSSR出力を確認します」
- 「SSRボディは描画されていました。新要素が含まれるか正確に確認します」
コードが悪いのか、ビルドが悪いのか、配信が悪いのかを一段ずつ潰していき、最終的にはdevサーバーの再起動で新バージョン(曲長0:59・指番号トグルあり)が反映された。待ち時間には並行してブログ記事の執筆まで進めていた。
公開前提に切り替える
最初はdev環境限定ページとして作ってもらっていたが、できあがりを見て「これ公開前提でよくて、ピアノのコンテンツも公開前提でいいですよ」と伝えた。devゲート・noindex・「開発環境のみ」表記・記事の unpublished フラグを一通り外してもらう。
ここでも一筋縄ではいかなかった。設定を外したはずなのにnoindexが残り続ける。サーバーを再起動しても消えない。「キャッシュではなく別の仕組みが付けている可能性があります」と他ページとの比較確認に進み、最終的に公開化は完了した。
「不足14件は全部直しましょう」
公開化の検証でテストを回したところ、失敗が出た。ただし中身を確認すると、失敗は全部 jukuwaza-math という私たちが今回まったく触っていないページのOGメタタグ不足。今回の変更とは無関係の、もともと存在していた不備だった。
放置してもピアノロールの公開には影響しない。でもせっかく見つかったので「不足14件は全部直しましょう」と指示した。テストの要求仕様と対象ページの現状を確認したうえで14ページにOGメタタグを追加してもらい、OGテストは全151件パス。全テストスイートも104ファイル・16,801件すべてグリーンになった。
ついでの一言で、関係ないページの積年の不備まで片付いた。
実装解説記事も同じセッションで
devサーバーの再起動を待つ間に、実装の詳細をまとめた解説記事も書いてもらった。
曲データの持ち方(パブリックドメイン曲の簡略版、著作権保護中の曲はコード進行のみ)、88鍵レイアウトの計算、落下バーの座標系、Web Audioによるピアノ音合成、運指番号、OMRやWeb MIDI対応の展望までカバーしている。
最後に「コミットしといてください」とだけ伝えると、ピアノ関連の作業一式を3コミットに分割して入れてくれた。
feat: Synthesia風ピアノロール /piano-roll を追加(88鍵Canvas+Web Audio合成・運指表示)
docs: ピアノロールの実装解説記事を追加(曲データ設計・座標系・音合成・OMR/Web MIDI展望)
ふりかえり
- 入力は画像1枚と「作ってもらいたいんですけど」の一言。そこから機能の特定、技術選定、実装、テスト、ブラウザ検証、記事執筆、コミット分割まで流れた
- 試行錯誤は2回(止まる再生時計、古いコードを配信するdevサーバー)。どちらも「計測する→切り分ける→比較する」の手順をログに残しながら進めてくれたので、私は画面の違和感を伝える係に徹した
- テストの失敗を「自分の変更と無関係」と確認したうえで、それでも直す判断は人間側でできる。「不足14件は全部直しましょう」の一言で16,801件グリーンまで持っていけたのは気持ちがよかった
- 公開/非公開の判断は早めに伝えるべきだった。後からdevゲートを外す作業でnoindexの謎調査が1往復増えた