2026年11月14日土曜日

86Mb位の、動画を。半分くらいの、容量に、ダイエットさせる、python3スクリプトや、Linuxコマンドについて、

86Mb位の、動画を。半分くらいの、容量に、ダイエットさせる、python3スクリプトや、Linuxコマンドについて、雑学や業界話を交えながら、解説してください。

動画を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の目安

CRF 画質 容量
18 ほぼ無劣化 かなり大きい
23 FFmpeg標準 普通
26 少し軽量 小さい
30 かなり圧縮 だいぶ小さい

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
FFmpegが
-c:v
を**「出力ファイル名」**だと思ってしまっています。 これは、Linuxシェルで \(バックスラッシュ)の後ろにスペースが入ってしまったためです。 あなたが入力したコマンドは実際には
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
となっています。 これなら1800k固定では画質が少し落ちるかもしれません。 私は今回はCRF方式をおすすめします。 例えば
ffmpeg -i input.mp4 \
  -c:v libx264 \
  -crf 26 \
  -preset medium \
  -c:a aac -b:a 128k \
  output.mp4
この方法なら、画質を見ながら自然に40~50MB程度になる可能性が高く、2パスより手軽です。 もし「86MB → 43MB前後にかなり正確に合わせたい」のであれば、その動画(2分51秒)に合わせて最適なビットレートを計算し、2パス用のコマンドを具体的な数値で作成します。  

同じ原因です。😊 FFmpegではなく、シェルへの入力方法が間違っています。 あなたが入力したのは
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. パス1
  2. パス2
を同じディレクトリで連続して実行する必要があります。 もしパス1が失敗していたら、パス2も成功しません。

お願い

確認したいので、次の2つを実行した結果を見せてください。
pwd
と
ls -l ffmpeg2pass*
これで、
  • パス1が成功してログファイル(ffmpeg2pass-0.logなど)が作られているか
  • 今いるディレクトリが正しいか
を確認できます。 また、コピー&ペーストではなく手入力している場合は、`` の後ろにスペースが入りやすいので、まずは1行版のコマンドを試すのがおすすめです。


2分52秒を、一分ごとに、分ける、コマンドを、雑学や業界話を交えながら、解説してください、

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
の3個に分割されています。

まず確認してください

同じフォルダで、
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
これは少し気になりますが、今回は致命的ではありません。 理由は、元動画が普通のMP4ではなく、
Video: vp9
Audio: opus
だからです。 つまり、
  • 映像 → VP9
  • 音声 → Opus
  • コンテナ → MP4
という、少し変わった組み合わせです。

業界雑学:なぜ変わったMP4なのか?

これはYouTube由来の動画でよくあります。 昔のMP4は、
MP4
 ├─ H.264
 └─ AAC
が定番でした。 いわゆる、
映像はH.264、音声はAAC
という「テレビ・Blu-ray系」の世界です。 しかし現在のWeb動画では、
MP4
 ├─ VP9
 └─ Opus
のような組み合わせも増えました。 Google系サービスでは特に多いです。 あなたの情報にも、
comment : https://www.youtube.com/watch?v=...
がありますので、おそらくYouTube由来でしょう。

もし再生できなかった場合

一部のプレイヤーでは、
output_000.mp4
が再生できない可能性があります。 その場合は「コピー」ではなく、再エンコードします。 例えば:
ffmpeg -i input.mp4 \
-c:v libx264 \
-c:a aac \
-f segment \
-segment_time 60 \
-reset_timestamps 1 \
output_%03d.mp4
これは、 VP9 → H.264 Opus → AAC に変換します。 メリット:
  • スマホ互換性◎
  • 古いテレビでも再生しやすい
デメリット:
  • 時間がかかる
  • 少し画質劣化

もう一つ業界的な話

今回の速度、
speed=914x
elapsed=0:00:00.18
これは驚異的です。 なぜなら、
2分51秒の動画
↓
0.18秒で処理
だからです。 これはCPUが頑張ったのではなく、 映像を計算していないからです。 -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
今回の処理自体は成功しています。 次の段階としては、「この3つをスマホ向けH.264に変換する」か「容量をさらに半分にする」あたりが実用的です。

0 件のコメント: