1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.jsで動画から再生ボタンを入れたサムネイル画像を作成する

Last updated at Posted at 2025-06-06

ffmpegで動画からサムネイル画像を作成してみます。
これをfluent-ffmpegというnpmライブラリを使うことでNode.jsから操作できます。

今回は動画からサムネイル画像を作成します。

CleanShot 2025-06-06 at 23.52.07.png

↓↓↓↓ こういうどこかのフレームを切り出したpng画像を出力

CleanShot 2025-06-06 at 23.51.57.png

ffmpegのインストールなど

Macを使ってますが事前にインストールしておきます。

$ brew install ffmpeg

インストール確認

$ which ffmpeg
/opt/homebrew/bin/ffmpeg

ちなみにNode.jsはv24です。

利用する動画

こちらで作った動画からサムネイルを取得します。

動画からフレームを切り出す

  • ライブラリのインストール
$ npm i fluent-ffmpeg
  • コード
import ffmpeg from 'fluent-ffmpeg';
import { basename, extname, dirname, join } from 'node:path';

async function createThumbnail(videoPath: string): Promise<string> {
  const videoName = basename(videoPath, extname(videoPath));
  const thumbnailPath = join(dirname(videoPath), `${videoName}_thumbnail.png`);
  
  console.log(`🎬 ${videoName} からサムネイル生成中...`);
  
  return new Promise((resolve, reject) => {
    ffmpeg(videoPath)
      .screenshots({
        timestamps: [1], //[1] => 1秒目 ['10%'] => 10%の長さの箇所 [1,5,10] => 1,5,10秒で複数画像  
        filename: basename(thumbnailPath),
        folder: dirname(thumbnailPath),
        size: '1280x720'
      })
      .on('end', () => {
        console.log(`✅ 完了: ${thumbnailPath}`);
        resolve(thumbnailPath);
      })
      .on('error', reject);
  });
}

// 実行
const videoPath = process.argv[2];
if (!videoPath) {
  console.log('使用方法: node simple-thumbnail.ts <動画パス>');
  process.exit(1);
}

createThumbnail(videoPath).catch(console.error);

.screenshotsのtimestampsの値を[1]にしてますが、これは1秒目のフレームを画像化する指定です。
[1,5,10]などにすると1秒目、5秒目、10秒目で3枚のスクリーンショットが抽出できます。

      .screenshots({
        timestamps: [1,5,10],
        filename: basename(thumbnailPath),
        folder: dirname(thumbnailPath),
        size: '1280x720'
      })
  • 使ってみる
$ node simple-thumbnail.ts ./tmp/IMG_0588.MOV

CleanShot 2025-06-06 at 23.56.39.png

こんな感じでpng画像が出力されます。

再生ボタンを入れた画像を作る

ちゃんと調べてないですが、drawtextのオプションでテキストを入れることができる模様です。

折角なので動画のサムネイルということで再生ボタンを入れた画像を作ってみます。

CleanShot 2025-06-07 at 01.00.36.png

import ffmpeg from 'fluent-ffmpeg';
import { basename, extname, dirname, join } from 'node:path';
import { unlink } from 'node:fs/promises';

async function createThumbnailWithPlayButton(videoPath: string): Promise<string> {
  const videoName = basename(videoPath, extname(videoPath));
  const baseThumbnailPath = join(dirname(videoPath), `${videoName}_base.png`);
  const thumbnailPath = join(dirname(videoPath), `${videoName}_thumbnail.png`);
  
  console.log(`🎬 ${videoName} から再生ボタン付きサムネイル生成中...`);
  
  return new Promise((resolve, reject) => {
    // 1. 基本サムネイル生成
    ffmpeg(videoPath)
      .screenshots({
        timestamps: [1], // 1秒目
        filename: basename(baseThumbnailPath),
        folder: dirname(baseThumbnailPath),
        size: '1280x720'
      })
      .on('end', () => {
        // 2. 再生ボタンを追加
        ffmpeg(baseThumbnailPath)
          .outputOptions([
            '-vf',
            'drawtext=text=▶️:fontsize=150:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:borderw=5:bordercolor=black@0.9'
          ])
          .output(thumbnailPath)
          .on('end', async () => {
            console.log(`✅ 完了: ${thumbnailPath}`);
            await unlink(baseThumbnailPath); // 中間ファイル削除
            resolve(thumbnailPath);
          })
          .on('error', () => {
            // 再生ボタン追加失敗時は基本サムネイルを使用
            console.log(`✅ 完了(再生ボタンなし): ${baseThumbnailPath}`);
            resolve(baseThumbnailPath);
          })
          .run();
      })
      .on('error', reject);
  });
}

// 実行
const videoPath = process.argv[2];
if (!videoPath) {
  console.log('使用方法: node simple_image.ts <動画パス>');
  process.exit(1);
}

createThumbnailWithPlayButton(videoPath).catch(console.error);

これはべんり

所感など

終わってみると割とサクッと画像切り出しができて便利ですね。

GPTのAPIなどに画像をあげつつ、盛り上がってる箇所を探してほしい選定などもやりたい

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?