アットウィキロゴ

motion

motion とは

motion は Webカメラ(Video4Linuxデバイス)やネットワークカメラで動体検知し録画するソフトです。動作が軽く、必要な条件だけ録画できるので、録画用のPCを別に用意しなくても、デスクトップ作業をしながら見守りをすることができます。

公式サイト

多くのディストリビューションでパッケージが用意されています。公式サイトでは Ubuntu と Debian の .deb バッケージが配布されています。DEB系以外のディストリで最新版を使うには、ソースをビルドすることになるでしょう。

基本的な使い方

$ motion -c /etc/motion/設定ファイル.conf

で動体検知と録画が始まります。設定ファイルは カメラごとに別々に書きます。多くのディストリでは、/etc/motion に雛形ファイルがあるでしょう。1台のカメラでも、昼と夜で設定ファイルを分けたりできます。軽いので複数台のカメラも1台のPCで間に合います。
PC の性能よりも、USBコントローラーの帯域のほうがボトルネックになることが多いです。多数の Webカメラを接続する場合は、端子ごとにコントローラーを搭載した USB 拡張ボードを用意するといいでしょう。

Web カメラがデバイスとして認識されない

Video4Linux デバイスは /dev/video0 などのデバイスファイルが作られますが、ディストリビューションのデフォルトでは一般ユーザーに権限がないのが普通です。ログインユーザーを video グループに加えることが必要です。

$ sudo adduser ユーザー名 video

PC を再起動すると複数台のカメラの設定が入れ替わってしまう

複数台の Webカメラを接続すると、/dev/video0、/dev/video1、… というようにデバイス名が作られますが、順序が一定しません。udev でエイリアスのデバイス名を別に作って、それを設定ファイルで指定することで、カメラの入れ替わりを回避できます。まず lsusb コマンドで、カメラのデバイス名を調べます。

$ lsusb
Bus 001 Device 002: ID 1bcf:28c4 Sunplus Innovation Technology Inc. FHD Camera Microphone
Bus 001 Device 007: ID 0bda:3036 Realtek Semiconductor Corp. USB Camera

/etc/udev/rules.d/99-local.rules というファイルを新規作成して、エイリアスのデバイス名を作ります。デバイス名の空白文字は逆スラッシュ文字でエスケープする必要があります。

KERNEL=="video[0-9]*", ATTR{index}=="0", ATTR{name}=="USB\ Camera:*", SYMLINK+="video-webcam0"
KERNEL=="video[0-9]*", ATTR{index}=="0", ATTR{name}=="FHD\ Camera\ Microphone*", SYMLINK+="video-webcam1"

カメラの自動露出が夜に追従できない

最近の画像センサーは暗所性能が上がってるので、マニュアル露出すれば夜間でも真っ黒にならないことが多いです(露出時間を長くするので画像が流れますが)。その場合、昼と夜で設定ファイルを別にします。
カメラの露出やシャープネス、フォーカスなどのパラメータをマニュアルでいじるには、vid_control_params オプションで指定します。設定可能なパラメータは、端末の起動メッセージに出てきますので、スクロールバックして拾って下さい。たとえば以下のようになります。

# camera_id
camera_name "FHD Camera"

# Video device (e.g. /dev/video0) to be used for capturing.
videodevice /dev/video-webcam1

# Image width in pixels.
width 1280

# Image height in pixels.
height 720

# Maximum number of frames to be captured per second.
framerate 2
minimum_motion_frames 1

vid_control_params "Brightness"=-33, "Contrast"=1, "Gamma"=100, "Power Line Frequency"=0, "Sharpness"=7,ID10094858=1,ID10094860=0

# Threshold for number of changed pixels that triggers motion.
threshold 40

# Number of images that must contain motion to trigger an event.
minimum_motion_frames 1
smart_mask_speed 3

# Output pictures when motion is detected
picture_output off

# Create movies of motion events.
movie_output on

# Container/Codec to used for the movie. See motion_guide.html
movie_codec mp4

# File name(without extension) for movies relative to target directory
movie_filename %Y%m%d-%H%M-%S%q%v

日付ごとにディレクトリを分けて録画したい

日付ごとにディレクトリを分けるために、ディレクトリを作る起動スクリプトを作ります。まず昼バージョンを $HOME/bin/Fhdcamera.sh とします。夜バージョンが起動してる場合には pkill コマンドで終了させます。

#/bin/sh
pkill -f FHDCamera 
while pgrep FHDCamera > /dev/null; do
    sleep 1
done
mkdir -p $HOME/Pictures/`date "+%m%d"`/fhd
cd $HOME/Pictures/`date "+%m%d"`/fhd
motion -c /etc/motion/FHDCamera.conf

夜バージョンを $HOME/bin/Fhdcamera-n.sh とします。

/bin/sh
pkill -f FHDCamera
while pgrep FHDCamera > /dev/null; do
    sleep 1
done
mkdir -p $HOME/Pictures/`date "+%m%d"`/fhd
cd $HOME/Pictures/`date "+%m%d"`/fhd
motion -c /etc/motion/FHDCamera-n.conf

日の出と日の入りに合わせて露出を変えて自動録画したい

日の出と日の入りの時刻は、python3-suntime でお手軽に取得できます。外部サーバーに接続せずにローカルで計算します。

$ sudo apt install python3-suntime

自動録画は cron で実行するのが簡単です。/etc/crontab で日の出用と日の入り用のスクリプトを指定します。

# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# *  *  *  *  * user-name command to be executed
20 4    * * *   ユーザー名    python3 $HOME/bin/sunrise.py
30 16   * * *   ユーザー名    python3 $HOME/bin/sunset.py 

python3-suntime で日の出または日の入りを時刻までスリープして、その時刻になると、pyhtonのプロセスを motion の起動用のシェルスクリプトに置き換えるには、以下のようにします(日の入り sunset.py の場合)。

import time
from datetime import datetime
from zoneinfo import ZoneInfo  # Python 3.9以上で標準搭載
from suntime import Sun
import os, sys

lat, lon = 35.6895, 139.6917  # 東京の緯度・経度
tz = ZoneInfo('Asia/Tokyo')

sun = Sun(lat, lon)
now = datetime.now(tz)

# 今日の日の出・日没の「正確な日時オブジェクト」を取得
sunrise_dt = sun.get_local_sunrise_time(now).astimezone(tz)
sunset_dt = sun.get_local_sunset_time(now).astimezone(tz)

# 日没ぴったりに動かしたい場合:残り秒数を計算
delay_seconds = (sunset_dt - now).total_seconds()

if delay_seconds > 0:
    print(f"日没({sunset_dt.strftime('%H:%M:%S')})まで {int(delay_seconds)} 秒待機します...")
    # 日没の時間までスクリプトをスリープ(待機)させる
    time.sleep(delay_seconds)
    
    # ─── ここに自動化したい処理(コマンド)を書く ───
    os.execvp("sh", ["sh", "/home/ユーザー名/bin/Fhdcamera-n.sh"])
    print("日没になりました。処理を実行します。")
else:
    print("本日の日没時刻はすでに過ぎています。")
最終更新:2026年09月19日 17:16