動画を86MB → 約43MBにする場合、一番現実的なのは FFmpeg を使う方法です。
動画業界では「容量を半分にする」という言い方よりも、「ビットレートをどれくらいにするか」という考え方をします。
なぜなら、
容量 ≒ ビットレート × 再生時間
だからです。
例えば2分の動画と20分の動画では、同じ43MBでも必要な画質は全く違います。
一番簡単なLinuxコマンド
ffmpeg -i input.mp4 \
-b:v 2500k \
-b:a 128k \
output.mp4
しかし「2500k」が適切かどうかは動画の長さ次第です。
「半分の容量」を狙う方法
実はFFmpegには目標サイズから逆算する方法があります。
例えば
元
86MB
↓目標
43MB動画時間を取得して
目標ビットレート
=
(43MB × 8)
÷ 秒数で計算します。
業界でも配信用の自動エンコードではこの計算をよく行います。
Python3スクリプト例
#!/usr/bin/env python3
import subprocess
import json
import os
import sys
input_file = sys.argv[1]
# 元容量
original_size = os.path.getsize(input_file)
# 半分を目標
target_size = original_size // 2
# 動画長取得
cmd = [
"ffprobe",
"-v", "quiet",
"-print_format", "json",
"-show_format",
input_file
]
info = json.loads(subprocess.check_output(cmd))
duration = float(info["format"]["duration"])
# ビットレート計算(bit/s)
target_bitrate = int(target_size * 8 / duration)
# 音声128kbps分を引く
video_bitrate = target_bitrate - 128000
output = "diet_" + input_file
subprocess.run([
"ffmpeg",
"-i", input_file,
"-b:v", str(video_bitrate),
"-b:a", "128k",
output
])
print("done:", output)
実行
python3 diet.py movie.mp4
もっと業界っぽい方法
実はプロは
-b:vをあまり使いません。
代わりに
-crfを使います。
例
ffmpeg -i input.mp4 \
-c:v libx264 \
-crf 26 \
output.mp4
CRFとは
品質を一定に保つモード
です。
CRFの目安
YouTubeへアップロードする動画も、CRFを使ってエンコードされることが多いです。
実は「半分」は意外と難しい
同じ86MBでも
- アニメ
- ゲーム実況
- 花火大会
- スポーツ
では圧縮率が全然違います。
例えば
静止画ばかりなら
86MB
↓
20MBでも十分綺麗です。
逆に水しぶきや紙吹雪のような映像では
86MB
↓
70MBでもノイズが目立つことがあります。
エンコーダはフレームごとの差分を記録するため、動きが激しい映像ほど情報量が増えるからです。
さらに業界の豆知識
映像制作や配信の現場では、「1パス」と「2パス」というエンコード方法がよく使われます。
- 1パス: 一度だけ解析してエンコードするので高速。CRFとの相性も良く、日常用途では十分。
- 2パス: 最初に動画全体を解析し、2回目でビットを賢く配分する方式。目標容量を厳密に守りたい場合に使われ、DVDやBlu-ray制作、古くは配信向けファイル作成でよく利用されました。
容量をほぼ43MBに合わせたいなら、2パスの例は次のようになります。
# 1パス
ffmpeg -i input.mp4 \
-c:v libx264 \
-crf 26 \
-preset medium \
-c:a aac -b:a 128k \
output.mp4
# 2パス
ffmpeg -y -i input.mp4 \
-c:v libx264 \
-b:v 1800k \
-pass 2 \
-c:a aac \
-b:a 128k \
output.mp4
この方法は少し時間はかかりますが、「指定した容量にできるだけ近づけたい」という用途では今でも有効です。
最近の傾向
最近では H.265 (HEVC) や AV1 といった新しいコーデックの普及により、H.264よりも30~50%程度少ないビットレートで同等の画質を実現できるケースが増えています。ただし、エンコード時間が長くなったり、古い機器では再生できない場合があるため、互換性とのバランスを考えて選択するのが一般的です。
例えばHEVCで圧縮するなら、
ffmpeg -i input.mp4 \
-c:v libx265 \
-crf 28 \
-c:a aac -b:a 128k \
output.mp4
とするだけで、H.264より小さなファイルになることが多いです。
結局のところ、「容量をきっちり半分にしたい」ならビットレート指定(必要に応じて2パス)、「画質を優先しつつ自然に小さくしたい」ならCRF方式、というのが現在の映像業界で最も一般的な使い分けです。
Error opening output file -c:v
-c:v
\(バックスラッシュ)の後ろにスペースが入ってしまったためです。
あなたが入力したコマンドは実際には
ffmpeg -y -i input.mp4 \ -c:v libx264 -b:v 1800k \ -pass 1 -an -f null /dev/null\
\(バックスラッシュ+スペース)では改行継続になりません。
方法1(おすすめ)
1行で実行してください。ffmpeg -y -i input.mp4 -c:v libx264 -b:v 1800k -pass 1 -an -f null /dev/null
方法2(見やすく書く)
改行するときは、バックスラッシュを行末の最後の文字にします。ffmpeg -y -i input.mp4 \
-c:v libx264 \
-b:v 1800k \
-pass 1 \
-an \
-f null /dev/null
ffmpeg -y -i input.mp4 \
-c:v libx264 \
-b:v 1800k \
-pass 1 \
-an \
-f null /dev/null
... input.mp4 \
↑ここで改行
... input.mp4 \ -c:v
↑スペースがある
あと1つ気になった点
あなたの動画はVideo: VP9
1920x1080
2分51秒
約86MB
ffmpeg -i input.mp4 \
-c:v libx264 \
-crf 26 \
-preset medium \
-c:a aac -b:a 128k \
output.mp4
ffmpeg -i input.mp4 \ -c:v libx264 -b:v 1800k \ -pass 2 -c:a aac -b:a 128k \ output.mp4
\ -c:v
一番確実な方法
まずは1行でそのままコピー&ペーストしてください。ffmpeg -y -i input.mp4 -c:v libx264 -b:v 1800k -pass 2 -c:a aac -b:a 128k output.mp4
改行したい場合
改行前の行の最後の文字を\ にします。
ffmpeg -y -i input.mp4 \
-c:v libx264 \
-b:v 1800k \
-pass 2 \
-c:a aac \
-b:a 128k \
output.mp4
...input.mp4 \
↑ここでEnter
\ -c:v のように、`` の後にスペースを書いてはいけません。
ただし、2パスにはもう1つ注意点があります
2パスエンコードでは、- パス1
- パス2
お願い
確認したいので、次の2つを実行した結果を見せてください。pwd
ls -l ffmpeg2pass*
- パス1が成功してログファイル(
ffmpeg2pass-0.logなど)が作られているか - 今いるディレクトリが正しいか
2分52秒の動画なら、1分ごとに分割するには FFmpeg の segment(セグメント)機能を使うのが一番簡単です。
例えば、
00:00 ~ 00:59.999
01:00 ~ 01:59.999
02:00 ~ 02:51.530
という3つのファイルに分かれます。
方法1(高速・おすすめ)
ffmpeg -i input.mp4 \
-c copy \
-f segment \
-segment_time 60 \
-reset_timestamps 1 \
output_%03d.mp4
すると、
output_000.mp4
output_001.mp4
output_002.mp4
ができます。
オプションの意味
-
-c copy
- 再エンコードしない
- とても速い
- 画質が劣化しない
-
-segment_time 60
- 60秒ごとに区切る
-
-reset_timestamps 1
- 各動画を0秒から始まるようにする
方法2(時間を指定して切る)
きっちり1分ずつ切るなら、
ffmpeg -i input.mp4 -ss 00:00:00 -t 60 -c copy part1.mp4
ffmpeg -i input.mp4 -ss 00:01:00 -t 60 -c copy part2.mp4
ffmpeg -i input.mp4 -ss 00:02:00 -c copy part3.mp4
最後は残り全部になります。
業界話①「コピーだけ」はなぜ速い?
動画は本ではなく、
ページ番号だけ付け替える
ような作業です。
-c copy は
- 映像をそのまま
- 音声もそのまま
コピーするだけなので、
2分の動画でも数秒で終わることがあります。
業界話②「ぴったり1分にならない」ことがある
実は MPEG-4 や H.264、VP9 などでは
Iフレーム
Pフレーム
Bフレーム
という仕組みがあります。
例えば
I
P
P
P
P
P
という並びでは、
途中から再生できません。
だから -c copy では
59.8秒や
60.3秒になることがあります。
これは故障ではなく、
キーフレーム(Iフレーム)単位でしか安全に切れないためです。
業界話③ テレビ局では?
テレビ局や配信会社では
- GOP(Group Of Pictures)
- キーフレーム間隔
を事前に決めています。
例えば
2秒ごとにIフレームを入れる設定なら、
どこで編集してもほぼ問題ありません。
YouTubeも、
アップロードされた動画を内部で再エンコードして、
編集しやすい構造に作り直しています。
業界話④ プロは「再エンコード」で切ることも多い
編集ソフトでは
-c:v libx264
のように再エンコードして切ることもあります。
メリットは
- ぴったり60.000秒
- 好きな位置で切れる
デメリットは
- 時間がかかる
- 少し画質が劣化する
という点です。
おすすめ
今回のような「2分52秒の動画を1分ごとに分けたい」という用途なら、
ffmpeg -i input.mp4 \
-c copy \
-f segment \
-segment_time 60 \
-reset_timestamps 1 \
output_%03d.mp4
が最も手軽です。
もし**「00:01:00ちょうどで必ず切りたい」**という目的なら、再エンコードを伴う方法や、キーフレームを打ち直してから分割する方法もあります。映像制作の現場では、正確なカット編集が必要な場合にこうした方法が使われています。
これは、どうしたら良いですか?、
[segment @ ...] Opening 'output_000.mp4' for writing
[segment @ ...] Opening 'output_001.mp4' for writing
[segment @ ...] Opening 'output_002.mp4' for writing
output_000.mp4
output_001.mp4
output_002.mp4
まず確認してください
同じフォルダで、ls -lh output_*.mp4
output_000.mp4 約60秒
output_001.mp4 約60秒
output_002.mp4 約51秒
途中の警告について
ここですね。[mp4 @ ...] track 1: codec frame size is not set
Video: vp9
Audio: opus
- 映像 → VP9
- 音声 → Opus
- コンテナ → MP4
業界雑学:なぜ変わったMP4なのか?
これはYouTube由来の動画でよくあります。 昔のMP4は、MP4
├─ H.264
└─ AAC
映像はH.264、音声はAACという「テレビ・Blu-ray系」の世界です。 しかし現在のWeb動画では、
MP4
├─ VP9
└─ Opus
comment : https://www.youtube.com/watch?v=...
もし再生できなかった場合
一部のプレイヤーでは、output_000.mp4
ffmpeg -i input.mp4 \
-c:v libx264 \
-c:a aac \
-f segment \
-segment_time 60 \
-reset_timestamps 1 \
output_%03d.mp4
- スマホ互換性◎
- 古いテレビでも再生しやすい
- 時間がかかる
- 少し画質劣化
もう一つ業界的な話
今回の速度、speed=914x
elapsed=0:00:00.18
2分51秒の動画
↓
0.18秒で処理
-c copy は、
「動画を切って箱(コンテナ)に詰め直しただけ」
という処理です。
映像制作現場ではこれを
- ストリームコピー
- ダイレクトストリームコピー
- リマックス
次に確認するなら
以下を実行すると分割後の長さが見られます。ffprobe output_000.mp4
for f in output_*.mp4; do
echo $f
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f"
done
0 件のコメント:
コメントを投稿