先の記事「コンクリート劣化の原因調査 」に関連して画像を撮影してアップロードする仕組みを構築しました。ここでは、構築までの手順を活用できる形で紹介していきます。事前準備がほぼ出来上がっているので意外と簡単に構築できました。
10分おきに自動更新している画像 ※画像が更新されていない場合は、ブラウザキャッシュが効いていることがあります。F5キーで再読み込みするか、Ctrl+右クリックで画像を、別タブで開いてF5キーを押すと再読み込みされます。
キャッチ画像から作成した動画 動画化 このように、NASへの蓄積から動画生成や、クラウドへのアップロードも自動化できました。
使用した製品 10年前のノートPCで動いているhsBoxの他には、下の製品を使用して構築しています。 カメラ: アトムテック株式会社(ATOM tech Inc.) 製 ATOM Cam 2https://www.atomtech.co.jp/products/atomcam2 NAS: BUFFALO 製 LS710Dhttps://www.buffalo.jp/product/detail/ls710d0101.html
実装方針、実装方法 できるだけ手間をかけず(つまりATOM Cam 2の改造など特殊なことはしない)、運用やhsBoxへの負荷も最低限になるように設計する。 ということで、hsBoxを使い10分間隔でrtspでATOM Cam2から画像を取得して、NASに保存、同時にクラウド上に送ることにしました。
事前準備 hsBoxに必要なライブラリが入っているかなど環境状況を確認します。 結果、必要なものはすべてこれまでの構築等でインストールされていることを確認しました。 インストールされていない場合インストールしてください。※ 本記事内のRTSP URL、トークン、ユーザー名・パスワードはすべてダミーです。
■ATOM CAM2のrtspのURLを確認する rtsp://<*user>:<*pass>@192.168.**.**/live ★ ■hsBoxライブラリの確認 ●FFmpeg (コマンドラインツール) ffmpeg -version ●NFS / CIFS (NAS接続用ユーティリティ) # インストールされているパッケージの確認 dpkg -l | grep -E 'nfs-common|cifs-utils' ●3. Python環境の確認 #hsBoxの制御コードを書くためのベースを確認します。 #Python はhsBoxで構築済みなので省きます。 ●マウントポイントの作成 #NASの画像を置くためのディレクトリをhsBox内に作成します。 #すでに作っていれば不要 sudo mkdir -p /mnt/nas_cam ●手動マウント マウントは他の記事(proxy設定) も参考にしてください アトムテックの製品のうち、rtspに対応しているのは公式にはATOM Cam 2のみです。ATOM Cam SwingやATOM Cam GPTは対応していないようです。 また、最初のころのATOM Cam2はrtspは公開されていなかったと記憶しています。ファームウェアバージョンにも依存するようです。対応状況やrtspのURL確認方法などの詳細はアトムテックのサイト を確認してください。
事前準備が終わったら、手動で画像が取れるか確認してみましょう。
ffmpeg -rtsp_transport tcp -ss 00:00:01 -i "rtsp://**:**@192.168.**.**/live" -vframes 1 -q:v 2 -y test_out.jpg *マークの箇所は環境に合わせて修正してください。 これで、画像が撮れれば問題ありません。取れなければIPが変わっていないかなどネットワーク的な問題を確認・解決する必要があります。
IPは動的に変わるので、MACからIPを確認する実装を組み込みます。そこで使用するMACアドレスを確認します。
# arp -a |grep 192.168.**.** ? (192.168.**.**) at 7c:dd:e9:**:**:** [ether] on enp1s0 MACアドレスが確認できました。 ここまで準備できればほぼ完成です。
サンプル実装(hsBox側実装) ★印の箇所は環境に合わせて設定してください。 コードは、Windows、hsBox (Linux) 共用です。 ※ 実運用では、環境変数や設定ファイルを用いてコード外に分離してください。
import os import subprocess import sys import re import base64 from datetime import datetime # --- 設定項目 --- # Windowsで試す際は、ここをカメラのIP等に書き換えてください #RTSP_URL = "rtsp://**:**@192.168.*.*:554/live" # 確認したMACアドレスをここに(ハイフンでもコロンでもOK) TARGET_MAC = "7c-dd-e9-**-**-**" # ★要更新 RTSP_USER = "**" # ★ RTSP_PASS = "**" # ★ # 保存先設定 # 保存先設定 #SAVE_DIR = "/mnt/nas_cam" if os.name != 'nt' else r"C:\temp\atom" SAVE_DIR = r"\\192.168.**.*****" if os.name == 'nt' else "/mnt/nas****" # ★ # url = "https://******.jp/**/upload.php" # ★ クラウドアップロードURL token = "your_secret_token" # ★ #認証の情報 user = "*****" # ★ pass = "*****" # ★ # ----------------------- BASE_DIR = SAVE_DIR def get_next_serial(BASE_DIR ): counter_file = os.path.join(BASE_DIR , "counter.txt") # 現在の番号を読み込む if os.path.exists(counter_file): with open(counter_file, "r") as f: try: count = int(f.read().strip()) except: count = 0 else: count = 0 # 次の番号を決定(0-199のリング) next_count = (count + 1) % 200 # 更新して保存 with open(counter_file, "w") as f: f.write(str(next_count)) return f"{count:03d}.jpg" # 000.jpg 形式 def upload_to_xserver(local_file_path, serial_name): # ユーザー名とパスワードを結合してBase64エンコード user_pass = f"{user}:{pass}" auth_encoded = base64.b64encode(user_pass.encode('ascii')).decode('ascii') # curlで「サーバー側の名前」を指定して送る # ★ cmd = [ 'curl', '-s', '-X', 'POST', #'--user', f'{basic_user}:{basic_pass}', # ここで認証を通す # ★ #'-H', f'Authorization: Basic {auth_encoded}', # ヘッダーで認証を通す # ★ '-F', f'image=@{local_file_path};filename={serial_name}', '-F', f'token={token}', url ] subprocess.run(cmd) def capture_with_auto_management(): ip = get_current_ip(TARGET_MAC) if not ip: print("Error: Camera not found.") sys.exit(1) # 1. 日付ごとのディレクトリ名を生成 (例: 2025-12-23) today_str = datetime.now().strftime("%Y-%m-%d") daily_dir = os.path.join(BASE_DIR, today_str) # 2. ディレクトリがなければ作成 if not os.path.exists(daily_dir): os.makedirs(daily_dir, exist_ok=True) # 3. ファイル名の生成 (例: 20251223_183000.jpg) filename = datetime.now().strftime("%Y%m%d_%H%M%S.jpg") save_path = os.path.join(daily_dir, filename) # --- ffmpeg実行部 --- rtsp_url = f"rtsp://{RTSP_USER}:{RTSP_PASS}@{ip}/live" cmd = [ 'ffmpeg', '-rtsp_transport', 'tcp', '-i', rtsp_url, '-ss', '00:00:01', '-vframes', '1', '-q:v', '2', '-y', save_path ] try: subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True, timeout=20) print(f"Saved: {filename} (via {ip})") serial_name = get_next_serial(BASE_DIR ) upload_to_xserver(save_path, serial_name) except Exception as e: print(f"FFmpeg failed: {e}") def get_current_ip(mac): """MACアドレスから現在のIPアドレスを特定する (Win/Linux共用)""" target_mac_raw = mac.replace(":", "").replace("-", "").lower() # --- 1. ARPテーブルの強制更新 (Linuxのみ) --- if os.name != 'nt': subprocess.run(["ping", "-c", "2", "-b", "192.168.*.255"], # ★ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) try: # ARPテーブルを取得 res = subprocess.check_output(["arp", "-a"]).decode("cp932" if os.name == 'nt' else "utf-8") for line in res.splitlines(): # 解析中の行からも記号をすべて消す line_raw = line.replace(":", "").replace("-", "").lower() # 純粋な英数字の並びでマッチング if target_mac_raw in line_raw: # 行からIPアドレス部分だけを抜き出す match = re.search(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", line) if match: return match.group(1) except Exception as e: print(f"Network scan error: {e}") return None if __name__ == "__main__": capture_with_auto_management() NASの指定ディレクトリの下に日付ディレクトリを作成し、その下にファイルを蓄積していきます。 ファイル自動削除の実装はありません。 必要に応じて、WindowsのエクスプローラーやNAS管理画面から手動で削除してください。
■サンプル実装(クラウド側実装) ※ 本PHPコードは動作確認用の簡易実装です。 ※ 実運用では、IP制限、HTTPS、拡張子チェック等の追加を推奨します。 ★
<?php //---★環境に合わせてアクセス制限等を追加してください $token = "your_secret_token"; // 簡易認証用 if ($_POST['token'] !== $token) exit("Access Denied"); $save_dir = "/cam_images/"; if (!is_dir($save_dir)) mkdir($save_dir, 0755); if (isset($_FILES['image'])) { // クライアントが指定したファイル名(001.jpg等)で保存 $file_name = basename($_FILES['image']['name']); move_uploaded_file($_FILES['image']['tmp_name'], $save_dir . $file_name); // 常に最新を確認するための固定名コピーも同時に行う copy($save_dir . $file_name, $save_dir . "latest.jpg"); echo "OK"; } アップロードされたファイルをディレクトリに保存します。 アップロードする際に000~199の番号をシリアルでつけてアップロードしてくるので、それを上書き保存します。あふれることはないので削除は不要です。 同時に、”latest.jpg”にコピーします。 latest.jpgに常に最新の画像が保存されます。
あとはcronに設定を追加するだけで、画像を蓄積し続けます。 cron設定についてはhsBox本家サイトの記事(hsBoxで作る“LAN監視システム・アラート”) を参考にしてください。
追加記事 上の記事の実装で、後日検出した問題と暫定対処https://mic.or.jp/info/2026/01/26/cam-3/
関連記事 https://mic.or.jp/info/2026/01/30/cam-4/