| Top > Network camera recording | 最終更新日 : 2025/11/21 |
ONVIF対応のネットワーク・カメラを ffmpeg で録画します。
ネットワーク・カメラの動画ストリームのURI rtsp://IPアドレス:554/・・・ は、固定ではなく都度変わる場合があるため、
ONVIFインターフェースを利用して動画ストリームのURIを都度取得して、ffmpeg の引数に指定します。
以下のサイトを参考にしました。
https://progzakki.sanachan.com/tools/recording-onvif-camera-by-ffmpeg/
https://qiita.com/ikeyasu/items/2a48588111d1b1e75f0c
https://brian0111.com/onvif-python-network-camera-control/
https://note.com/fine_shimit44/n/nc4e6906f73aa
https://kuttsun.blogspot.com/2024/02/python-onvif-rtsp.html
Pythonの onvif-zeep ライブラリーをインストールします。
pip install onvif-zeep
ネットワーク・カメラは、ONVIFを有効、エンコードをH.264に設定します。
最短のスクリプト
#!/usr/bin/python3
from onvif import ONVIFCamera
# カメラに接続
camera = ONVIFCamera( IPアドレス, ポート番号, ユーザーID, パスワード )
# Mediaサービスを取得
media_service = camera.create_media_service()
# プロファイルを取得
profiles = media_service.GetProfiles()
# ストリーミングURIを取得
stream_uri = media_service.GetStreamUri( {'StreamSetup': {'Stream': 'RTP-Unicast', 'Transport': 'UDP'}, 'ProfileToken': profiles[プロファイル番号].token} ).Uri
# ストリーミングURIにユーザーIDとパスワードを挿入
stream_uri = stream_uri[0:7] + ユーザーID + ":" + パスワード + "@" + stream_uri[7:]
# カメラの録画開始
recording_file = 保存するディレクトリ + "/" + 任意のファイル名 + "_%Y%m%d_%H%M.mp4"
ffmpeg = [ "ffmpeg",
"-i", stream_uri,
"-nostdin",
"-vcodec", "copy", ・・・ カメラに応じた設定
"-acodec", "copy", ・・・ カメラに応じた設定
"-f", "segment",
"-segment_time", "出力ファイルの分割時間",
"-segment_format", "mp4",
"-reset_timestamps", "1",
"-strftime", "1",
recording_file
]
if 同期処理または非同期処理の選択条件:
# 同期処理
subprocess.run( ffmpeg )
else:
# 非同期処理
ffmpeg_process = subprocess.Popen( ffmpeg, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL )
コマンド・ラインのオプションと引数の処理、エラー処理、ログ出力を実装した録画スクリプトです。
#!/usr/bin/python3
# 機能 ONVIF対応のネットワーク・カメラを録画する
#
# 引数 ipaddress port userid password outputpath
#
# オプション -h ヘルプ表示
# -p 番号 録画するストリームのプロファイルの番号(デフォルト:0)
# --video-codec ffmpegの音声コーデック
# --no-audio ffmpegで音声を削除
# --audio-codec ffmpegの音声コーデック
# --foregound 録画をフォアグラウンドで実行
# --profiles プロファイルを表示して終了
# --stream-uri ストリームURIを表示して終了
#
# 出力ファイル 出力パス/IPアドレス_日付_時刻.mp4
#
# ライブラリ onvif-zeep
#
# ライブラリのインストール・コマンド
# pip install ライブラリ名
#
# 変更履歴
# 2025/10/03 初版
import argparse, logging, os, subprocess, sys, syslog, traceback
from onvif import ONVIFCamera
CONSOLE_LOG = True
#===================================================================================================
def _info_logging( log ):
logger = logging.getLogger(__name__)
log = "INFO: " + log
syslog.syslog( syslog.LOG_INFO, log )
if CONSOLE_LOG:
logger.info( log )
return
#===================================================================================================
def _exception_logging( exc ):
logger = logging.getLogger(__name__)
tb = traceback.extract_tb( e.__traceback__, limit=1 )
log = "ERROR: " + f"{camera_ip} {camera_port} {camera_userid} {camera_password} : {e.__class__.__name__} : LineNo={tb[0].lineno} [ {tb[0].line} ]"
syslog.syslog( syslog.LOG_INFO, log )
syslog.syslog( syslog.LOG_ERR, log )
if CONSOLE_LOG:
logger.error( log )
return
#===================================================================================================
# コマンド・ラインのオプションと引数
parser = argparse.ArgumentParser( description=os.path.basename(sys.argv[0]) )
parser.add_argument( "-p", type=int, default=0, help="録画するストリームのプロファイルの番号(デフォルト: 0)" )
parser.add_argument( "--video-codec", default="", help="ffmpegの動画コーデック" )
parser.add_argument( "--no-audio", action="store_true", help="ffmpegで音声を削除" )
parser.add_argument( "--audio-codec", default="", help="ffmpegの音声コーデック" )
parser.add_argument( "--foreground", action="store_true", help="録画をフォアグラウンドで実行" )
parser.add_argument( "--profiles", action="store_true", help="プロファイルを表示して終了" )
parser.add_argument( "--stream-uri", action="store_true", help="ストリームURIを表示して終了" )
parser.add_argument( "ipaddress" )
parser.add_argument( "port" )
parser.add_argument( "userid" )
parser.add_argument( "password" )
parser.add_argument( "outputpath" )
args = parser.parse_args()
camera_ip = args.ipaddress
camera_port = args.port
camera_userid = args.userid
camera_password = args.password
output_path = args.outputpath
profile_number = args.p
ffmpeg_vcodec = args.video_codec
ffmpeg_an = args.no_audio
ffmpeg_acodec = args.audio_codec
if not os.path.isdir( output_path ):
print( f"{os.path.basename(sys.argv[0])}: error: dir not found [{output_path}]",file=sys.stderr )
sys.exit( 2 )
_info_logging( f"Starting camera recorder {camera_ip}" )
# カメラに接続
try:
camera = ONVIFCamera( camera_ip, camera_port, camera_userid, camera_password )
except Exception as e:
_exception_logging( e )
sys.exit( 4 )
# Mediaサービスを取得
try:
media_service = camera.create_media_service()
except Exception as e:
_exception_logging( e )
sys.exit( 4 )
# プロファイルを取得
try:
profiles = media_service.GetProfiles()
except Exception as e:
_exception_logging( e )
sys.exit( 4 )
if args.profiles:
print( profiles )
sys.exit( 0 )
# ストリーミングURIを取得
try:
stream_uri = media_service.GetStreamUri( {'StreamSetup': {'Stream': 'RTP-Unicast', 'Transport': 'UDP'}, 'ProfileToken': profiles[profile_number].token} ).Uri
except Exception as e:
_exception_logging( e )
sys.exit( 4 )
if args.stream_uri:
print( stream_uri )
sys.exit( 0 )
rtsp_camera_ip = f"rtsp://{camera_ip}"
if True and stream_uri[0:len(rtsp_camera_ip)].lower() == rtsp_camera_ip:
# ストリーミングURIにユーザーIDとパスワードを挿入
stream_uri = stream_uri[0:7] + camera_userid + ":" + camera_password + "@" + stream_uri[7:]
# カメラの録画開始
recording_file = output_path + "/" + camera_ip + "_%Y%m%d_%H%M.mp4"
ffmpeg = [ "ffmpeg",
"-i", stream_uri,
"-nostdin"
]
if ffmpeg_vcodec != "":
ffmpeg += [ "-vcodec", ffmpeg_vcodec ]
if ffmpeg_an:
ffmpeg += [ "-an" ]
elif ffmpeg_acodec != "":
ffmpeg += [ "-acodec", ffmpeg_acodec ]
ffmpeg += [
"-f", "segment",
"-segment_time", "3600",
"-segment_format", "mp4",
"-reset_timestamps", "1",
"-strftime", "1",
recording_file
]
if args.foreground:
# 同期処理
print( " ".join(ffmpeg) + "\n" )
subprocess.run( ffmpeg )
else:
# 非同期処理
ffmpeg_process = subprocess.Popen( ffmpeg, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL )
_info_logging( f"Started camera recorder {camera_ip}: pid={ffmpeg_process.pid}: {recording_file}" )
上記のスクリプトで録画できるネットワーク・カメラは、以下のとおりです。
| メーカー | 型番 | 接続 | 設定方法 | IPアドレス | ポート番号 | ユーザーID | パスワード | プロファイル番号 | ffmpeg 動画コーデック | ffmpeg 音声コーデック |
|---|---|---|---|---|---|---|---|---|---|---|
| Ctronics | 880C-5MP | 有線、Wi-Fi | PCのブラウザー | 静的設定またはDHCP | 8080 | 設定値 | 設定値 | 0 または 1 | copy | |
| H.VIEW | HV-500S2 | 有線PoE | PCの専用ツール | 静的設定またはDHCP | 80 | 設定値 | 設定値 | 0 または 1 | copy | pcm_s16le |
| Hiseeu | JP-HD405-P | 有線PoE | PCのブラウザー | 静的設定またはDHCP | 8888 | 設定値 | 設定値 | 0 または 1 | copy | |
| ieGeek | IE60 | Wi-Fi | スマホのアプリ | DHCP | 80 | 設定値 | 設定値 | 0 または 1 | copy | copy |