scikit-video について
scikit-videoは、科学計算や動画研究向けのPythonツールキットで、NumPyインターフェースを通じて動画を扱い、入出力にはFFmpegを利用します。動き推定、動画品質評価、フレーム単位の読み込みを備え、分析やデータセット作成に使えます。
主な機能
- 01FFmpegによる動画の読み書き
- 02動画フレームをNumPy配列で表現
- 03大容量動画のフレーム単位読み込み
- 04動きと動画品質の指標を計算
- 05生のYUVデータを処理
活用シーン
- 01長い動画から指定区間を抽出
- 02原版と圧縮動画の品質を比較
- 03機械学習向け動画データセットを作成
- 04科学映像の時間変化を分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tondevrel/ scientific-agent-skills --skill scikit-videoインストール後、Claude Code で/scikit-videoを入力して読み込まれたか確認します。
詳細
scikit-video - 科学的な動画処理
scikit-video は、一貫性のある NumPy ベースのインターフェースを提供することで、動画コーデックやコンテナの複雑な仕組みを簡単に扱えるようにします。モーションベクトルの計算、動画品質評価(VQA)、科学的な Python エコシステムとのシームレスな統合が可能です。
使用する場面
- FFmpeg を使用して、さまざまな形式(MP4、AVI、MKV)の動画ファイルを読み書きする場合。
- 動画全体をメモリに読み込まずに、長い動画から特定のフレームや区間を抽出する場合。
- 動きの推定(ブロックマッチング、オプティカルフロー)を計算する場合。
- 動画品質(PSNR、SSIM、VIF、NIQE)を測定する場合。
- 機械学習用の動画データセットを生成する場合。
- ピクセルデータの時間的な変化(科学的な記録など)を可視化する場合。
- 生の YUV データストリームを処理する場合。
リファレンスドキュメント
公式ドキュメント: http://www.scikit-video.org/
GitHub: https://github.com/scikit-video/scikit-video
検索パターン: skvideo.io.vread、skvideo.io.FFmpegReader、skvideo.motion、skvideo.measure
基本原則
4 次元配列としての動画
動画は、形状が (T, H, W, C) の NumPy 配列として表現されます。
- T:時間(フレーム数)
- H:高さ
- W:幅
- C:チャンネル数(通常、RGB の場合は 3)
FFmpeg バックエンド
Scikit-video は独自のコーデックを含まず、FFmpeg へのブリッジとして機能します。skvideo.io を動作させるには、システムに FFmpeg をインストールする必要があります。
大容量データにはジェネレーターを使用
長い動画の場合、scikit-video はジェネレーターベースのリーダー(vreader)を提供し、フレームを 1 つずつ処理して RAM の枯渇を防ぎます。
クイックリファレンス
インストール
pip install scikit-video
# Note: Ensure ffmpeg is in your system PATH
標準的なインポート
import skvideo.io
import skvideo.motion
import skvideo.measure
import numpy as np
基本パターン - 読み込みと確認
import skvideo.io
# 1. Read the whole video into a NumPy array
# Shape: (frames, height, width, 3)
video_data = skvideo.io.vread("experiment.mp4")
# 2. Get basic info
n_frames, height, width, channels = video_data.shape
print(f"FPS: {n_frames / 10}, Resolution: {width}x{height}")
# 3. Access a specific frame
frame_10 = video_data[10]
重要なルール
✅ 推奨事項
- 大きなファイルには vreader を使用する - 高解像度または長時間の動画には、必ずジェネレーターベースの読み込みを使用してください。
- num_frames を設定する - 必要なフレーム数が分かっている場合は、不要なスキャンを避けるために指定してください。
- FFmpeg のパスを確認する - FFmpeg が標準以外の場所にインストールされている場合は、
skvideo.setFFmpegPath()を使用してください。 - メトリクス用に正規化する - ピクセル値が
skvideo.measureで想定される範囲(通常、uint8 では [0, 255])になっていることを確認してください。 - 単純な出力には vwrite を使用する - 複雑な FFmpeg コマンドライン引数を処理してくれます。
- YUV を検討する - 生の伝送データを扱う場合は、専用の YUV 読み込み機能を使用してください。
❌ 非推奨事項
- 4K 動画を vread で読み込む - 1 分間の 4K 動画は、ほとんどの RAM 容量を超えます。
- inputdict と outputdict を無視する - これらを使うと、ビットレート、ピクセル形式、コーデックなどの特定のフラグを FFmpeg に渡せます。
- RGB の順序だと思い込む - 特に外部コーデックを使用している場合は、読み込み後にチャンネルの順序を必ず確認してください。
- ノイズ除去をせずに動画を処理する - 動画ノイズは動きの推定を損なう可能性があります。先に空間フィルターまたは時間フィルターを適用してください。
アンチパターン(絶対に避ける)
import skvideo.io
# ❌ BAD: Loading a massive file at once
# video = skvideo.io.vread("huge_4k_recording.mp4") # CRASH!
# ✅ GOOD: Processing frame by frame
reader = skvideo.io.vreader("huge_4k_recording.mp4")
for frame in reader:
# Process frame
pass
# ❌ BAD: Manual frame writing in a loop with manual codec setup
# (Fragile and complex)
# ✅ GOOD: Use FFmpegWriter
writer = skvideo.io.FFmpegWriter("output.mp4")
for frame in processed_frames:
writer.writeFrame(frame)
writer.close()
# ❌ BAD: Relying on system default FFmpeg without checking
# ✅ GOOD: Verify backend
# print(skvideo._HAS_FFMPEG)
読み込みと書き込み(skvideo.io)
高度な動画入出力
import skvideo.io
# 1. Reading with specific FFmpeg options
input_parameters = {
"-ss": "00:00:10", # Start at 10 seconds
"-t": "5" # Duration 5 seconds
}
video = skvideo.io.vread("video.mp4", inputdict=input_parameters)
# 2. Writing with specific bitrate and codec
output_parameters = {
"-vcodec": "libx264",
"-b:v": "5000k", # 5 Mbps bitrate
"-pix_fmt": "yuv420p"
}
skvideo.io.vwrite("output.mp4", video, outputdict=output_parameters)
動きの推定(skvideo.motion)
動きの計算
from skvideo.motion import blockMotion
from skvideo.io import vread
# Load two consecutive frames
video = vread("video.mp4")
frame1 = video[0]
frame2 = video[1]
# Block matching algorithm
# Returns motion vectors for each block
motion_vectors = blockMotion(frame1, frame2, method='DS', mbSize=16)
# motion_vectors shape: (H/mbSize, W/mbSize, 2)
# The last dimension contains (dy, dx) offsets
動画品質評価(skvideo.measure)
劣化の測定
from skvideo.measure import psnr, ssim, mse
# Compare original and compressed video
original = vread("original.mp4")
distorted = vread("compressed.mp4")
# Calculate metrics frame by frame
psnr_scores = psnr(original, distorted)
ssim_scores = ssim(original, distorted)
print(f"Average PSNR: {np.mean(psnr_scores)}")
データセットとユーティリティ
内蔵データセットの使用
import skvideo.datasets
# Load a built-in sample video (useful for testing)
path = skvideo.datasets.bigbuckbunny()
reader = skvideo.io.vreader(path)
実践的なワークフロー
1. シンプルな背景差分パイプライン
def extract_background(video_path):
"""Calculates the static background of a video using the median."""
reader = skvideo.io.vreader(video_path)
frames = []
# Sample every 10th frame to save memory
for i, frame in enumerate(reader):
if i % 10 == 0:
frames.append(frame)
if len(frames) > 50: break
# Background is the median of frames
background = np.median(np.array(frames), axis=0).astype(np.uint8)
return background
# Usage
# bg = extract_background("security_cam.mp4")
2. 動画の手ブレ補正(フレームの位置合わせ)
def stabilize_frames(video_array):
"""Very basic stabilization using motion vectors."""
stabilized = [video_array[0]]
for i in range(1, len(video_array)):
motion = skvideo.motion.blockMotion(video_array[i-1], video_array[i])
avg_motion = np.mean(motion, axis=(0, 1)) # Global drift
# Translate frame back (Simplified logic)
# Use scipy.ndimage.shift for actual translation
...
3. 動画品質レポートの自動生成
def generate_vqa_report(ref_path, test_path):
ref = skvideo.io.vread(ref_path)
test = skvideo.io.vread(test_path)
report = {
"MSE": np.mean(skvideo.measure.mse(ref, test)),
"PSNR": np.mean(skvideo.measure.psnr(ref, test)),
"SSIM": np.mean(skvideo.measure.ssim(ref, test))
}
return report
パフォーマンスの最適化
マルチスレッドで vreader を使用する
各フレームに対して負荷の高い処理を行う場合は、キューベースのマルチスレッド方式を使用して、FFmpeg パイプが常にデータを受け取れる状態を保ってください。
効率的なスライス
vread で読み込んでからスライスする代わりに、inputdict を介して FFmpeg のシークおよび再生時間のフラグを指定し、ディスクから必要なデータだけを読み込んでください。
よくある問題と解決策
FFmpeg が見つからない
Scikit-video は ffmpeg 実行ファイルに依存します。
# ✅ Solution: Manually set the path if it's not in environment
import skvideo
skvideo.setFFmpegPath("C:/ffmpeg/bin")
色空間の不一致
動画によっては YUV422 または YUV444 で保存されています。Scikit-video はデフォルトでこれらを RGB に変換します。
# ❌ Problem: Colors look washed out or incorrect
# ✅ Solution: Specify the pixel format in inputdict
reader = skvideo.io.vreader("video.mp4", inputdict={"-pix_fmt": "yuv420p"})
メモリ不足(OOM)エラー
vreader を使っていても、すべてのフレームをリストに保存すると、メモリが不足します。
# ❌ Problem: frames.append(frame) in a loop
# ✅ Solution: Process and save to disk, or clear the list periodically.
scikit-video は、FFmpeg の機能を NumPy の世界にもたらします。動画コンテナの複雑さを抽象化し、動きの推定や品質指標などの科学的な分析ツールを提供するため、時間的な画像データを扱う研究者にとって欠かせないツールです。