[ffmpeg影片壓縮] 如何取得原本影片寬高,不放大影片,最大不超過1920,FPS不超過60?

 


 

如果希望在影片的幀率超過 60 FPS 時才限制為 60,否則保留原始幀率,可以先使用 ffprobe 提取影片的幀率,然後根據結果動態設置 FFmpeg 命令。

以下是更新的程式碼:


完整程式碼

import subprocess
import json
import os
import re

def get_video_info(input_file):
    """取得影片的解析度和幀率"""
    command = [
        "ffprobe",
        "-v", "error",
        "-select_streams", "v:0",
        "-show_entries", "stream=width,height,r_frame_rate",
        "-of", "json",
        input_file
    ]
    result = subprocess.run(command, capture_output=True, text=True, check=True)
    video_info = json.loads(result.stdout)
    width = video_info['streams'][0]['width']
    height = video_info['streams'][0]['height']
    
    # 計算幀率(轉換分數形式)
    frame_rate = video_info['streams'][0]['r_frame_rate']
    num, den = map(int, frame_rate.split('/'))
    fps = num / den
    return width, height, fps

def calculate_new_resolution(width, height, max_resolution):
    """計算新的解析度,僅縮小,不放大"""
    if max(width, height) > max_resolution:
        if width > height:
            new_width = max_resolution
            new_height = int(height * max_resolution / width)
        else:
            new_height = max_resolution
            new_width = int(width * max_resolution / height)
        # 確保寬高是偶數
        new_width = (new_width // 2) * 2
        new_height = (new_height // 2) * 2
        return new_width, new_height
    else:
        # 不縮放,保持原解析度
        return width, height

def convert_mov_to_mp4_with_dynamic_fps(input_file, output_file, max_resolution=1920, max_fps=60):
    """轉檔並根據條件限制解析度和幀率"""
    if not os.path.exists(input_file):
        raise FileNotFoundError(f"Input file not found: {input_file}")
    
    # 取得影片資訊
    original_width, original_height, original_fps = get_video_info(input_file)
    new_width, new_height = calculate_new_resolution(original_width, original_height, max_resolution)
    
    # 決定幀率參數
    fps_option = f"-r {max_fps}" if original_fps > max_fps else ""
    
    # 使用 FFmpeg 轉檔
    command = [
        "ffmpeg",
        "-i", input_file,                                # 輸入檔案
        "-vf", f"scale={new_width}:{new_height}",        # 指定解析度
    ]
    if fps_option:
        command.extend(fps_option.split())              # 添加幀率限制
    command.extend([
        "-c:v", "libx264",                              # 重新編碼視訊為 H.264
        "-preset", "fast",                              # 編碼速度與壓縮率平衡
        "-crf", "23",                                   # 視訊品質控制
        "-c:a", "aac",                                  # 音訊重新編碼為 AAC
        "-b:a", "128k",                                 # 音訊比特率
        "-map_metadata", "0",                           # 保留所有元數據
        output_file                                     # 輸出檔案
    ])
    
    try:
        subprocess.run(command, check=True)
        print(f"Conversion successful! Output saved to: {output_file}")
    except subprocess.CalledProcessError as e:
        print(f"Error during conversion: {e}")

# 使用範例
input_mov = "example.mov"
output_mp4 = "example_dynamic_fps.mp4"
convert_mov_to_mp4_with_dynamic_fps(input_mov, output_mp4)

程式說明

  1. 取得幀率

    • 使用 ffprobe 提取 r_frame_rate,計算出實際幀率。
    • 例如,r_frame_rate 可能是 30000/1001,轉換後得到 29.97 FPS
  2. 動態設定幀率

    • 如果原始幀率超過 60 FPS,使用 -r 60 限制。
    • 如果幀率小於或等於 60 FPS,則不添加 -r,保留原始幀率。
  3. 解析度不放大

    • 如果原始寬高小於 1920,直接保留原解析度。
    • 確保解析度的寬高為偶數,避免解碼器問題。
  4. 轉檔流程

    • 幀率條件和解析度條件分別處理,動態生成 FFmpeg 指令。

優點

  • 保留原始幀率(低於 60 FPS 時),符合實際需求。
  • 動態計算解析度,確保不會放大影片且保持寬高比。
  • 高效轉檔,只在必要時改變解析度或幀率。

試試看這個版本,應該能完全符合需求!如果還有其他問題,請隨時告訴我。