Pythonで動画ファイルを編集(秒数指定・範囲指定トリミングと倍速再生)してみた

# はじめに

こんにちは。この記事では、Pythonを使って動画を自動トリミングしたり、指定した範囲の動画を倍速で出力する方法を解説します。「動画の一部を切り出したい」「動画の一部を倍速で再生したい」という需要にこたえられる記事です。

この記事では、PythonとOpenCVを使って実現する動画の自動一括トリミングと倍速出力機能を解説します。

# この記事の目次
- [対象読者](#対象読者)
- [実現したいこと](#実現したいこと)
- [必要な環境](#必要な環境)
- [Step1: OpenCVのインストール](#step1-opencvのインストール)
- [Step2: Pythonコードを作成](#step2pythonコードを作成)
- [Step3: Pythonコードを実行](#step3pythonコードを実行)
- [おわりに](#おわりに)

# 対象読者
- OpenCVを使って動画のトリミングや倍速出力を実現したい人

# 実現したいこと
1. 動画を指定した範囲(上下左右)でトリミング
2. 動画を指定した範囲(開始時間・終了時間)でトリミング
3. 動画をx倍速

# 必要な環境
- Python 3.11.9

## Step1: OpenCVのインストール
まず、OpenCVをインストールする必要があります。下記のコマンドを実行してください。

```bash
pip install opencv-python
```

# Step2:Pythonコードを作成
下記は指定した領域と時間範囲で動画をトリミングし、指定倍速で出力するPythonコードです。
自分で指定する値は、
- ```input_folder```：編集前の動画ファイル名
- ```output_foldrer```：編集後の動画ファイル名
- ```x_times_speed```：x倍速
- ```start_time```, ```end_time```：トリミングの開始・終了秒数(ミリ秒)
- ```top```, ```bottom```, ```left```, ```right```：トリミング領域

です。

```trim_video.py
import cv2
import math

def trimVideo(targetFileName, destFileName, startMillis, stopMillis, x_times_faster, top, bottom, left, right):
    # 動画のFPS、フレーム数・開始終了フレーム番号取得
    videoCapture = cv2.VideoCapture(targetFileName)
    fps = videoCapture.get(cv2.CAP_PROP_FPS)
    totalFrames = int(videoCapture.get(cv2.CAP_PROP_FRAME_COUNT))
    width = int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # トリミング範囲のチェック
    if left < 0 or right > width or top < 0 or bottom > height:
        print("エラー: トリミング範囲が動画の範囲外です。")
        return

    startFrameIndex = math.ceil(fps * startMillis / 1000)
    stopFrameIndex = math.ceil(fps * stopMillis / 1000)
    
    if startFrameIndex < 0: 
        startFrameIndex = 0
    if stopFrameIndex >= totalFrames:
        stopFrameIndex = totalFrames - 1

    videoCapture.set(cv2.CAP_PROP_POS_FRAMES, startFrameIndex)
    frameIndex = startFrameIndex
    
    # 開始～終了地点までフレームを分割し、トリミング
    imgArr = []
    while frameIndex <= stopFrameIndex:
        ret, img = videoCapture.read()
        if not ret:
            break
        cropped_img = img[top:bottom, left:right]  # トリミング処理
        imgArr.append(cropped_img)
        frameIndex += 1
        
    # 分割フレームをmp4動画に再構成
    output_fps = fps * x_times_faster
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
    video = None
    tmpVideoFileName = destFileName
    for img in imgArr:
        if video is None:
            h, w, _ = img.shape
            video = cv2.VideoWriter(tmpVideoFileName, fourcc, output_fps, (w, h))
        video.write(img)
    
    video.release()
    print(f"動画を '{destFileName}' に保存しました。")

if __name__ == "__main__":
    
    prefix          = "test"
    
    input_filename  = prefix + ".mp4"
    output_filename = prefix + "_trimmed.mp4"
    
    start_time      = 15500     # ms
    end_time        = 83500     # ms
    
    x_times_speed   = 2.0
    
    top             = 330
    bottom          = 820
    left            = 890
    right           = 1390
    
    trimVideo(input_filename, output_filename, 
              start_time, end_time, 
              x_times_speed, 
              top, bottom,left, right
    )
```

# Step3:Pythonコードを実行
それではStep2で作成したPythonコードを実行していきましょう。
```trim_video.py```と編集対象の.mp4ファイルは同じディレクトリに配置してください。

```shell-session
> python trim_video.py
動画を 'test_trimmed.mp4' に保存しました。
```
実行後、指定した範囲をトリミングし、倍速化した動画が指定したファイル名で保存されます。

# おわりに
この記事では、PythonとOpenCVを使って動画をトリミングしたり倍速出力する方法を解説しました。動画の編集作業を自動化することで、手作業の負担を大幅に減らすことができます。この記事が少しでも参考になれば幸いです。ぜひ自分の用途に合わせてコードをカスタマイズしてみてください。