本ページはプロモーションが含まれています。

ffmpegで動画を毎晩変換するバッチを書いたものの、共有レンタルサーバーでは途中で止まる、手元のPCでは朝まで起動しておけない。そんな悩みを持つ方に向けて、ffmpeg 7.1をPythonから呼び出す「今の書き方」と、毎晩変換する処理の置き場所の選び方をまとめました。比較するのはエックスサーバー、ConoHa VPS、自宅機の3つです。2026年11月時点の料金、cronの可否、root権限、それぞれが止まる条件を並べます。自分の素材でCPU負荷を測る手順も載せているので、その結果をもとに選べます。

ffmpeg 7.1の夜間変換バッチ:subprocessで呼ぶ今の書き方

実行環境と準備するもの

  • Python:3.9以降を前提にしています。list[str]という型ヒントの書き方を使うためです。確認はpython3 --versionで行います。
  • pip install するパッケージ:ありません。標準ライブラリ(subprocess・pathlib・logging)だけで書いています。
  • ffmpeg:本記事は7.1を想定しています。OSのパッケージで入るバージョンは環境ごとに違うので、ffmpeg -versionの1行目で確認してください。下のコードで使うエンコーダーとオプションが手元で使えるかは、ffmpeg -h encoder=libx264や公式ドキュメントで確かめられます。

以前の書き方と、今の書き方

項目

以前の書き方

今の書き方

ffmpegの呼び出し

os.system()やshell=Trueでコマンド文字列を連結する

subprocess.run()に引数をリストで渡す。ファイル名の空白や記号で壊れない

止まらない処理への対策

何もしない(固まると翌晩の分と重なる)

timeoutで1本ごとに上限を切る。cron側はflockで多重起動を防ぐ

出力ファイル

最終ファイル名へ直接書き込む(途中で落ちると壊れたMP4が残る)

.partに書き出し、成功したときだけリネームする

CPUの使い方

そのまま全力で回す

nice -n 19で優先度を下げる。同じ機械で動く他の処理を邪魔しない

結果の記録

標準出力を捨てる

1本ごとの所要時間と失敗理由をログに残す。置き場所を決める材料にもなる

コード全体(convert.py)

#!/usr/bin/env python3
"""inbox の動画を毎晩まとめて H.264/AAC の MP4 に変換する"""
import logging
import shutil
import subprocess
import sys
import time
from pathlib import Path

BASE = Path("/home/username/videos")
SRC = BASE / "inbox"
DST = BASE / "converted"
DONE = BASE / "done"
LOG = BASE / "logs" / "convert.log"
EXTS = {".mov", ".mp4", ".mkv"}
TIMEOUT_SEC = 60 * 60   # 1本あたりの上限
SETTLE_SEC = 5 * 60     # 更新から5分たっていないファイルはアップロード中とみなす


def build_cmd(src: Path, out: Path) -> list[str]:
    return [
        "nice", "-n", "19",
        "ffmpeg", "-hide_banner", "-nostdin", "-loglevel", "error", "-y",
        "-i", str(src),
        "-c:v", "libx264", "-preset", "medium", "-crf", "23",
        "-c:a", "aac", "-b:a", "128k",
        "-movflags", "+faststart",
        "-f", "mp4", str(out),
    ]


def convert_one(src: Path) -> bool:
    dst = DST / (src.stem + ".mp4")
    part = DST / (src.stem + ".mp4.part")
    started = time.monotonic()
    try:
        result = subprocess.run(
            build_cmd(src, part),
            capture_output=True, text=True, errors="replace",
            timeout=TIMEOUT_SEC,
        )
    except subprocess.TimeoutExpired:
        part.unlink(missing_ok=True)
        logging.error("timeout: %s", src.name)
        return False
    elapsed = time.monotonic() - started
    if result.returncode != 0:
        part.unlink(missing_ok=True)
        logging.error("failed: %s\n%s", src.name, result.stderr[-2000:])
        return False
    part.rename(dst)
    shutil.move(str(src), DONE / src.name)
    logging.info("ok: %s %.1fs", src.name, elapsed)
    return True


def main() -> int:
    for d in (DST, DONE, LOG.parent):
        d.mkdir(parents=True, exist_ok=True)
    logging.basicConfig(filename=LOG, level=logging.INFO,
                        format="%(asctime)s %(levelname)s %(message)s")
    if shutil.which("ffmpeg") is None:
        logging.error("ffmpeg not found in PATH")
        return 1
    now = time.time()
    targets = [p for p in sorted(SRC.iterdir())
               if p.suffix.lower() in EXTS and now - p.stat().st_mtime > SETTLE_SEC]
    failed = 0
    for src in targets:
        if not convert_one(src):
            failed += 1
    logging.info("done: %d files, %d failed", len(targets), failed)
    return 1 if failed else 0


if __name__ == "__main__":
    sys.exit(main())

ブロックごとの説明

  • 定数部分:入力(inbox)、出力(converted)、処理済みの退避先(done)、ログの場所を/home/username/videosの下にまとめています。SETTLE_SECは、アップロード中のファイルを変換し始めないための待ち時間です。
  • build_cmd():ffmpegの引数をリストで組み立てます。nice -n 19はOSに「この処理の優先度は最低でよい」と伝えるコマンドです。-nostdinはcronのような端末のない環境で入力待ちにならないように、-loglevel errorはエラー以外を出さずログを小さく保つために付けています。画質は-crf(値が小さいほど高画質で大きいファイル)、速度は-presetで調整します。
  • convert_one():1本を変換します。出力先は.partなので、拡張子からは形式を判断できません。そのため-f mp4で形式を明示しています。成功したらリネームし、元ファイルはdoneへ移します。こうしておくと、翌晩に同じファイルをもう一度変換することがありません。時間切れや失敗のときは中途半端な.partを消し、ffmpegのエラー出力の末尾をログに残します。
  • main():フォルダを用意し、ffmpegがPATH(コマンドを探す場所の一覧)にあるかを先に確かめます。cronはログイン時と違う最小限のPATHで動くため、ここで止まる例が多いからです。失敗が1本でもあれば終了コード1を返します。cron側やGitHub Actions側で異常を検知しやすくするためです。

CPU負荷と処理時間を自分の素材で測る(/usr/bin/timeとログ)

動画変換の重さは、素材の長さ・解像度・-presetの値で大きく変わります。他人の実測値はそのまま当てはまりません。私は置き場所を決める前に、まず1晩分の素材を手元で変換して、次の項目を測るようにしています。

測り方

/usr/bin/time -v python3 /home/username/videos/convert.py
grep "ok:" /home/username/videos/logs/convert.log
nproc
free -h

測る項目

確認方法

判断に使うこと

1晩分の合計時間

time -vの「Elapsed (wall clock) time」

夜間のうちに終わるか。1vCPUのVPSでも足りるか

1本あたりの所要時間

ログのok: ファイル名 秒数

TIMEOUT_SECの目安。共有サーバーの実行時間制限に収まるか

最大メモリ使用量

time -vの「Maximum resident set size」

メモリ512MB〜1GBのプランで足りるか

測った機械のコア数

nproc

コア数の違うVPSで時間がどう変わるかの見積もり

測った機械がVPSより多くのコアを持っていれば、VPSではその分だけ遅くなると見込んでおくのが無難です。最終的には、後述する時間課金・無料お試しのVPSで同じスクリプトを1回流して確かめるのが確実です。

エックスサーバー・ConoHa VPS・自宅機の比較(2026年11月の料金とCPU制限)

比較表

置き場所

2026年11月時点の料金

cron

常駐

root権限

CPU

エックスサーバー(スタンダード)

月額1,100円〜(12ヶ月契約)、10日間無料お試し

可(最短5分間隔)

原則不可

不可

共用

ConoHa VPS(最安プラン)

1ヶ月契約で月額460円、36ヶ月一括で月額換算326円、時間課金あり

可(最短1分)

可

可

1コア

シンVPS 4GB

36ヶ月契約で月額1,350円(3ヶ月契約は月額1,771円)

可(最短1分)

可

可

プラン依存

XServer VPS クラウド 4GB

月額2,480円(2026年8月31日開始、自動バックアップ付き)

可

可

可

プラン依存

自宅機

機械と電気代のみ

可

可

可

手持ちの機械次第

  • ConoHa VPSの最安プランのメモリは、調査の段階で1GBとする情報と512MBとする情報がありました。契約前に公式の料金ページで確認してください。
  • Xserver VPSは2026年9月17日から全プランの新規受付を一時停止しています。2026年11月中に再開する予定ですが、確定ではありません。停止前の4GBプラン(4コア・4GB・150GB NVMe SSD)は、1ヶ月契約で月額2,640円でした。
  • さくらのVPSは石狩リージョンの1GBが月額880円で、2週間の無料お試しがあります。CVE-2026-99999への対応で止まっていた新規申し込みも、11月10日までに大阪リージョンのLinux通常容量プランを除いて再開しています。

共有レンタルサーバーで変換を回しにくい理由

エックスサーバーのような共有レンタルサーバーでもcronは使えます。ただし、CPU重めの変換を毎晩回すには、次の点で詰まりやすくなります。

  1. root権限がない:OSのパッケージとしてffmpegを入れられません。自前のバイナリを置くことが規約上許されるかは、事業者のマニュアルで確認が必要です。
  2. CPU・メモリが共用:他の利用者と同じ機械を分け合っています。長時間CPUを使い切る処理は、負荷が高いとして止められる可能性があります。具体的な制限値は公式マニュアルで確認してください。
  3. 常駐が原則不可で、プロセスにタイムアウトがある:1本に数十分かかる変換は途中で終了させられることがあります。この症状と、処理を分割して逃がす書き方はレンタルサーバー cron 強制終了|30分バッチ 26年11月にまとめています。

Webサイトの置き場所としては、2026年10月のPHP脆弱性(PHP2shell)の際、エックスサーバーは翌朝には対応作業を始めていたという評価があります。サイトは共有サーバーに置き、重い変換だけをVPSか自宅機に分ける構成が現実的です。

条件別の選び方と、それぞれが止まる条件

あなたの条件

選ぶ置き場所

止まる条件

測った処理が1本数分で終わり、追加ソフトが要らない

共有レンタルサーバーのcron(ただしffmpegが使える場合に限る)

実行時間・CPUの制限に当たったとき、ffmpegを置けないとき、規約上重い処理と判断されたとき

1晩の合計が長く、最大メモリが1GBに収まる

ConoHa VPSなどの1GB級VPS(時間課金で試してから月額・長期契約へ)

メモリ不足でプロセスが落ちたとき、カーネル更新などのメンテナンスで再起動したとき、支払いが止まったとき、SSHを開けっぱなしにして侵入されたとき

4K素材などでメモリやコアが足りない

シンVPS 4GBやXServer VPS クラウドなど4GB級のVPS

上と同じ。加えて、新規受付の停止中(Xserver VPS)は契約できない

素材が自宅にあり、手元に高性能な機械がある

自宅機のcron(外部に公開しない)

スリープ・電源断・OS更新による再起動、家族による電源オフ、機械の故障

素材を毎晩数GB単位で上げ下ろしするなら、アップロードの手間と回線の負担も考えてください。自宅に素材がある場合は、自宅機で変換して完成品だけをサーバーへ送る方が速いことも多いです。

毎晩動かし続ける設定:cron・flock・VPSの最低限の防御

cronの設定

30 1 * * * /usr/bin/flock -n /home/username/videos/convert.lock /usr/bin/python3 /home/username/videos/convert.py >> /home/username/videos/logs/cron.log 2>&1
  • 30 1 * * *:毎日1時30分に起動します。
  • flock -n:ロックファイルを使って、前の晩の変換がまだ動いていれば今夜の起動をすぐ諦めます。2本同時にffmpegが走ってCPUを取り合うのを防ぐ仕組みです。
  • コマンドはフルパスで書きます。cronのPATHは最小限なので、python3だけでは見つからないことがあるためです。
  • 失敗に気づける仕組みも必要です。cronの出力をメールで受け取る方法と、VPSで25番ポートが塞がれている場合の考え方はcron メール通知 置き場所|25番ポートと26年11月料金で扱っています。

小さなVPSでも開設直後から狙われる

「変換するだけの無名サーバーだから」という油断は通用しません。ConoHa VPSのCPU1コア・メモリ512MBの小型サーバーでは、開設直後から世界各地から3万回を超える不審な接続があったと報告されています。わずか16秒でプログラムの持ち込み・起動・削除まで試みる攻撃も観測されました(2026年10月21日〜29日の観測)。また、2026年10月16日にはLinuxカーネルの脆弱性CVE-2026-99999(通称PwnEscape)が公開され、VPS各社が対応に追われました。VPSを選んだら、最初に次の作業を済ませてください。

  1. SSHは鍵認証にし、/etc/ssh/sshd_configでPasswordAuthentication noにする(接続はssh username@203.0.113.10のように鍵で行う)
  2. ファイアウォールで、使うポート以外を閉じる。変換バッチだけならWebのポートを開ける必要はない
  3. OSとカーネルの更新を定期的に当て、再起動後にcronが動いているかをログで確認する

自宅機は、外部から接続できるように公開しなければ、こうした攻撃の対象になりにくくなります。素材の受け渡しのためだけにポートを開けるのは避けましょう。

素材の取得元への配慮(robots.txt・利用規約・アクセス間隔)

変換する動画を自分の機材やストレージから集めるなら問題ありません。外部のサイトから素材を取得して変換する場合は、次の点を守ってください。

  • robots.txt(クローラーに取得してよい範囲を伝えるファイル)をhttps://example.com/robots.txtのように確認し、禁止されているパスは取得しない
  • 利用規約で自動取得・ダウンロード・再加工が許されているかを確認する。動画は著作物なので、規約で許されていても変換後の公開範囲には注意する
  • アクセス間隔:1ファイルごとにtime.sleep()で十分な間隔をあけ、並列で一斉に取得しない。動画は1ファイルが大きいため、相手の回線への負担は普通のページ取得より重くなる
  • ログインや取得制限がかかっている素材を、仕組みを回避して取りに行かない。権限のある方法(提供元のエクスポート機能や公式APIなど)がある場合はそちらを使う

関連する選択肢

毎日決まった時刻にスクリプトを動かすだけなら、共有のレンタルサーバーでも足ります。cronが使えるプランを選べば、自分でOSを管理する必要はありません。

レンタルサーバー エックスサーバー

※ 広告を含みます(A8.net)。リンク経由でお申し込みがあった場合、手数料を受け取ることがあります。

まとめ:毎晩の変換を止めないための3つの判断

ffmpegの夜間バッチは、subprocess.run()にリストで引数を渡し、timeout・.part出力・nice・flockを組み合わせるのが今の書き方です。置き場所は、まず自分の素材で合計時間と最大メモリを測ってから決めます。エックスサーバーのような共有サーバーはcronこそ最短5分間隔で使えますが、root権限がなく常駐も原則不可なので、重い変換には向きません。1GBに収まるならConoHa VPS(月額460円〜)、足りなければシンVPS 4GB(36ヶ月契約で月額1,350円)などの4GB級、素材が手元にあるなら自宅機が候補です。VPSは開設直後から攻撃されるため、鍵認証・ファイアウォール・更新の3点を最初に済ませてください。