0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ffmpeg で動画ファイルから 5秒ごとに画像を切り出すスクリプト

Posted at

概要・目的

5秒ごとに1スライドがある動画ファイルから画像を切り出したかった。

生成AIでざっくりスクリプトを書いてもらって、一部手直しをしたら使えたので記事にまとめておきます。用途は限定的ですが動作確認済みです。

写真をスライドショー的な動画ファイルにして、これで展開とかも使えそう。

動作確認

  • macOS 14.4
  • ffmpeg
ffmpeg version 7.1 Copyright (c) 2000-2024 the FFmpeg developers
  built with Apple clang version 16.0.0 (clang-1600.0.26.4)
  • bash
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.

スクリプト

#!/bin/bash -xe

# 動画ファイル名
input_video="input.mp4"

# 出力画像のディレクトリ
output_dir="output_images"

# 切り出す間隔 (秒)
interval=5

# 出力画像の形式
format="jpg"

# 出力画像のファイル名フォーマット
filename_format="image_%04d.%s"

# 出力ディレクトリを作成 (存在しない場合)
mkdir -p "$output_dir"

# 動画の長さを取得
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input_video")
# 切り出し回数を計算
count=$(printf "%.0f" $(echo "$duration / $interval" | bc -l))

# 切り出し処理
for ((i=0; i<$count; i++)); do
  filename=$(printf "$filename_format" "$i" "$format")
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 -vf scale=-1:720 "$output_dir/${filename}"
done

解説など

以下の内容も確認済みです。

スクリプトの解説

  1. 変数定義:
    • input_video: 入力動画ファイル名
    • output_dir: 出力画像のディレクトリ
    • interval: 切り出す間隔 (秒)
    • format: 出力画像の形式 (jpg, pngなど)
    • filename_format: 出力画像のファイル名フォーマット (image_%04d.jpgのように連番で保存)
  2. 出力ディレクトリ作成: mkdir -pコマンドで出力ディレクトリを作成します。
  3. 動画の長さ取得: ffprobeコマンドで動画の長さを取得し、duration変数に格納します。interval で割って切り出し回数を計算します。
  4. 切り出し処理:
    • forループで、interval秒ごとに動画から1フレームを切り出します。
    • ファイル名を printf で連番で生成します。
    • ffmpeg
      • -ss: 動画の開始位置を指定します。
      • -frames:v 1: 1フレームだけ出力します。
      • -vf scale=-1:720: 出力画像の高さを720pxにリサイズします。幅は自動調整されます。

スクリプトの実行方法

  1. 上記のスクリプトをテキストエディタで作成し、.sh拡張子で保存します (例: extract_images.sh)。
  2. ターミナルでスクリプトのあるディレクトリに移動します。
  3. 実行権限を与えます: chmod +x extract_images.sh
  4. スクリプトを実行します: ./extract_images.sh

注意点

  • 動画の長さ: 動画の長さが非常に長い場合は、処理時間がかかる可能性があります。
    • 約18分の動画(1920x1080)で200枚の切り出しでしたが1分程度だった。
  • 出力画像のサイズ: -vf scaleオプションで出力画像のサイズを調整できます。
  • 出力形式: format変数を変更することで、出力画像の形式を変更できます。

参考:

おわりに

ffmpeg も bash での制御文も、一から書くととても時間がかかる。
生成AIに依頼することでそれっぽいものができた。
エラーをつぶすだけだったのでかなり時間短縮ができた。

手で修正した箇所

for 部分

## 修正前
# 切り出し処理
for ((i=0; i<=`echo "$duration / $interval" | bc -l`; i++)); do

## 修正後
# 切り出し回数を計算
count=$(printf "%.0f" $(echo "$duration / $interval" | bc -l))
# 切り出し処理
for ((i=0; i<$count; i++)); do

修正前だと計算結果に小数点が出て for のシンタックスエラーになった。
事前に小数点を切り捨てるようにした。

ファイル名

## 修正前
for ...
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 "$output_dir/${filename_format}" -vf scale=-1:720
done

## 修正後
for ...
  filename=$(printf "$filename_format" "$i" "$format")
  ffmpeg -ss "$((i * interval))" -i "$input_video" -frames:v 1 -vf scale=-1:720 "$output_dir/${filename}"
done

ffmpeg の結果ファイル名を連番ファイル名にするべきところが $filename_format だった。

ついでに ffmpeg のオプションの scale の位置がまちがっていた。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?