

私のPCの環境はお世辞にも新しいと言えないのです。
CPU:Intel i9-9900es GPU:GEFORCE GTX1060 6GB 2枚搭載という環境です。OSはWindows11pro 25H2
CPUもGPUもヤフオクで購入です。GPUに至っては、ヤフオクで中古で購入でした。
今回は、拡張子tsのファイルを1920*1080のFHD、ファイルサイズは500MB以下に自動的に圧縮して保存するPythonコードをgemini3にお願いして作ってみました。
前提条件
前提条件:
「FFmpegがインストールされ、パスが通っていること」
「NVIDIAのGPU(およびドライバ)がインストールされていること」
カスタマイズ:
target_size_mb = 500 の数値を変えれば、好みのサイズに調整できます。←1ファイルの上限を500MB以下としています。
NvidiaのGPUを使っているならそのままコピーで試してみて
先にAMD用に変更する部分のコードを記載しておきます。ただし、当方で動作環境がないので未確認です。
# --- AMD GPU (AMF) 用のコマンド設定 ---
final_cmd = [
'ffmpeg', '-y', '-i', input_path,
'-c:v', 'h264_amf', # AMDのエンコーダーを指定
'-b:v', f'{video_bitrate}k', # 映像ビットレート
'-s', '1920x1080', # フルHD
'-quality', 'quality', # 画質優先設定(speed, balanced, quality)
'-rc', 'vbr_peak', # 可変ビットレート制御
'-c:a', 'aac', '-b:a', '128k',
output_path
]
コード本体はこちらになります。こちらは動作検証済みです。
import os
import subprocess
import tkinter as tk
from tkinter import filedialog
def get_duration(input_file):
"""動画の長さを取得する"""
cmd = [
'ffprobe', '-v', 'error',
'-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1',
input_file
]
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8')
if result.returncode != 0:
return None
return float(result.stdout.strip())
def get_best_gpu():
"""空いているGPUを選択"""
try:
cmd = "nvidia-smi --query-gpu=utilization.gpu --format=csv,nounits,noheader"
result = subprocess.check_output(cmd, shell=True).decode('utf-8')
utils = [int(x) for x in result.strip().split('\n')]
return utils.index(min(utils))
except:
return 0
def main():
# 1. ファイル選択ダイアログを表示(複数選択を許可)
root = tk.Tk()
root.withdraw()
print("変換したいTSファイルをすべて選択してください(Ctrlキーやマウスドラッグで複数選べます)...")
# askopenfilenames (最後にsがつく) に変更
file_paths = filedialog.askopenfilenames(title="TSファイルを複数選択してください", filetypes=[("TS files", "*.ts")])
if not file_paths:
print("ファイルが選択されませんでした。")
return
total_files = len(file_paths)
print(f"{total_files} 個のファイルが選択されました。変換を開始します。\n")
for i, raw_path in enumerate(file_paths, 1):
input_path = os.path.normpath(raw_path)
output_path = os.path.splitext(input_path)[0] + ".mp4"
filename = os.path.basename(input_path)
print(f"[{i}/{total_files}] 処理中: {filename}")
# 2. 動画の長さを取得
duration = get_duration(input_path)
if duration is None:
print(f" × エラー: {filename} の長さが取得できません。スキップします。")
continue
# 3. ビットレート計算 (500MB目安)
target_size_mb = 500
target_total_bitrate = (target_size_mb * 8192 * 0.94) / duration
video_bitrate = int(target_total_bitrate - 128)
# 4. GPU選択(ファイルごとに空いている方を確認)
selected_gpu = get_best_gpu()
final_cmd = [
'ffmpeg', '-y', '-i', input_path,
'-c:v', 'h264_nvenc', '-b:v', f'{video_bitrate}k',
'-maxrate', f'{video_bitrate * 2}k', '-bufsize', f'{video_bitrate * 2}k',
'-gpu', str(selected_gpu), '-s', '1920x1080',
'-c:a', 'aac', '-b:a', '128k',
output_path
]
try:
# 実行
subprocess.run(final_cmd, check=True, capture_output=True)
print(f" ○ 完了!")
except subprocess.CalledProcessError as e:
print(f" × 変換エラー: {e}")
print("\nすべての処理が完了しました!")
if __name__ == "__main__":
main()
geminiに転載の許可は取ってあります。(笑)