自分で作ったデモ動画ツールを使ってUI/UXを改善した話 — ズーム3フェーズ設計とイージング関数の体感速度

2026.02.24
Share:

はじめに

「自分が使いたいツールを作る」——個人開発でよく聞く言葉だが、作っただけで終わると本当の問題は見えてこない。

デモ動画作成ツールを89番目の無料ツールとして公開した直後、自分でX投稿用のデモ動画を作り始めた。すると、開発中には気づかなかった3つの違和感が浮かび上がった。ズームの開始が遅い、ズームが終わるときに急に元に戻る、アスペクト比を変えたときに動画の位置を調整できない。

この記事では、ドッグフーディング(自社製品を自分で使うこと)で発見した問題と、その改善プロセスを記録する。特に「イージング関数を変えるだけで体感速度がまるで違う」という発見は、動画編集に限らずあらゆるUIアニメーションに応用できる知見だと思う。ツールの設計判断(Canvas + MediaRecorder + FFmpeg WASMの3層アーキテクチャ)については設計判断の記事で詳しく書いている。

問題1: ズームが「もっさり」する

デモ動画でよく使う演出がズームだ。操作画面の特定の部分を拡大して、注目すべきポイントを強調する。

最初の実装では、ズームの開始タイミングが0.5秒、イージング関数が easeInOutCubic だった。テスト動画では問題なく見えたが、実際にX投稿用の30秒動画を編集していると、ズームの反応が遅く感じた。

ズーム開始タイミング改善: デフォルト0.5s→0.3s、イージングを easeInOutCubic(遅い開始)→ easeOutCubic(高速開始)に変更

Story Logにはこう書いていた。

ズームの設定場所が分かりにくい、ズームの開始が遅い、ズームが終わるときに急に元に戻る。自分が使うツールだからこそ、小さな使い勝手の悪さが気になる。

easeOutCubicが体感速度を変える

この改善で最も印象的だったのは、イージング関数の変更だ。

easeInOutCubic は「ゆっくり始まって、加速して、ゆっくり止まる」カーブ。一般的なUIアニメーションでは自然に見える。しかしズーム演出では、最初の「ゆっくり始まる」部分が「反応が鈍い」という印象を与えていた。

easeOutCubic に変更すると、最初から速く動き始めて徐々に減速する。同じ0.3秒のアニメーションなのに、体感速度がまるで違う。

同じ0.3秒のアニメーションでも、easeInOutCubic(遅→速→遅)より easeOutCubic(速→遅)の方が「即座に反応した」と感じる。ユーザーの体感速度はアニメーション前半のカーブに支配される

開発日記の「学んだこと」セクションに書いたこの一文が、今回のドッグフーディングで得た最大の発見だった。アニメーションの最初の0.1秒——ユーザーが「反応した」と認知する瞬間——のカーブが、全体の印象を支配する。

問題2: ズームが急に解除される

ズームイン後、元の倍率に戻る瞬間が唐突だった。拡大した状態からいきなり全体表示に切り替わる。映像として不自然で、視聴者の目が追いつかない。

ZeronovaZeronova
ズームインした後、元に戻る瞬間が急すぎる。「イン → そのまま維持 → ゆっくりアウト」の3フェーズにしたい。
Claude Code
ZoomKeyframeholdDuration(保持時間)と outDuration(ズームアウト時間)を追加しましょう。ズームインは easeOutCubic で素早く、保持フェーズで拡大状態を維持し、ズームアウトは easeInOutCubic で自然に減速する設計です。既存データとの後方互換は、holdDuration / outDuration がない場合にデフォルト動作(保持なし・即解除)を維持すれば確保できます。
ZeronovaZeronova
後方互換を保ちつつ3フェーズに拡張できるなら、それでいこう。

この改善により、ズーム演出が「イン → 保持 → アウト」のスムーズなトランジションになった。ズームインは easeOutCubic で即座に反応し、保持フェーズで視聴者が拡大部分を認識する時間を確保し、ズームアウトは easeInOutCubic で自然に元に戻る。

映像品質が格段に向上したと実感できた瞬間だった。

問題3: アスペクト比変更時の配置

X投稿用に9:16の縦長動画を作ろうとした。アスペクト比を変更すると、横長の動画素材の上下にレターボックス(黒帯)が表示される。ここまでは想定通りだが、動画が中央に固定されて位置を変えられない。

「上寄せにしてテロップスペースを下に確保したい」——実際に使ってみて初めてこのニーズに気づいた。

ZeronovaZeronova
アスペクト比を変えたときに、動画の位置を上下左右に調整したい。レターボックスの余白をどこに配分するかをユーザーが選べるようにしたい。
Claude Code
9点グリッド(3×3)のセレクターが直感的です。VideoAlignment 型で top-left から bottom-right まで9つのポジションを定義し、hFactor / vFactor(0, 0.5, 1)で余白配分を計算すればシンプルに実装できます。アスペクト比が「自動」の場合はレターボックスが発生しないので、セレクターを非表示にする条件分岐を入れましょう。
ZeronovaZeronova
グリッドUIなら直感的だし、実装もシンプルでいいね。

9点グリッドによる配置制御

この議論を経て、9点グリッドの配置UIを実装した。

VideoAlignment 型を新設(top-left / top / top-right / left / center / right / bottom-left / bottom / bottom-right) VIDEO_ALIGN_OPTIONS 定数で hFactor / vFactor(0, 0.5, 1)を管理

配置の計算は非常にシンプルだ。レターボックスの余白(extraW, extraH)に対して、hFactorvFactor を掛けるだけ。

// レターボックス内の配置計算
const offsetX = extraW * hFactor; // 0=左, 0.5=中央, 1=右
const offsetY = extraH * vFactor; // 0=上, 0.5=中央, 1=下

3x3のグリッドUIをスタイルパネルに追加し、アスペクト比が「自動」以外の場合のみ表示する条件分岐を入れた。自動アスペクト比ではレターボックスが発生しないため、配置選択は不要だ。

バグ発見: MP4エクスポートとアスペクト比の組み合わせ

ドッグフーディング中に、もう1つ重大なバグを発見した。アスペクト比を変更した状態でMP4エクスポートすると、エラーが発生する。

Story Logにはこう記録している。

MP4エクスポートでアスペクト比を変えるとエラーが出る問題があった。最初は環境の問題かと思ったが、自分で「さっきまでMP4でダウンロードできていた」「アスペクト比を変えるとエラーになる」と伝えたことで原因が特定できた。

原因は、非autoアスペクト比でキャンバス解像度が増大し、H.264ハードウェアエンコーダーの上限を超過していたことだった。WebCodecs APIの isConfigSupported() は "supported" を返すが、実際のGPU依存の解像度上限は反映されない。

H.264ハードウェアエンコーダーの隠れた制約: isConfigSupported はコーデックレベルのサポートを返すが、実際の解像度上限はGPU依存

修正は3段階で行った。

  1. MP4専用の解像度キャップ: MAX_H264_DIM = 4096MAX_H264_PIXELS = 4,000,000
  2. 動的H.264レベル選択: ピクセル数に応じてLevel 3.1 / 4.0 / 5.1を自動切替
  3. Baseline Profileフォールバック: エンコード失敗時にHigh→Baselineに切り替え

このバグは、自分がユーザーとして「さっきまでできていた」「アスペクト比を変えるとダメ」という正確な再現手順を伝えられたからこそ、素早く原因特定できた。外部のバグ報告では、ここまで正確な情報が得られないことが多い。

TypeScript型定義とランタイムの乖離

バグ修正の過程で、TypeScriptの型定義とランタイムの乖離にも遭遇した。

VideoEncoder.state の型は "configured" | "unconfigured" と定義されているが、ランタイムでは "closed" という状態も存在する。エンコーダーがエラーでクローズされた後に encoder.encode() を呼ぶと例外が発生するが、型チェックでは "closed" 状態を検出できない。

// TS型定義に "closed" が含まれないため、as string でキャスト
if ((encoder.state as string) === "closed") {
  // エラー後のクローズ状態をハンドリング
}

WebCodecsのような比較的新しいAPIでは、型定義がランタイムの実態に追いついていないことがある。防御的な型キャストが必要な場面だ。

ドッグフーディングの価値

開発者テストでは見つからない問題がある

ユニットテストや手動テストでは「機能が動くか」を確認する。しかし「使っていて気持ちいいか」は、実際のユースケースで使い込まないと分からない。ズームの0.2秒の遅さ、配置の不自由さ——こうした「微妙な違和感」は、テストケースには書けない。

ユーザーとしての正確なフィードバックが修正を加速する

「エラーが出ます」よりも「アスペクト比を16:9から9:16に変えてMP4エクスポートするとエラーになる」の方が、原因特定が格段に速い。自分がユーザーなら、再現手順を正確に伝えられる。

小さな改善の積み重ねが品質を作る

ズームのイージング変更、3フェーズ化、9点グリッド——どれも個別に見れば小さな改善だ。しかし、これらが組み合わさることで「映える動画が直感的に作れる」体験が成立する。

完成したツールで無料ツールやIdeaSpoolのデモ動画が簡単に作れるようになった。使い勝手も直感的で機能も豊富。自分が欲しかったものが形になった実感がある。

Story Logに書いたこの言葉が、ドッグフーディングを経た後の率直な感想だ。機能を作るだけでなく、自分で使い込んで磨くプロセスこそが、ツールの品質を決める。

学んだこと

イージング関数は「最初の0.1秒」で選ぶ

アニメーション全体のカーブではなく、最初の0.1秒で「反応した」と感じられるかどうかが重要。ズームのように即時フィードバックが期待される操作では、easeOutCubic(速→遅)が easeInOutCubic(遅→速→遅)より適している。

APIの「対応」と「実動作」は別物

WebCodecs APIの isConfigSupported() が true を返しても、GPU依存の制約で実際にはエンコードできないケースがある。新しいブラウザAPIを使う際は、防御的なフォールバックを必ず用意すべきだ。

ドッグフーディングは「機能追加」ではなく「体験改善」

使ってみて気づくのは、足りない機能ではなく、既存機能の使い心地の悪さだ。テスト駆動では発見できない「体験の質」を高めるために、開発者自身がユーザーになる時間を意図的に作ることを今後も続けていく。

Zeronova avatar

Zeronovaゼロノバ

Product Manager / AI-Native Builder

Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。

関連プロダクト

ZERONOVA LAB

AIネイティブ実験開発スタジオ