import asyncio import os from datetime import datetime from pathlib import Path import cv2 from aiohttp import ClientSession from blinkpy.blinkpy import Blink from blinkpy.auth import Auth class BlinkRecorder: def __init__(self, save_path: str): self.save_path = Path(save_path) self.blink: Blink | None = None self.recording = False async def setup(self) -> None: self.blink = Blink(session=ClientSession()) auth = Auth({"username": os.getenv("BLINK_USERNAME"), "password": os.getenv("BLINK_PASSWORD")}) self.blink.auth = auth await self.blink.start() async def start_continuous_recording(self) -> None: if not self.blink: return self.recording = True tasks = [] for name, camera in self.blink.cameras.items(): camera_folder = self.save_path / name camera_folder.mkdir(parents=True, exist_ok=True) tasks.append(asyncio.create_task( self.record_camera(camera, camera_folder) )) await asyncio.gather(*tasks) async def record_camera(self, camera, save_path: Path) -> None: while self.recording: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") video_path = save_path / f"{timestamp}.mp4" stream_url = await camera.get_rtsp_stream() cap = cv2.VideoCapture(stream_url) fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter( str(video_path), fourcc, 30.0, (1920, 1080) ) start_time = datetime.now() try: while (datetime.now() - start_time).seconds < 3600: if not self.recording: break ret, frame = cap.read() if ret: out.write(frame) await asyncio.sleep(0.033) finally: cap.release() out.release() async def main(): recordings_path = Path("/mnt/external_hd/blink_recordings") recorder = BlinkRecorder(save_path=str(recordings_path)) await recorder.setup() try: await recorder.start_continuous_recording() except Exception as err: print(f"Error occurred: {err}") finally: recorder.recording = False if __name__ == "__main__": asyncio.run(main())