🎥

ネットワークカメラの映像をRTSP経由でMacの画面に表示する

2023/09/18に公開

はじめに

この記事ではTapo C310という種類のネットワークカメラの映像をRTSP経由でMacPCの画面に表示する手順を解説します。
Tapoシリーズのネットワークカメラは、映像をスマホアプリで閲覧するのが公式の方法のようですが、仕様外の機能でRTSPのプロトコルを開放しているため自力で設定をすればパソコンでも表示できるようになっています。私の環境で使っているルーターの関係でルーター側の設定が少しトリッキーでしたが、手順自体はとても簡単です。

今回使用した機器や環境は以下の通りです。

Network camera: Tapo C310
Router: docomo home5g
PC: MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
OS: MacOS Monterey (version12.2.1)
Python version: 3.11.0
Package Manager: poetry

なお、本手順でご紹介するルーター側の設定方法は非公式の方法となります。本手順を実施することにより発生した事象については一切の責任を負いかねますのでご了承ください。

RTSP(Real Time Streaming Protocol)とは?

RTSPとは、TCP/IPネットワーク上で音声や動画などのストリーミング伝送を行うための制御データの送受信をするプロトコル(通信手順)の一つ。IETFによって1998年にRFC 2326として標準化された。
引用: https://e-words.jp/w/RTSP.html

簡単に言えばリアルタイムで動画を送ったり受け取ったりするためのプロトコルの1つです。リアルタイム通信のための技術についてはこちらがわかりやすかったです。

構成

今回の構成は以下の通りです。

作業手順

手順は以下のステップで構成されます。

  1. ネットワークカメラの設定
  2. ルーターのポートマッピング設定
  3. 動画表示用スクリプト準備
  4. 仮想環境準備 / スクリプトの実行

1. ネットワークカメラの設定

このステップでは以下を行います。

  • ネットワークカメラを起動
  • ユーザーの作成

まずはネットワークカメラを電源につないで起動し、スマートフォンのアプリをインストールしてwifiに接続します。アプリはiOS用もandroid用もあるのでどちらでも設定できます。
こちらのステップ1を参考に、アカウントを作成します。
ここで作成したアカウントは後ほどネットワークカメラへの接続の際にRTSPアドレスを指定するために使用します。

2. ルーターのポートマッピング設定

RTSP通信は、標準で554番ポートが使われます。そのため、ルーターが554番ポート宛ての通信をネットワークカメラへルーティングしてくれるようにポートマッピングの設定をする必要があります。
今回使用するdocomo home5Gは、ユーザーが公式の設定画面からポートマッピングを設定できるようにはなっておらず、下記のアドレスを直接指定して開くことのできる隠し設定ページから設定する必要があります。

上記リンクをブラウザで直接指定して隠し設定ページを開き、ルールを追加をクリックします。

こちらの手順でネットワークカメラに割り当てられているプライベートIPアドレスを確認します。私の環境では192.168.128.192が割り当てられていました。
続いて、554番ポートの通信をネットワークカメラのIPアドレスにルーティングするよう、以下の通り設定を行います。

以下の通り表示されていればルーターの設定は完了です。

3. 動画表示用のスクリプト準備

今回はこちらのサイトのスクリプトを参考にさせていただきました。

適当な名前でフォルダを作成し、フォルダ内に以下の内容でcamera.pyというファイルを作成します。自分の環境に合わせて以下のuser_id, user_pw, hostを書き換えます。

import cv2

##### 手動で変更が必要な箇所 #####
user_id = "user" # 手順1で作成したアカウントのユーザIDを指定
user_pw = "password" # 手順1で作成したアカウントのパスワードを指定
host = "192.168.128.192" # ネットワークカメラに割り当てられているIPアドレスを指定
###############################
winname = "VIDEO"

cap = cv2.VideoCapture(f"rtsp://{user_id}:{user_pw}@{host}/stream1")

windowInitialized = False

BackendError = type('BackendError', (Exception,), {})


def IsWindowVisible(winname):
    try:
        ret = cv2.getWindowProperty(winname, cv2.WND_PROP_VISIBLE)
        if ret == -1:
            raise BackendError(
                'Use Qt as backend to check whether window is visible or not.'
            )

        return bool(ret)

    except cv2.error:
        return False


while True:
    try:
        ret, frame = cap.read()
        if ret == True:
            # Please modify the value to fit your PC screen size.
            frame2 = cv2.resize(frame, (1280, 720))
            # Display video.
            cv2.imshow(winname, frame2)

            if windowInitialized==False:
                # Specify window position only once at startup.
                cv2.moveWindow(winname, 100, 100)
                windowInitialized = True

        # Press the "q" key to finish.
        k = cv2.waitKey(1) & 0xff   # necessary to display the video by imshow ()
        if k == ord("q"):
            break

        # Exit the program if there is no specified window.
        if not IsWindowVisible(winname):
            break

    except KeyboardInterrupt:
        # Press '[ctrl] + [c]' on the console to exit the program.
        print("KeyboardInterrupt")
        break

cap.release()
cv2.destroyAllWindows()

4. 仮想環境準備 / スクリプトの実行

上記のスクリプトを実行するため仮想環境を作成します。
個別でインストールが必要なライブラリはopencvだけです。

poetry init
poetry add opencv-python

続いて、作成したスクリプトを実行します。

poetry run python camera.py

ネットワークカメラの映像が表示されました。

ウィンドウを閉じるには「Ctrl+C」で停止することができます。

参考文献

https://djczzz.naturum.ne.jp/e3457503.html
https://i-pro-corp.github.io/Programing-Items/index.html?contentsUrl=https://i-pro-corp.github.io/Programing-Items/Python/connect_camera/connect_with_rtsp.html
https://www.tp-link.com/jp/support/faq/2680/

Discussion