Open9

ffmpeg Tips

bellbindbellbind

ffmpegでmovコンテナを再エンコード無しでmp4コンテナに変換

ffmpeg -i src.mov -c:v copy -c:a copy dest.mp4

注意点: -i fileオプションは、video/audioオプションのに置くことが必須。

bellbindbellbind

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)
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
bellbindbellbind

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というのは各フレームの表示時期の値で、四倍速ではそれを四分の一にしている。

bellbindbellbind

ffmpegで音量二倍

ffmpeg -i src.mp4 ... -af "volume=2.0" target.mp4
bellbindbellbind

ffmpegで連結

現在のffmpegでは-f concatのあと、ファイルリストファイルを-i list.txtで渡す方法のみ対応している。Web検索結果で出てくる他の方法(ファイル名を|でつなぐ、など)は現在のffmpegでは無効化されている。

ファイルリストの内容例

list.txt
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
bellbindbellbind

[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コマンドを前後で使うことになるだろうか。

bellbindbellbind

[nodejs] フォルダの動画を連結し、4倍速音量二倍で、YouTube向けエンコーディングしたmp4ファイルを生成するスクリプト

concat.mjs
#!/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ファイルを生成するスクリプト

concat.js
#!/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();
bellbindbellbind

フレーム欠損対策

ビデオカメラの録画では、時折フレームの欠損(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"
bellbindbellbind

明るさ調整

$ 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以上なら明るくなる。