asopi tech
asopi techIndie Developer
AstroのMarkdownコードブロックにVHSのターミナル動画を埋め込む

【2026年8月版】

AstroのMarkdownコードブロックにVHSのターミナル動画を埋め込む

公開日: 2026/08/17
読了時間: 約 10分

ターミナルの操作をブログで説明するとき、コマンドをコードブロックに貼るだけでは、どこに入力して、どんな結果が出たのかが分かりにくいです。

そこで、あそぴテックでは、コマンドの入力と結果を見せられるVHSを導入してみました。VHSで作ったデモを、AstroのMarkdown記事に埋め込みました。この記事では、その取り組みを紹介します。

VHSとは

VHSは、.tapeファイルに書いた台本を仮想ターミナル上で実行し、コマンドの入力と結果を再現したGIF、MP4、WebM、PNGを作るオープンソースのターミナルツールです。入力速度、待ち時間、画面サイズも台本で指定できます。

画面録画と違い、入力速度や待ち時間などを台本で揃えられるため、全く同じ手順を何度でも再現できます。ブログ用のMP4、X用のGIF、結果を示すPNGも同じ台本から作れます。

このページのデモも、同じ方法で生成しました。

VHSの台本から生成したブログ埋め込みデモ

動画を開く

VHSは.txtまたは.asciiOutputに指定すると、最終的なターミナルの内容をテキストファイルにも出力できます。このブログでは、動画エリア右上のボタンから、その実行結果をコピーできるようにしました。

AstroにVHSを埋め込むには?

このブログでは、コードブロックの宣言にvideoを指定し、ブロック内に動画のURLやタイトルなどを書くことで、記事内にターミナルデモを表示できるようにしました。

AstroのMarkdownファイルでは、次のように書きます。

```video
src: /videos/astro-vhs-blog/demo.mp4
```

srcには動画のURLを指定します。詳しい属性の指定方法は、後の「動画表示の属性」で説明します。

Astroの設定には、既存のRemarkプラグインと並べて登録しました。

// astro.config.mjs
import { remarkTerminalVideo } from './src/lib/remark-terminal-video';

export default defineConfig({
  markdown: {
    remarkPlugins: [
      remarkCodeTitles,
      remarkReadingTime,
      remarkTerminalVideo,
    ],
  },
});

記事ごとにAstroコンポーネントをimportしなくて済むようにしました。Markdownでvideoブロックを書くだけで、サイト全体で同じ動画表示を使えます。AstroのMarkdown処理とMarkdownプラグインの考え方は、Astro公式ドキュメントにも整理されています。

本サイトで使用したVHS台本の例

本サイトでは、コマンドの入力、処理中、結果の流れを見せるため、echoを使った台本からターミナルデモを作成しました。

Output public/videos/analyze-project/demo.mp4
Output public/videos/analyze-project/demo.gif
Output public/videos/analyze-project/demo.txt

Require echo
Set Shell "bash"
Set Width 960
Set Height 540
Set FontSize 22
Set Padding 8
Set CursorBlink false
Set Framerate 10
Set TypingSpeed 65ms

Hide
Type "clear"
Enter
Type "echo 'analyzing sample-project...'"
Enter
Sleep 1s
Type "echo 'files: 42  dependencies: 8  status: ready'"
Enter
Sleep 2s
Screenshot public/videos/analyze-project/demo.png
Show

この台本では、Set WidthSet Heightでターミナルのサイズを指定し、TypeEnterSleepで入力と処理中の時間を表現しています。MP4、GIF、PNGはこのサイズで生成し、記事では縦横比を保って表示します。スマートフォンでは画面幅に合わせて縮小されます。

本サイトでは、何度実行しても同じデモになるよう、入力データを固定し、本番環境で繰り返し実行できないコマンドは--demoモードで再現しています。

Outputで動画、GIF、テキストを、Screenshotでポスター画像を生成しています。

動画ブロックの表示方法と属性

このブログでは、Markdownの言語名にvideoと書いたコードブロックを、ターミナルデモとして表示します。ブロック内のkey: value形式の設定を読み取り、formatに応じて動画プレーヤー、GIF、PNGを表示します。titlecaptionを添え、textを指定した場合は実行結果をコピーできるボタンを表示します。通常のコードブロックや他のMarkdownは、そのまま表示します。

メディアのURLはサイト内のパスまたはHTTPSに限定しています。javascript:data:、制御文字、HTML属性を壊す引用符は受け付けず、記事の値は表示時にエスケープします。これにより、記事に書いた設定が意図しないHTMLとして解釈されることを防ぎます。

次のように属性をまとめて指定できます。

```video
format: video
src: /videos/astro-vhs-blog/demo.mp4
webm: /videos/astro-vhs-blog/demo.webm
poster: /videos/astro-vhs-blog/demo.png
text: /videos/astro-vhs-blog/demo.txt
title: プロジェクト解析のターミナルデモ
caption: コマンドを実行して解析結果を表示する
autoplay: true
controls: true
loop: true
muted: true
playsinline: true
preload: metadata
fallback: /videos/astro-vhs-blog/demo.mp4
```
  • src: 表示する動画や画像を指定します。必須です
  • webm: WebM形式の動画を指定します
  • poster: 動画の再生前に表示する画像を指定します
  • text: 実行結果をコピーするためのテキストファイルを指定します
  • title: デモのタイトルを指定します
  • caption: 動画や画像の説明を指定します
  • autoplay: ページを開いたときに再生します
  • controls: 再生、一時停止、音量などの操作を表示します
  • loop: 再生を繰り返します
  • muted: 音声を消して再生します
  • playsinline: スマートフォンでもページ内で再生します
  • preload: 動画の読み込み方法を指定します。metadataなら、ページを開いた時点では動画全体を読み込みません
  • fallback: 動画を再生できない場合に表示する代替コンテンツを指定します

controlsloopmutedplaysinlineは既定で有効にし、autoplayは指定した場合だけ有効にしています。

formatで表示形式を切り替えます。

format表示向いている用途
video動画プレーヤー操作UI、ポスター、MP4/WebM、長めのデモ
gif繰り返し再生する画像X向けと同じ短い無音ループ、軽い確認用
png静止画結果の保存、動画のポスター

GIFとPNGでは、altで画像の内容を説明できます。たとえば、次のように指定します。

```video
format: gif
src: /videos/astro-vhs-blog/demo.gif
text: /videos/astro-vhs-blog/demo.txt
alt: VHSで生成したターミナルアニメーション
caption: GIFは画像として自動的にループします
```

実際の表示例です。

VHSで生成したターミナルアニメーション
GIFは画像として自動的にループします
```video
format: png
src: /videos/astro-vhs-blog/demo.png
text: /videos/astro-vhs-blog/demo.txt
alt: VHSで生成したターミナルの静止画
caption: PNGはポスターや静止画として表示します
```

PNGの表示例です。

VHSで生成したターミナルの静止画
PNGはポスターや静止画として表示します

CSSは、動画や画像が記事の幅に合わせて表示され、スマートフォンでも横幅に収まるように調整しています。

VHS生成物の管理例

本サイトでの保存単位の一例は次の通りです。

tapes/
└── <デモ名>.tape

public/videos/<記事スラッグ>/
├── demo.mp4
├── demo.gif
└── demo.png

動画ファイルだけを更新すると、どの手順や設定から作った動画なのか分からなくなります。そこで、本サイトでは台本を残し、同じデモから作ったファイルと一緒に管理しています。

まとめ

VHSの台本からMP4・GIF・PNGを生成し、Astroのvideoコードブロックで記事に表示できるようにしました。formatで表示形式を切り替え、動画エリアのボタンから実行結果をコピーできるようにしました。

今後ともあそぴテックサイトをよろしくお願いします。

参考