やり方はいろいろあると思いますが、OpenCV を使えば簡単にできました。
画像を取得して表示
VideoCapture
の引数に RTSP の URL を記述するだけで簡単に画像を取得できます。
URL はネットワークカメラの仕様を確認してください。
今回は Panasonic のカメラを使いました。
import cv2
user_id = "admin"
user_pw = "password"
host = "192.168.0.1"
cap = cv2.VideoCapture(f"rtsp://{user_id}:{user_pw}@{host}/MediaInput/h264")
while(True):
try:
ret, frame = cap.read()
if ret == True:
cv2.imshow('VIDEO', frame)
cv2.waitKey(1)
except KeyboardInterrupt:
print("KeyboardInterrupt")
break
cap.release()
cv2.destroyAllWindows()
VideoCapture の引数を変更すれば、USB カメラや動画ファイルの読み込み、連番のJPGファイルも一括で読み込めたりするので便利です。
保存
今回 RTSP では H.264 で取得しましたが、フレームの処理は OpenCV 側で上手く処理してくれているので、キーフレームとか GOP とか何も考えずに保存できます。
JPG の保存
cv2.imwrite("sample.jpg", frame)
動画の保存
VideoWriter_fourcc
でコーデックを指定します。
以下が参考になりました。
画像サイズはキャプチャから取得できる値をそのまま保存時にも使っていますが、フレームレートは取得できないので、直接指定しています。
これが合っていないと当然おかしなことになります(早送り再生やスロー再生したような状態になります)。
import cv2
user_id = "admin"
user_pw = "password"
host = "192.168.0.1"
cap = cv2.VideoCapture(f"rtsp://{user_id}:{user_pw}@{host}/MediaInput/h264")
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fmt = cv2.VideoWriter_fourcc(*'MP4V')
frame_rate = 30.0
writer = cv2.VideoWriter("sample.mp4", fmt, frame_rate, (int(width), int(height)))
while(True):
try:
ret, frame = cap.read()
if ret == True:
writer.write(frame)
cv2.imshow('VIDEO', frame)
cv2.waitKey(1)
except KeyboardInterrupt:
print("KeyboardInterrupt")
break
writer.release()
cap.release()
cv2.destroyAllWindows()