ffmpeg Tips

ffmpegでmovコンテナを再エンコード無しでmp4コンテナに変換
ffmpeg -i src.mov -c:v copy -c:a copy dest.mp4
注意点: -i file
オプションは、video/audioオプションの前に置くことが必須。

ffmpegでYouTube用エンコード
- ソース動画: 1080p
- ターゲット
- コンテナ: mp4 ファストスタート(
-movflags +faststart
) - 動画: H264 ハイプロファイル(
-c:v libx264 -profile:v high
) FPS=30(-r 30
) BPS=10M(-b:v 10M
) Bフレーム=2(-bf 2
) GOP=FPSの半分(-g 15
) CABAC有効(-coder 1
) インタレース除去(-vf yadif=0:-1:1
) - 音声: AAC-LC(
-c:a aac -profile:a aac_low
)ステレオ(-ac 2
) サンプリングレート=96k hz(-ar 96000
) BPS=384k(-b:a 384k
)
- コンテナ: mp4 ファストスタート(
ffmpeg -i src.mov -movflags +faststart \
-c:v libx264 -profile:v high -r 30 -b:v 10M -bf 2 -g 15 -coder 1 -vf "yadif=0:-1:1" \
-c:a aac -profile:a aac_low -ac 2 -ar 96000 -b:a 384k \
target.mp4

ffmpegで4倍速
ffmpeg -i src.mp4 ... -vf "setpts=PTS/4.0" ... -af "atempo=2.0,atempo=2.0" target.mp4
-vf
はビデオフィルタで-af
はオーディオフィルタ、カンマで複数のフィルタを連結できる。
atempoは倍速までしか対応していないので、オーディオ4倍速は二倍速を二回掛ける必要がある。
ptsというのは各フレームの表示時期の値で、四倍速ではそれを四分の一にしている。

ffmpegで音量二倍
ffmpeg -i src.mp4 ... -af "volume=2.0" target.mp4

ffmpegで連結
現在のffmpegでは-f concat
のあと、ファイルリストファイルを-i list.txt
で渡す方法のみ対応している。Web検索結果で出てくる他の方法(ファイル名を|
でつなぐ、など)は現在のffmpegでは無効化されている。
ファイルリストの内容例
file file:/Users/bellbind/Movies/001.mp4
file file:/Users/bellbind/Movies/002.mp4
file file:/Users/bellbind/Movies/003.mp4
コマンド
ffmpeg -safe 0 -f concat -i list.txt ... target.mp4
注意: リスト中のファイル名がフルパスの場合、-safe 0
を付ける必要がある。
ファイルリストはstdin経由で流すこともできる。
cat list.txt | ffmpeg -safe 0 -f concat -i /dev/stdin ... target.mp4
プラットフォーム非依存にするには/dev/stdin
ではなく、pipe:0
を使うのが良いようだ(要-protocol_whitelist
に追加)。
cat list.txt | ffmpeg -protocol_whitelist "file,pipe,crypto,data" -safe 0 -f concat -i pipe:0 ... target.mp4

[mac] caffeinateコマンドでffmpegエンコード中のスリープ防止
ffmpegのエンコードは時間がかかるので、ターミナル上で実行して放置すると、システムスリープしてしまい、より時間がかかってしまう。
そこでmacに搭載されているcaffeinate
コマンドを使うことで、コマンド実行中にスリープさせないようにすることができる。
caffeinate -i -m -d ffmpeg -i src.mp4 ... target.mp4
caffeinate
コマンドは、引数のコマンド列を実行し、その実行が終わるまで、スリープするのを防止する。
-
-i
: システムスリープを防ぐ -
-d
: 画面スリープを防ぐ -
-m
: ディスクスリープを防ぐ
Ubuntuではcaffeine
パッケージにcaffeinate
コマンドが搭載されている(オプションはなしでコマンド列を渡して実行)。
Windowsではpowercfgコマンドを前後で使うことになるだろうか。

[nodejs] フォルダの動画を連結し、4倍速音量二倍で、YouTube向けエンコーディングしたmp4ファイルを生成するスクリプト
#!/usr/bin/env node
// usage: node concat.mjs /Volumes/UNTITLED/Normal/F/ result.mp4
import * as cp from "node:child_process";
import * as fs from "node:fs/promises";
import * as path from "node:path";
import * as process from "node:process";
import * as stream from "node:stream";
import * as url from "node:url";
//console.log(process.argv);
const sources = process.argv.at(-2);
const output = process.argv.at(-1);
const inputs = (await fs.readdir(sources)).sort();
const list = inputs.map(f => `file ${url.pathToFileURL(path.join(sources, f))}\n`).join("");
const ffmpeg = process.platform === "darwin" ? `caffeinate -i -m -d ffmpeg` : "ffmpeg";
const command = `${ffmpeg} -protocol_whitelist "file,data,pipe,crypto" -safe 0 -f concat -i pipe:0 -movflags +faststart \
-c:v libx264 -profile:v high -b:v 10M -bf 2 -r 30 -g 15 -coder 1 -vf "yadif=0:-1:1,fps=30,setpts=PTS/4.0" \
-c:a aac -profile:a aac_low -b:a 384k -ac 2 -ar 96000 -af "atempo=2.0,atempo=2.0,volume=2.0" \
${output}`
console.log(command);
cp.execSync(command, {input: list, stdio: [null, 1, 2]});
[deno] フォルダの動画を連結し、4倍速音量二倍で、YouTube向けエンコーディングしたmp4ファイルを生成するスクリプト
#!/usr/bin/env -S deno run --allow-read --allow-run
// usage: deno run --allow-read --allow-run concat.js /Volumes/UNTITLED/Normal/F/ result.mp4
import * as path from "https://deno.land/std/path/mod.ts";
const sources = Deno.args.at(-2);
const output = Deno.args.at(-1);
const inputs = [];
for await (const {name} of Deno.readDir(sources)) inputs.push(name);
inputs.sort();
const list = inputs.map(f => `file ${path.toFileUrl(path.join(sources, f))}\n`).join("");
const ffmpeg = Deno.build.os === "darwin" ? [`caffeinate`, `-imd`, `ffmpeg`] : ["ffmpeg"];
const options = [
`-protocol_whitelist`, `file,data,pipe,crypto`, `-safe`, `0`, `-f`, `concat`, `-i`, `pipe:0`,
`-movflags`, `+faststart`,
`-c:v`, `libx264`, `-profile:v`, `high`, `-b:v`, `10M`, `-bf`, `2`, `-r`, `30`, `-g`, `15`, `-coder`, `1`, `-vf`, `yadif=0:-1:1,fps=30,setpts=PTS/4.0`,
`-c:a`, `aac`, `-profile:a`, `aac_low`, `-b:a`, `384k`, `-ac`, `2`, `-ar`, `96000`, `-af`, `atempo=2.0,atempo=2.0,volume=2.0`,
];
const cmd = [...ffmpeg, ...options, output];
console.log(cmd.join(" "));
const proc = Deno.run({cmd, stdin: "piped"});
const tes = new TextEncoderStream();
tes.readable.pipeTo(proc.stdin.writable);
const writer = tes.writable.getWriter();
await writer.write(list);
await writer.close();
await proc.status();

フレーム欠損対策
ビデオカメラの録画では、時折フレームの欠損(missing picture)が起こるが、ffmpegのデフォルトでは欠損部分がなかったのもとして連結されるため、欠損したぶん、録画時間より映像時間が短くなってしまう。
このため、時間のほうを合わせる場合、ビデオフィルタ(-vf
)でフレーム補間の指定する必要がある。
ffmpegのフレーム補間機能は3タイプ存在するので、どれかを指定する。
-
fps
: 近接フレームのコピー -
framerate
: 前後フレームの混合(インタレース画像には不適) -
minterpolate
: モーション補完
オプションはいくつかあるが、時間で合わせるにはソース動画のFPS値を指定する
- FPS30の場合:
fps=30
- FPS29.97の場合:
fps=30000/1001
倍速させる場合は、倍速フィルタの前に補完フィルタを置く。
-vf "fps=30,setpts=PTS/4.0"

明るさ調整
$ ffmpeg -i src.mp4 -vf eq=brightness=0.075 dest.mp4
0.1でかなり、0.05くらいでもだいぶ明るくなる(0.075から始めるくらいでいいかも)。
明るくするのは+(brightness=0.05
)、暗くするのはマイナス(brightness=-0.05
)。
また、ガンマ値によっても明るくできる。ただしbrightnessより処理時間がかかる。
$ ffmpeg -i src.mp4 -vf eq=gamma=1.4 dest.mp4
1未満なら暗く、1以上なら明るくなる。