GithubHelp home page GithubHelp logo

kerberos-io / agent Goto Github PK

View Code? Open in Web Editor NEW
618.0 16.0 73.0 29.06 MB

An open and scalable video surveillance system for anyone making this world a better and more peaceful place.

Home Page: https://kerberos.io

License: MIT License

Dockerfile 0.24% Go 89.68% HTML 0.11% Shell 0.02% JavaScript 9.01% SCSS 0.84% CSS 0.04% HCL 0.06%
videosurveillance golang react ipcamera video-surveillance motiondetection motiondetector docker

agent's Introduction

Kerberos Agent

Kerberos Agent Kerberos Agent

PkgGoDev Coverage Status Coverage Status

License: MIT donate Twitter Widget Discord Shield kerberosio

Docker Hub | Documentation | Website | View Demo

Kerberos Agent is an isolated and scalable video (surveillance) management agent made available as Open Source under the MIT License. This means that all the source code is available for you or your company, and you can use, transform and distribute the source code; as long you keep a reference of the original license. Kerberos Agent can be used for commercial usage (which was not the case for v2). Read more about the license here.

Kerberos Agent go through UI

🤔 Prerequisites

  • An IP camera which supports a RTSP H264 or H265 encoded stream,
  • Any hardware (ARMv6, ARMv7, ARM64, AMD64) that can run a binary or container, for example: a Raspberry Pi, NVidia Jetson, Intel NUC, a VM, Bare metal machine or a full blown Kubernetes cluster.

📹 Is my camera working?

There are a myriad of cameras out there (USB, IP and other cameras), and it might be daunting to know if Kerberos Agent will work for your camera. Therefore we are listing all the camera models that are acknowlegded by the community. Feel free to add your camera to the list as well!

📚 Overview

Up and running in no time

  1. Quickstart - Docker
  2. Quickstart - Balena
  3. Quickstart - Snap

Introduction

  1. A world of Kerberos Agents

Running and automation

  1. How to run and deploy a Kerberos Agent
  2. Access the Kerberos Agent
  3. Configure and persist with volume mounts
  4. Configure with environment variables

Insights

  1. Encryption
  2. H264 vs H265

Contributing

  1. Contribute with Codespaces
  2. Develop and build
  3. Building from source
  4. Building for Docker

Varia

  1. Support our project
  2. What is new?
  3. Contributors

Quickstart - Docker

The easiest to get your Kerberos Agent up and running is to use our public image on Docker hub. Once you have selected a specific tag, run below docker command, which will open the web interface of your Kerberos agent on port 80, and off you go. For a more configurable and persistent deployment have a look at Running and automating a Kerberos Agent.

docker run -p 80:80 --name mycamera -d --restart=always kerberos/agent:latest

If you want to connect to an USB or Raspberry Pi camera, you'll need to run our side car container which proxy the camera to an RTSP stream. In that case you'll want to configure the Kerberos Agent container to run in the host network, so it can connect directly to the RTSP sidecar.

docker run --network=host --name mycamera -d --restart=always kerberos/agent:latest

Quickstart - Balena

Run Kerberos Agent with Balena Cloud super powers. Monitor your Kerberos Agent with seamless remote access, over the air updates, an encrypted public https endpoint and many more. Checkout our application video-surveillance on Balena Hub, and create your first or fleet of Kerberos Agent(s).

deploy with balena

Quickstart - Snap

Run Kerberos Agent with our Snapcraft package.

 snap install kerberosio

Once installed you can find your Kerberos Agent configration at /var/snap/kerberosio/common. Run the Kerberos Agent as following

sudo kerberosio.agent -action=run -port=80

A world of Kerberos Agents

The Kerberos Agent is an isolated and scalable video (surveillance) management agent with a strong focus on user experience, scalability, resilience, extension and integration. Next to the Kerberos Agent, Kerberos.io provides many other tools such as Kerberos Factory, Kerberos Vault and Kerberos Hub to provide additional capabilities: bring your own cloud, bring your own storage, central overview, live streaming, machine learning etc.

As mentioned above Kerberos.io applies the concept of agents. An agent is running next to (or on) your camera, and is processing a single camera feed. It applies motion based or continuous recording and make those recordings available through a user friendly web interface. A Kerberos Agent allows you to connect to other cloud services or integrates with custom applications. Kerberos Agent is used for personal usage and scales to enterprise production level deployments.

This repository contains everything you'll need to know about our core product, Kerberos Agent. Below you'll find a brief list of features and functions.

  • Low memory and CPU usage.
  • Simplified and modern user interface.
  • Multi architecture (ARMv6, ARMv7, ARM64, AMD64)
  • Multi stream, for example recording in H265, live streaming and motion detection in H264.
  • Multi camera support: IP Cameras (H264 and H265), USB cameras and Raspberry Pi Cameras through a RTSP proxy.
  • Single camera per instance (e.g. one container per camera).
  • Low resolution streaming through MQTT and high resolution streaming through WebRTC (only supports H264/PCM).
  • Backchannel audio from Kerberos Hub to IP camera (requires PCM ULAW codec)
  • Audio (AAC) and video (H264/H265) recording in MP4 container.
  • End-to-end encryption through MQTT using RSA and AES (livestreaming, ONVIF, remote configuration, etc)
  • Conditional recording: offline mode, motion region, time table, continuous recording, webhook condition etc.
  • Post- and pre-recording for motion detection.
  • Encryption at rest using AES-256-CBC.
  • Ability to create fragmented recordings, and streaming through HLS fMP4.
  • Deploy where you want with the tools you use: docker, docker compose, ansible, terraform, kubernetes, etc.
  • Cloud storage/persistance: Kerberos Hub, Kerberos Vault and Dropbox. (WIP: Minio, Storj, Google Drive, FTP etc.)
  • Outputs: trigger an integration (Webhooks, MQTT, Script, etc) when a specific event (motion detection or start recording ) occurs
  • REST API access and documentation through Swagger (trigger recording, update configuration, etc).
  • MIT License

How to run and deploy a Kerberos Agent

As described before a Kerberos Agent is a container, which can be deployed through various ways and automation tools such as docker, docker compose, kubernetes and the list goes on. To simplify your life we have come with concrete and working examples of deployments to help you speed up your Kerberos.io journey.

We have documented the different deployment models in the deployments directory of this repository. There you'll learn and find how to deploy using:

By default your Kerberos Agents will store all its configuration and recordings inside the container. To help you automate and have a more consistent data governance, you can attach volumes to configure and persist data of your Kerberos Agents, and/or configure each Kerberos Agent through environment variables.

Access the Kerberos Agent

Once you have deployed the Kerberos Agent, using one of the deployment models described above, you will be able to access the Kerberos Agent user interface. A login page is presented asking for some credentials.

The default username and password for the Kerberos Agent is:

  • Username: root
  • Password: root

Please note that you change the username and password for a final installation, see Configure with environment variables below.

Configure and persist with volume mounts

An example of how to mount a host directory is shown below using docker, but is applicable for all the deployment models and tools described above.

You attach a volume to your container by leveraging the -v option. To mount your own configuration file and recordings folder, execute as following:

docker run -p 80:80 --name mycamera \
-v $(pwd)/agent/config:/home/agent/data/config \
-v $(pwd)/agent/recordings:/home/agent/data/recordings \
-d --restart=always kerberos/agent:latest

More example can be found in the deployment section for each deployment and automation tool. Please note to verify the permissions of the directory/volume you are attaching. More information in this issue.

chmod -R 755 kerberos-agent/
chown 100:101 kerberos-agent/ -R

Configure with environment variables

Next to attaching the configuration file, it is also possible to override the configuration with environment variables. This makes deployments easier when leveraging docker compose or kubernetes deployments much easier and scalable. Using this approach we simplify automation through ansible and terraform.

docker run -p 80:80 --name mycamera \
-e AGENT_NAME=mycamera \
-e AGENT_TIMEZONE=Europe/Brussels \
-e AGENT_CAPTURE_IPCAMERA_RTSP=rtsp://fake.kerberos.io/stream \
-e AGENT_CAPTURE_CONTINUOUS=true \
-d --restart=always kerberos/agent:latest
Name Description Default Value
LOG_LEVEL Level for logging, could be "info", "warning", "debug", "error" or "fatal". "info"
LOG_OUTPUT Logging output format "json" or "text". "text"
AGENT_MODE You can choose to run this in 'release' for production, and or 'demo' for showcasing. "release"
AGENT_TLS_INSECURE Specify if you want to use InsecureSkipVerify for the internal HTTP client. "false"
AGENT_USERNAME The username used to authenticate against the Kerberos Agent login page. "root"
AGENT_PASSWORD The password used to authenticate against the Kerberos Agent login page. "root"
AGENT_KEY A unique identifier for your Kerberos Agent, this is auto-generated but can be overriden. ""
AGENT_NAME The agent friendly-name. "agent"
AGENT_TIMEZONE Timezone which is used for converting time. "Africa/Ceuta"
AGENT_REMOVE_AFTER_UPLOAD When enabled, recordings uploaded successfully to a storage will be removed from disk. "true"
AGENT_OFFLINE Makes sure no external connection is made. "false"
AGENT_AUTO_CLEAN Cleans up the recordings directory. "true"
AGENT_AUTO_CLEAN_MAX_SIZE If AUTO_CLEAN enabled, set the max size of the recordings directory in (MB). "100"
AGENT_TIME Enable the timetable for Kerberos Agent "false"
AGENT_TIMETABLE A (weekly) time table to specify when to make recordings "start1,end1,start2,end2;start1.. ""
AGENT_REGION_POLYGON A single polygon set for motion detection: "x1,y1;x2,y2;x3,y3;... ""
AGENT_CAPTURE_IPCAMERA_RTSP Full-HD RTSP endpoint to the camera you're targetting. ""
AGENT_CAPTURE_IPCAMERA_SUB_RTSP Sub-stream RTSP endpoint used for livestreaming (WebRTC). ""
AGENT_CAPTURE_IPCAMERA_ONVIF Mark as a compliant ONVIF device. ""
AGENT_CAPTURE_IPCAMERA_ONVIF_XADDR ONVIF endpoint/address running on the camera. ""
AGENT_CAPTURE_IPCAMERA_ONVIF_USERNAME ONVIF username to authenticate against. ""
AGENT_CAPTURE_IPCAMERA_ONVIF_PASSWORD ONVIF password to authenticate against. ""
AGENT_CAPTURE_MOTION Toggle for enabling or disabling motion. "true"
AGENT_CAPTURE_LIVEVIEW Toggle for enabling or disabling liveview. "true"
AGENT_CAPTURE_SNAPSHOTS Toggle for enabling or disabling snapshot generation. "true"
AGENT_CAPTURE_RECORDING Toggle for enabling making recordings. "true"
AGENT_CAPTURE_CONTINUOUS Toggle for enabling continuous "true" or motion "false". "false"
AGENT_CAPTURE_PRERECORDING If CONTINUOUS set to false, specify the recording time (seconds) before after motion event. "10"
AGENT_CAPTURE_POSTRECORDING If CONTINUOUS set to false, specify the recording time (seconds) after motion event. "20"
AGENT_CAPTURE_MAXLENGTH The maximum length of a single recording (seconds). "30"
AGENT_CAPTURE_PIXEL_CHANGE If CONTINUOUS set to false, the number of pixel require to change before motion triggers. "150"
AGENT_CAPTURE_FRAGMENTED Set the format of the recorded MP4 to fragmented (suitable for HLS). "false"
AGENT_CAPTURE_FRAGMENTED_DURATION If AGENT_CAPTURE_FRAGMENTED set to true, define the duration (seconds) of a fragment. "8"
AGENT_MQTT_URI A MQTT broker endpoint that is used for bi-directional communication (live view, onvif, etc) "tcp://mqtt.kerberos.io:1883"
AGENT_MQTT_USERNAME Username of the MQTT broker. ""
AGENT_MQTT_PASSWORD Password of the MQTT broker. ""
AGENT_STUN_URI When using WebRTC, you'll need to provide a STUN server. "stun:turn.kerberos.io:8443"
AGENT_FORCE_TURN Force using a TURN server, by generating relay candidates only. "false"
AGENT_TURN_URI When using WebRTC, you'll need to provide a TURN server. "turn:turn.kerberos.io:8443"
AGENT_TURN_USERNAME TURN username used for WebRTC. "username1"
AGENT_TURN_PASSWORD TURN password used for WebRTC. "password1"
AGENT_CLOUD Store recordings in Kerberos Hub (s3), Kerberos Vault (kstorage) or Dropbox (dropbox). "s3"
AGENT_HUB_ENCRYPTION Turning on/off encryption of traffic from your Kerberos Agent to Kerberos Hub. "true"
AGENT_HUB_URI The Kerberos Hub API, defaults to our Kerberos Hub SAAS. "https://api.hub.domain.com"
AGENT_HUB_KEY The access key linked to your account in Kerberos Hub. ""
AGENT_HUB_PRIVATE_KEY The secret access key linked to your account in Kerberos Hub. ""
AGENT_HUB_REGION The Kerberos Hub region, to which you want to upload. ""
AGENT_HUB_SITE The site ID of a site you've created in your Kerberos Hub account. ""
AGENT_KERBEROSVAULT_URI The Kerberos Vault API url. "https://vault.domain.com/api"
AGENT_KERBEROSVAULT_ACCESS_KEY The access key of a Kerberos Vault account. ""
AGENT_KERBEROSVAULT_SECRET_KEY The secret key of a Kerberos Vault account. ""
AGENT_KERBEROSVAULT_PROVIDER A Kerberos Vault provider you have created (optional). ""
AGENT_KERBEROSVAULT_DIRECTORY The directory, in the provider, where the recordings will be stored in. ""
AGENT_DROPBOX_ACCESS_TOKEN The Access Token from your Dropbox app, that is used to leverage the Dropbox SDK. ""
AGENT_DROPBOX_DIRECTORY The directory, in the provider, where the recordings will be stored in. ""
AGENT_ENCRYPTION Enable 'true' or disable 'false' end-to-end encryption for MQTT messages. "false"
AGENT_ENCRYPTION_RECORDINGS Enable 'true' or disable 'false' end-to-end encryption for recordings. "false"
AGENT_ENCRYPTION_FINGERPRINT The fingerprint of the keypair (public/private keys), so you know which one to use. ""
AGENT_ENCRYPTION_PRIVATE_KEY The private key (assymetric/RSA) to decryptand sign requests send over MQTT. ""
AGENT_ENCRYPTION_SYMMETRIC_KEY The symmetric key (AES) to encrypt and decrypt request send over MQTT. ""

Encryption

You can encrypt your recordings and outgoing MQTT messages with your own AES and RSA keys by enabling the encryption settings. Once enabled all your recordings will be encrypted using AES-256-CBC and your symmetric key. You can either use the default openssl toolchain to decrypt the recordings with your AES key, as following:

openssl aes-256-cbc -d -md md5 -in encrypted.mp4 -out decrypted.mp4 -k your-key-96ab185xxxxxxxcxxxxxxxx6a59c62e8

, and additionally you can decrypt a folder of recordings, using the Kerberos Agent binary as following:

go run main.go -action decrypt ./data/recordings your-key-96ab185xxxxxxxcxxxxxxxx6a59c62e8

or for a single file:

go run main.go -action decrypt ./data/recordings/video.mp4 your-key-96ab185xxxxxxxcxxxxxxxx6a59c62e8

H264 vs H265

If we talk about video encoders and decoders (codecs) there are 2 major video codecs on the market: H264 and H265. Taking into account your use case, you might use one over the other. We will provide an (not complete) overview of the advantages and disadvantages of each codec in the field of video surveillance and video analytics. If you would like to know more, you should look for additional resources on the internet (or if you like to read physical items, books still exists nowadays).

  • H264 (also known as AVC or MPEG-4 Part 10)

    • Is the most common one and most widely supported for IP cameras.
    • Supported in the majority of browsers, operating system and third-party applications.
    • Can be embedded in commercial and 3rd party applications.
    • Different levels of compression (high, medium, low, ..)
    • Better quality / compression ratio, shows less artifacts at medium compression ratios.
    • Does support technologies such as WebRTC
  • H265 (also known as HEVC)

    • Is not supported on legacy cameras, though becoming rapidly available on "newer" IP cameras.
    • Might not always be supported due to licensing. For example not supported in browers on a Linux distro.
    • Requires licensing when embedding in a commercial product (be careful).
    • Higher levels of compression (50% more than H264).
    • H265 shows artifacts in motion based environments (which is less with H264).
    • Recording the same video (resolution, duration and FPS) in H264 and H265 will result in approx 50% the file size.
    • Not supported in technologies such as WebRTC

Conclusion: depending on the use case you might choose one over the other, and you can use both at the same time. For example you can use H264 (main stream) for livestreaming, and H265 (sub stream) for recording. If you wish to play recordings in a cross-platform and cross-browser environment, you might opt for H264 for better support.

Contribute with Codespaces

One of the major blockers for letting you contribute to an Open Source project is to setup your local development machine. Why? Because you might have already some tools and libraries installed that are used for other projects, and the libraries you would need for Kerberos Agent, for example FFmpeg, might require a different version. Welcome to the dependency hell..

By leveraging codespaces, which the Kerberos Agent repo supports, you will be able to setup the required development environment in a few minutes. By opening the <> Code tab on the top of the page, you will be able to create a codespace, using the Kerberos Devcontainer base image. This image requires all the relevant dependencies: FFmpeg, OpenCV, Golang, Node, Yarn, etc.

Kerberos Agent codespace

After a few minutes, you will see a beautiful Visual Studio Code shown in your browser, and you are ready to code!

Kerberos Agent VSCode

On opening of the GitHub Codespace, some dependencies will be installed. Once this is done go ahead to the ui/src/config.json file, and (un)comment following section. Make sure to replace the externalHost variable with the DNS name you will retrieve from the next step.

// Uncomment this when using codespaces or other special DNS names (which you can't control)
// replace this with the DNS name of the kerberos agent server (the codespace url)
const externalHost = 'cedricve-automatic-computing-machine-v647rxvj4whx9qp-80.preview.app.github.dev';

const dev = {
  ENV: 'dev',
  HOSTNAME: externalHost,
  //API_URL: `${protocol}//${hostname}:80/api`,
  //URL: `${protocol}//${hostname}:80`,
  //WS_URL: `${websocketprotocol}//${hostname}:80/ws`,

  // Uncomment, and comment the above lines, when using codespaces or other special DNS names (which you can't control)
  API_URL: `${protocol}//${externalHost}/api`,
  URL: `${protocol}//${externalHost}`,
  WS_URL: `${websocketprotocol}//${externalHost}/ws`,
};

Go and open two terminals one for the ui project and one for the machinery project.

  1. Terminal A:

    cd machinery/
    go run main.go -action run -port 80
    
  2. Terminal B:

    cd ui/
    yarn start
    

Once executed, a popup will show up mentioning portforwarding. You should see two ports being opened, one for the ui 3000 and one for the machinery 80. Right-click on the port 80 and change visibility from private to public, this is required to avoid CORS errors.

Codespace make public

As mentioned above, copy the hostname of the machinery DNS name, and past it in the ui/src/config.json file. Once done reload, the ui page in your browser, and you should be able to access the login page with the default credentials root and root.

Develop and build

Kerberos Agent is divided in two parts a machinery and web. Both parts live in this repository in their relative folders. For development or running the application on your local machine, you have to run both the machinery and the web as described below. When running in production everything is shipped as only one artifact, read more about this at Building for production.

UI

The web is a React project which is the main entry point for an end user to view recordings, a livestream, and modify the configuration of the machinery.

git clone https://github.com/kerberos-io/agent
cd ui
yarn start

This will start a webserver and launches the web app on port 3000.

login-agent

Once signed in you'll see the dashboard page showing up. After successfull configuration of your agent, you'll should see a live view and possible events recorded to disk.

dashboard-agent

Machinery

The machinery is a Golang project which delivers two functions: it acts as the Kerberos Agent which is doing all the heavy lifting with camera processing and other kinds of logic, on the other hand it acts as a webserver (Rest API) that allows communication from the web (React) or any other custom application. The API is documented using swagger.

You can simply run the machinery using following commands.

git clone https://github.com/kerberos-io/agent
cd machinery
go run main.go -action run -port 80

This will launch the Kerberos Agent and run a webserver on port 80. You can change the port by your own preference. We strongly support the usage of Goland or Visual Studio Code, as it comes with all the debugging and linting features builtin.

VSCode desktop

Building from source

Running Kerberos Agent in production only require a single binary to run. Nevertheless, we have two parts, the machinery and the web, we merge them during build time. So this is what happens.

UI

To build the Kerberos Agent web app, you simply have to run the build command of yarn. This will create a build directory inside the web directory, which contains a minified version of the React application. Other than that, we also move this build directory to the machinery directory.

cd ui
yarn build

Machinery

Building the machinery is also super easy 🚀, by using go build you can create a single binary which ships it all; thank you Golang. After building you will endup with a binary called main, this is what contains everything you need to run Kerberos Agent.

Remember the build step of the web part, during build time we move the build directory to the machinery directory. Inside the machinery web server we reference the build directory. This makes it possible to just a have single web server that runs it all.

cd machinery
go build

Building for Docker

Inside the root of this agent repository, you will find a Dockerfile. This file contains the instructions for building and shipping Kerberos Agent. Important to note is that start from a prebuild base image, kerberos/base:xxx. This base image contains already a couple of tools, such as Golang, FFmpeg and OpenCV. We do this for faster compilation times.

By running the docker build command, you will create the Kerberos Agent Docker image. After building you can simply run the image as a Docker container.

docker build -t kerberos/agent .

What is new?

This repository contains the next generation of Kerberos.io, Kerberos Agent (v3), and is the successor of the machinery and web repositories. A switch in technologies and architecture has been made. This version is still under active development and can be followed on the develop branch and project overview.

Read more about this at the FAQ below.

opensource-to-agent

Contributors

This project exists thanks to all the people who contribute.

agent's People

Contributors

afldt avatar andp97 avatar cedricve avatar chaitanya110703 avatar fadkeabhi avatar izzotop avatar jeffersonglemos avatar kododake avatar leospyke avatar lubikx avatar milankragujevic avatar olokos avatar teeteufel avatar thomasqp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

agent's Issues

Error when buid docker image [debian repo + eslint error]

Step to reproduce:

Clone the repo at current master branch

docker build -t kerberos/opensource .
  1. Error on Dockerfile maybe caused by older version of debian present on FROM command:
Reading package lists...
E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
The command '/bin/sh -c apt-get update && apt-get install -y curl && curl -sL https://deb.nodesource.com/setup_14.x | bash - &&     curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - &&     echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list &&     apt update && apt install yarn -y' returned a non-zero code: 100

  1. After fixing Docker file i see this eslint error:
src/containers/RequireInstall.jsx
  Line 10:14:  Replace `⏎········isAuthenticated,⏎········isInstalled,⏎········redirectDashboard,⏎········redirectLogin,` with `·isAuthenticated,·isInstalled,·redirectDashboard,·redirectLogin·}·=`  prettier/prettier
  Line 15:7:   Replace `}·=` with `·`                                                                                                                                                                 prettier/prettier

Continuous recording: panic: runtime error: invalid memory address or nil pointer dereference

Hello,

I am trying enable "Continuous recording" but no success.
Every time I enable container crash.
I am using docker +docker compose instead of kubernetes.

docker-compose.yml

version: '3'

services:
  kerberos-agent:
    image: 'kerberos/agent-dev:arch-amd64-a67c84a'
    restart: always
    container_name: 'kerberos-camera1'
    hostname: 'kerberos-camera1'
    ports:
      - '8080'
    volumes:
      - "./agent/config:/home/agent/data/config"
      - "./agent/recordings:/home/agent/data/recordings"

    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.kerberos-camera1.rule=Host(`kerberos-camera1.domain.tld`)'
      - 'traefik.http.routers.kerberos-camera1.entrypoints=websecure'
      - 'traefik.http.routers.kerberos-camera1.tls=true'
      - 'traefik.http.routers.kerberos-camera1.tls.certresolver=leresolver'
      - 'traefik.http.services.kerberos-camera1.loadbalancer.server.port=8080'

  kerberos-vault:
    image: 'kerberos/vault:latest'
    restart: always
    container_name: 'kerberos-vault'
    hostname: 'kerberos-vault'
    ports:
      - '80'
      - '8081'
    volumes:
      - "./vault:/vault"
    environment:
      - GIN_MODE=release
      - STORAGE_API_URL=kerberos-vault-api.domain.tld
      - KERBEROS_LOGIN_USERNAME=root
      - KERBEROS_LOGIN_PASSWORD=pass
      - MONGODB_HOST=kerberos-mongo
      - MONGODB_DATABASE_CREDENTIALS=admin
      - MONGODB_USERNAME=root
      - MONGODB_PASSWORD=pass
      - MONGODB_DATABASE_STORAGE=KerberosStorage
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.kerberos-vault.rule=Host(`kerberos-vault.domain.tld`)'
      - 'traefik.http.routers.kerberos-vault.entrypoints=websecure'
      - 'traefik.http.routers.kerberos-vault.tls=true'
      - 'traefik.http.routers.kerberos-vault.tls.certresolver=leresolver'
      - "traefik.http.routers.kerberos-vault.service=kerberos_vault"
      - 'traefik.http.services.kerberos_vault.loadbalancer.server.port=80'
      - 'traefik.http.routers.kerberos-vault-api.rule=Host(`kerberos-vault-api.domain.tld`)'
      - 'traefik.http.routers.kerberos-vault-api.entrypoints=websecure'
      - 'traefik.http.routers.kerberos-vault-api.tls=true'
      - 'traefik.http.routers.kerberos-vault-api.tls.certresolver=leresolver'
      - "traefik.http.routers.kerberos-vault-api.service=kerberos_vault_api"
      - 'traefik.http.services.kerberos_vault_api.loadbalancer.server.port=8081'

  kerberos-mongo:
    image: 'mongo:4.4.16'
    container_name: 'kerberos-mongo'
    hostname: 'kerberos-mongo'
    ports:
      - 27017
    volumes:
      - ./mongodb:/data/db
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=pass

volumes:
  kerberos-data:

networks:
  default:
      name: cluster-net
      external: true

Docker Logs:

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /debug/pprof/             --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/cmdline      --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/profile      --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] POST   /debug/pprof/symbol       --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/symbol       --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/trace        --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/allocs       --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/block        --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/goroutine    --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/heap         --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/mutex        --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
[GIN-debug] GET    /debug/pprof/threadcreate --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
{"level":"info","msg":"RunAgent: opening RTSP stream","time":"2022-09-08T16:10:58+01:00"}
[GIN-debug] GET    /swagger/*any             --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (4 handlers)
[GIN-debug] GET    /config                   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func1 (4 handlers)
[GIN-debug] POST   /config                   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func2 (4 handlers)
[GIN-debug] POST   /api/login                --> github.com/appleboy/gin-jwt/v2.(*GinJWTMiddleware).LoginHandler-fm (4 handlers)
[GIN-debug] GET    /api/dashboard            --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func3 (4 handlers)
[GIN-debug] POST   /api/latest-events        --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func4 (4 handlers)
[GIN-debug] GET    /api/days                 --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func5 (4 handlers)
[GIN-debug] GET    /api/stream               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func6 (4 handlers)
[GIN-debug] GET    /api/config               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func7 (4 handlers)
[GIN-debug] POST   /api/config               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func8 (4 handlers)
[GIN-debug] GET    /api/restart              --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func9 (4 handlers)
[GIN-debug] GET    /api/stop                 --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func10 (4 handlers)
[GIN-debug] POST   /api/hub/verify           --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func11 (4 handlers)
[GIN-debug] POST   /api/persistence/verify   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func12 (4 handlers)
[GIN-debug] GET    /file/*filepath           --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (9 handlers)
[GIN-debug] HEAD   /file/*filepath           --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (9 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8080
{"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-09-08T16:10:58+01:00"}
{"level":"info","msg":"ConfigureMQTT: Set broker uri ","time":"2022-09-08T16:10:59+01:00"}
{"level":"info","msg":"ConfigureMQTT: Set username xxx","time":"2022-09-08T16:10:59+01:00"}
{"level":"info","msg":"ConfigureMQTT: Set password xxx","time":"2022-09-08T16:10:59+01:00"}
{"level":"error","msg":"HandleHeartBeat: (400) Something went wrong while sending to Kerberos Hub.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"HandleLiveStreamHD: Waiting for peer connections.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"HandleRecordStream: Start continuous recording ","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"WriteToTrack: listing codecs.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"WriteToTrack: codec - H264 found.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"H264","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"WriteToTrack: codec - PCM_ALAW found.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"PCM_ALAW","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"WriteToTrack: not using a transcoder.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"ProcessMotion: Continuous recording, so no motion detection.","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"HandleStream: packet size 176627","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"Recording started","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"HandleRecordStream: composing recording","time":"2022-09-08T16:11:02+01:00"}
{"level":"info","msg":"HandleRecordStream: write header","time":"2022-09-08T16:11:02+01:00"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x6196a0]

goroutine 30 [running]:
github.com/kerberos-io/joy4/format/mp4.(*Muxer).WriteHeader(0xc000034050?, {0xc00046eaa0?, 0x242?, 0xc00041eec0?})
        /go/pkg/mod/github.com/kerberos-io/[email protected]/format/mp4/muxer.go:154 +0x20
github.com/kerberos-io/agent/machinery/src/capture.HandleRecordStream(0xc00003c620?, 0xc0001e6000, 0xc0005d6070, {0xc00046eaa0, 0x2, 0x2})
        /go/src/github.com/kerberos-io/agent/machinery/src/capture/main.go:194 +0x18fb
created by github.com/kerberos-io/agent/machinery/src/components.RunAgent
        /go/src/github.com/kerberos-io/agent/machinery/src/components/Kerberos.go:125 +0x8ef

Please, can you help figure out?

Feature request: Multiple-level asymmetric encryption

Nice to have such a feature, in the cunning times we live, for the (compressed) raw recording; for example:

  • owner's key (individual, company)
  • security company's key
  • recognised state authority's (police, notary/conveyancer/scrivener, etc) key

panic: invalid memory pointer on nil pointer dereference after #39

image

{"level":"info","msg":"FindMotion: Number of changes detected:9455","time":"2022-08-18T12:17:22+02:00"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x227a00]

goroutine 66 [running]:
github.com/kerberos-io/joy4/format/mp4.(*Muxer).WriteHeader(0x0, {0x24101b0, 0x1, 0x1})
        /go/pkg/mod/github.com/kerberos-io/[email protected]/format/mp4/muxer.go:154 +0x18
github.com/kerberos-io/agent/machinery/src/capture.HandleRecordStream(0x24a6910, 0x273ec00, 0x2700360, {0x24101b0, 0x1, 0x1})
        /go/src/github.com/kerberos-io/agent/machinery/src/capture/main.go:256 +0x6f4
created by github.com/kerberos-io/agent/machinery/src/components.RunAgent
        /go/src/github.com/kerberos-io/agent/machinery/src/components/Kerberos.go:109 +0x974

Last night it was pitch black when I was working on this, so there was nothing to detect, but now I came to dead docker container, with the reason behind it listed above.

The screenshot and the text logs are exactly the same, just provided them in both forms, so ez copy paste and easy to read at the same time, thanks to colors on ss.

I will investigate this, but it's related to joy4, which I noticed that @thomasqp did write a comment on top of some of the files that it needs to be updated/changed, I'm not sure myself, but I will look into this.

Translation web UI (additional languages)

We are currently translating the Kerberos Agent UI. Find a list of the translations we are currently focusing on, feel free to add more languages if you are willing to contribute.

Languages can be found in the public folder. If your language is missing, create a new directory with the language 2 letter code, copy the translation.json file from the en folder, and start translating.

Initiate Backend

Initiate Golang backend project, setting up the scene (Docker, Github CI)

Docker build bug - package list out of date

Hi!

When running the Docker build, I happened to get this problem:

After this operation, 410 kB of additional disk space will be used.
Ign:1 http://deb.debian.org/debian buster/main amd64 curl amd64 7.64.0-4+deb10u1
Err:1 http://deb.debian.org/debian buster/main amd64 curl amd64 7.64.0-4+deb10u1
  404  Not Found [IP: 151.101.18.132 80]
E: Failed to fetch http://security.debian.org/debian-security/pool/updates/main/c/curl/curl_7.64.0-4+deb10u1_amd64.deb  404  Not Found [IP: 151.101.18.132 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
The command '/bin/sh -c apt-get install curl && curl -sL https://deb.nodesource.com/setup_14.x | bash - &&     curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - &&     echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list &&     apt update && apt install yarn -y' returned a non-zero code: 100

Fix is very easy - add apt-get update to line 19.

It should look likes this:

RUN apt-get update && apt-get install -y curl && curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt update && apt install yarn -y

Note I set it to apt-get install -y curl, as there is also this issue:

49 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libcurl4
The following NEW packages will be installed:
  curl
The following packages will be upgraded:
  libcurl4
1 upgraded, 1 newly installed, 0 to remove and 48 not upgraded.
Need to get 597 kB of archives.
After this operation, 412 kB of additional disk space will be used.
Do you want to continue? [Y/n] Abort.
The command '/bin/sh -c apt update && apt-get install curl && curl -sL https://deb.nodesource.com/setup_14.x | bash - &&     curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - &&     echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list &&     apt update && apt install yarn -y' returned a non-zero code: 1

RTSP H265 support

I'm still using the Kerberos.IO Machinery interface for my video cameras because it supports h265 streams and agent does not yet. With more and more cameras going to 4k with h265, when can we expect support in agent for h265 streams?

Dockerfile bug can't cd to

Step to reproduce:

  • git clone
  • docker build .

Docker build fail with this error:

/bin/sh: 1: cd: can't cd to /go/src/github.com/kerberos-io/opensource/backend

Installed using Advanced Install (now unable to uninstall)

It looks I am having issues related to the advanced install procedure, that is still serving the kerberos agent application through port 8080. I am not sure how to uninstall this, and what service is serving the kerberos agent application.

I followed the installation procedure backwards, and uninstalled and rm -rf a bunch of created directories during the advanced installation process, but for some reason it is still serving the kerberos agent login at https://IP:8080. I tried systemctl stop nginx and that didn't work. It is still serving the kerberos service.

Curious how one might troubleshoot this?

Create welcome / onboarding screen

Develop the onboarding screen in react, which will guide you through the initial setup of Kerberos Open Source.

  • Language
  • Username
  • Password
  • Type of camera

Installed Kerberos on RPI4 using Docker (Machinery Not Running Issue)

I followed this guide on the Kerberos.io documentation, and for some reason the Web is Running, but the Machinery is Not Running.

https://cedricverst.medium.com/kerberos-io-on-docker-19b25fa7efd1

I am pulling in a RTSP stream, that works over VLC so I know the connection is good there. However, the RTSP stream link that I put in the IP Camera setting isn't being detected. I'm pretty sure it is due to the Machinery not running.

Curious how I go about troubleshooting the Machinery, and how to start it?

I also don't know where to find the Kerberos logs to troubleshoot.

Any help would be greatly appreciated.

Initiate Frontend

Initiate React frontend project, setting up the scene (docker, ci)

Add startup checks: data folder writeable, camera connection, etc.

Currently the Kerberos Agent doesn't give relevant information about the Kerberos Agent startup status:

  • The agent will crash, if trying to write a recording to disk, and no writing permissions where granted.
  • Validate if an internet connection can be made if not in "offline mode"
  • Proper camera working check
  • etc.

Name change

While I am excited to see how this tool compares to things like ZoneMinder, it confuses me why "kerberos" is the name that was chosen for this project. Kerberos is already an established technology. You're just going to make it harder to make a name for yourself and people are going to have problems finding answers to their questions related to this product using search engines.

Raspberry Pi Zero - ARMv6 image not available

Hi,
thanks for your wonderful product.
I've tried to install Kerberos Agent through docker and everything seems to work until I try to get to the interface. The client (firefox in my case) says it's unable to connect to the server.
I've installed the agent on a raspberry pi Zero with the latest Raspberry Pi OS lite version. I can access the pi through ssh.
the command I entered to launch the service is:
sudo docker run -p 80:80 --name kerberos0 -d kerberos/agent:latest
Maybe I must add that I've encountered this warning, maybe related:
WARNING: The requested image's platform (linux/arm/v7) does not match the detected host platform (linux/arm/v6) and no specific platform was requested

Thanks in advance.

Unable to update polygon-selection with mounted config.json

Configuration Overview

Docker Versions

$ docker --version
Docker version 20.10.21, build baeda1f
$ docker compose version
Docker Compose version v2.12.2

Preparation Steps

mkdir /srv/kerberos-agent /srv/kerberos-agent/garage-south/ /srv/kerberos-agent/garage-south/config
wget https://raw.githubusercontent.com/kerberos-io/agent/master/machinery/data/config/config.json -O /srv/kerberos-agent/garage-south/config
sudo chown 1000:1000 /srv/kerberos-agent -R
sudo chmod 777 /srv/kerberos-agent -R
mkdir /media/nvr/kerberos/garage-south /media/nvr/kerberos/garage-south/recordings /media/nvr/kerberos/garage-south/snapshots
sudo chown 1000:1000 /media/nvr/kerberos -R
sudo chmod 777 /media/nvr/kerberos -R

docker-compose.yml

version: "3.9"
networks:
  kerberos-agent-net:
    driver: bridge
    name: kerberos-agent-net
services:
  ka-garage-south:
    image: "kerberos/agent:latest"
    container_name: ka-garage-south
    hostname: ${HOSTNAME}-ka-garage-south
    networks:
      - kerberos-agent-net
    ports:
      - "80:80"
    environment:
      - AGENT_USERNAME=${AGENT_USERNAME}
      - AGENT_PASSWORD=${AGENT_PASSWORD}
    volumes:
      - ${APPDATA}/garage-south/config:/home/agent/data/config:rw
      - ${RECORDINGS}/garage-south/recordings:/home/agent/data/recordings:rw
      - ${RECORDINGS}/garage-south/snapshots:/home/agent/data/snapshots:rw
    restart: unless-stopped

.env

# Directory locations
APPDATA=/srv/kerberos-agent
RECORDINGS=/media/nvr/kerberos
# Container specifics
AGENT_USERNAME=[username]
AGENT_PASSWORD=[password]
HOSTNAME=[hostname]

config.json

{
        "type": "",
        "key": "",
        "name": "garage-south",
        "time": "true",
        "offline": "false",
        "auto_clean": "true",
        "max_directory_size": 102400,
        "timezone": "America/Edmonton",
        "capture": {
                "name": "",
                "ipcamera": {
                        "rtsp": "rtsp://[details]",
                        "sub_rtsp": "rtsp://[details]",
                        "fps": ""
                },
                "usbcamera": {
                        "device": ""
                },
                "raspicamera": {
                        "device": ""
                },
                "continuous": "true",
                "postrecording": 40,
                "prerecording": 20,
                "maxlengthrecording": 600,
                "transcodingwebrtc": "",
                "transcodingresolution": 0,
                "forwardwebrtc": "",
                "fragmented": "false",
                "fragmentedduration": 8,
                "pixelChangeThreshold": 150
        },
        "timetable": [
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                },
                {
                        "start1": 3600,
                        "end1": 43199,
                        "start2": 43200,
                        "end2": 86400
                }
        ],
        "region": {
                "name": "",
                "rectangle": {
                        "x1": 0,
                        "y1": 0,
                        "x2": 800,
                        "y2": 640
                },
                "polygon": []
        },
        "cloud": "",
        "s3": {},
        "kstorage": {},
        "mqtturi": "tcp://195.168.1.95:1883",
        "mqtt_username": "",
        "mqtt_password": "",
        "stunuri": "",
        "turnuri": "",
        "turn_username": "",
        "turn_password": "",
        "heartbeaturi": "",
        "hub_uri": "",
        "hub_key": "",
        "hub_private_key": "",
        "hub_site": "",
        "condition_uri": ""
}

Start and Verify Container

$ docker compose --file /srv/kerberos-agent/docker-compose.yml up --detach
[+] Running 2/2
 ⠿ Network kerberos-agent-net  Created                                                                                          0.1s
 ⠿ Container ka-garage-south   Started                                                                                          1.0s

$ docker exec ka-garage-south env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=[hostname]-ka-garage-south
AGENT_USERNAME=[username]
AGENT_PASSWORD=[password]
ZONEINFO=/zoneinfo.zip
HOME=/home/agent

$ docker container inspect ka-garage-south -f '{{range .Mounts}}{{.Type}}:{{.Source}}:{{.Destination}}{{println}}{{ end }}'
bind:/media/nvr/kerberos/garage-south/snapshots:/home/agent/data/snapshots
bind:/srv/kerberos-agent/garage-south/config:/home/agent/data/config
bind:/media/nvr/kerberos/garage-south/recordings:/home/agent/data/recordings

$ docker compose --file /srv/kerberos-agent/docker-compose.yml logs
ka-garage-south  | {"level":"info","msg":"Successfully Opened config.json from opensource","time":"2022-12-21T17:35:05+01:00"}
ka-garage-south  | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
ka-garage-south  |
ka-garage-south  | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
ka-garage-south  |  - using env:        export GIN_MODE=release
ka-garage-south  |  - using code:       gin.SetMode(gin.ReleaseMode)
ka-garage-south  |
ka-garage-south  | [GIN-debug] GET    /debug/pprof/             --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/cmdline      --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/profile      --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] POST   /debug/pprof/symbol       --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/symbol       --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/trace        --> github.com/gin-gonic/gin.WrapF.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/allocs       --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/block        --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/goroutine    --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/heap         --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/mutex        --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /debug/pprof/threadcreate --> github.com/gin-gonic/gin.WrapH.func1 (3 handlers)
ka-garage-south  | [GIN-debug] GET    /swagger/*any             --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /config                   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func1 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /config                   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func2 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/login                --> github.com/appleboy/gin-jwt/v2.(*GinJWTMiddleware).LoginHandler-fm (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/dashboard            --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func3 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/latest-events        --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func4 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/days                 --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func5 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/stream               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func6 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/config               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func7 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/config               --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func8 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/restart              --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func9 (4 handlers)
ka-garage-south  | [GIN-debug] GET    /api/stop                 --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func10 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/camera/verify/:streamType --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func11 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/hub/verify           --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func12 (4 handlers)
ka-garage-south  | [GIN-debug] POST   /api/persistence/verify   --> github.com/kerberos-io/agent/machinery/src/routers/http.AddRoutes.func13 (4 handlers)
ka-garage-south  | {"level":"info","msg":"RunAgent: opening RTSP stream","time":"2022-12-21T09:35:05-07:00"}
ka-garage-south  | [GIN-debug] GET    /file/*filepath           --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (9 handlers)
ka-garage-south  | [GIN-debug] HEAD   /file/*filepath           --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (9 handlers)
ka-garage-south  | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
ka-garage-south  | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
ka-garage-south  | [GIN-debug] Listening and serving HTTP on :80
ka-garage-south  | {"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-12-21T09:35:05-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: opened RTSP stream","time":"2022-12-21T09:35:06-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: opened RTSP sub stream","time":"2022-12-21T09:35:06-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: SetMaxGopCount was set with: 20","time":"2022-12-21T09:35:06-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: Creating sub stream queue with SetMaxGopCount set to 20","time":"2022-12-21T09:35:06-07:00"}
ka-garage-south  | {"level":"info","msg":"ConfigureMQTT: Set broker uri tcp://195.168.1.95:1883","time":"2022-12-21T09:35:06-07:00"}
ka-garage-south  | {"level":"info","msg":"ProcessMotion: Continuous recording, so no motion detection.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"HandleLiveStreamHD: Waiting for peer connections.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"error","msg":"HandleHeartBeat: (400) Something went wrong while sending to Kerberos Hub.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: listing codecs.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: codec - H264 found.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"H264","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: not using a transcoder.","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"HandleRecordStream: Start continuous recording ","time":"2022-12-21T09:35:09-07:00"}
ka-garage-south  | {"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-12-21T09:35:10-07:00"}
ka-garage-south  | {"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-12-21T09:35:15-07:00"}
ka-garage-south  | {"level":"info","msg":"Main: Restarting machinery.","time":"2022-12-21T09:35:15-07:00"}
ka-garage-south  | {"level":"error","msg":"HandleStream: read tcp 192.168.32.2:43006-\u003e192.168.1.83:554: use of closed network connection","time":"2022-12-21T09:35:16-07:00"}
ka-garage-south  | {"level":"error","msg":"HandleSubStream: read tcp 192.168.32.2:43018-\u003e192.168.1.83:554: use of closed network connection","time":"2022-12-21T09:35:16-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: stop writing to track.","time":"2022-12-21T09:35:16-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: waiting 3 seconds to make sure everything is properly closed.","time":"2022-12-21T09:35:16-07:00"}
ka-garage-south  | {"level":"info","msg":"Successfully Opened config.json from opensource","time":"2022-12-21T09:35:19-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: opening RTSP stream","time":"2022-12-21T09:35:19-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: opened RTSP stream","time":"2022-12-21T09:35:20-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: opened RTSP sub stream","time":"2022-12-21T09:35:20-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: SetMaxGopCount was set with: 20","time":"2022-12-21T09:35:20-07:00"}
ka-garage-south  | {"level":"info","msg":"RunAgent: Creating sub stream queue with SetMaxGopCount set to 20","time":"2022-12-21T09:35:20-07:00"}
ka-garage-south  | {"level":"info","msg":"ConfigureMQTT: Set broker uri tcp://195.168.1.95:1883","time":"2022-12-21T09:35:20-07:00"}
ka-garage-south  | {"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-12-21T09:35:22-07:00"}
ka-garage-south  | {"level":"info","msg":"ProcessMotion: Continuous recording, so no motion detection.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"HandleLiveStreamHD: Waiting for peer connections.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"HandleRecordStream: Start continuous recording ","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"error","msg":"HandleHeartBeat: (400) Something went wrong while sending to Kerberos Hub.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: listing codecs.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: codec - H264 found.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"H264","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"WriteToTrack: not using a transcoder.","time":"2022-12-21T09:35:23-07:00"}
ka-garage-south  | {"level":"info","msg":"ControlAgent: Number of packets read 0","time":"2022-12-21T09:35:27-07:00"}

Testing Process

  1. Access agent at http://[hostname]:80/
  2. Log in with [username] and [password]
  3. Validate camera feed is live
  4. Check initial settings in configuration file (note: listing only those expected to change)
        "name": "garage-south",
[...]
        "timezone": "America/Edmonton",
[...]
                "continuous": "false",
[...]
        "region": {
                "name": "",
                "rectangle": {
                        "x1": 0,
                        "y1": 0,
                        "x2": 800,
                        "y2": 640
                },
                "polygon": []
        },
  1. Edit settings as follows:
    5.1. Click Settings | Overview
    5.2. Camera Name from "garage-south" to "garage-south-two"
    5.3. Timezone from "" to "(UTC-07:00) Mountain Time (US & Canada)"
    5.4. Click Save
    5.5. Confirm message "Your configuration have been updated successfully." appears
  2. Check configuration file:
        "name": "garage-south-2",
[...]
        "timezone": "America/Boise",
  1. Edit settings as follows:
    7.1. Click Settings | Recording
    7.2. Continuous recording from "disabled" to "enabled"
    7.3. Click Save
    7.4. Confirm message "Your configuration have been updated successfully." appears
  2. Check configuration file:
                "continuous": "true",
  1. Edit settings as follows:
    9.1. Click Settings | Conditions
    9.2. In Region of Interest define a "polygon-selection" region
    9.3. Click Save
    9.4. Confirm message "Your configuration have been updated successfully." appears
  2. Check configuration file:
        "region": {
                "name": "",
                "rectangle": {
                        "x1": 0,
                        "y1": 0,
                        "x2": 800,
                        "y2": 640
                },
                "polygon": []
        },
  1. Edit settings as follows:
    11.1. Click Settings | Conditions
    11.2. In Region of Interest define a "rectangle box" region
    11.3. Click Save
    11.4. Confirm message "Your configuration have been updated successfully." appears
  2. Check configuration file:
        "region": {
                "name": "",
                "rectangle": {
                        "x1": 0,
                        "y1": 0,
                        "x2": 800,
                        "y2": 640
                },
                "polygon": [
                        {
                                "id": "1671641763618",
                                "coordinates": [
                                        {
                                                "x": 530.5807711693549,
                                                "y": 392.1292212701613
                                        },
                                        {
                                                "x": 1909.6776713709678,
                                                "y": 392.1292212701613
                                        },
                                        {
                                                "x": 1909.6776713709678,
                                                "y": 1073.4195438508063
                                        },
                                        {
                                                "x": 530.5807711693549,
                                                "y": 1073.4195438508063
                                        }
                                ]
                        }
                ]
        },

Browser Details

  • Google Chrome 108.0.5359.125 (64-bit)
  • Mozilla Firefox 108.0.1 (64-bit)

Results Summary

Test 5: ✔️ Settings
Test 7: ✔️ Recording
Test 9: ❌ Polygon
Test 11: ✔️ Rectangle

Conclusion

I tried this a few times on Firefox and Chrome, but nothing saves.

Continuous recording setting is confusing and misleading

I think the setting for "continuous recording" needs to be reworded or reworked.

Currently, it's an on/off radio toggle, but the description says "Make 24/7 or motion based recordings" without clearly indicating what the "on" or "off" positions do. Could this verbiage be clarified? I feel a radio button isn't the best UI choice for this.

Motion-based recording doesn't happen until you configure a region?

Hello, I think I found a bug.

I noticed I was having a heck of a time just trying to get the software to record when there's motion. Unchecking "continuous recording" wasn't enough to get it to start working - I had to go into the "Conditions" tab and draw a box in the "Region of Interest" settings panel to get it to start recording events. From a UX perspective, this wasn't clear and I'm not sure if it's a bug or intended behavior.

Suggestion about files removal when storage is almost full

Hi,

I like very much this project. I think it is a great one!! I plan to use it with my Home Assistant server.

One thing I noticed that I think can be improved (user experience aspect) -

I run kerberos.io on docker and suddenly witnessed all files on the capture folder being removed every 1 min or so.
It turned out that my 450GB SSD had only ~32GB free space. Once I cleaned the recycle bin (~80GB), the phenomenon disappeared.
I guess Kerberos checks free space by percentage - I suggest to do it by actual GB. 32GB are a lot of free space and should not cause such aggressive files deletion.
I also suggest to eliminate older files only. Maybe leave always the newest 50 files or so? Instead of delete them all.

thanks in advanced and cheers!

UX Improvement - Fewer clicks to review captured videos

When reviewing captured videos, the user can adjust a slider to select an hour of the day. This will immediately show videos captured early in the hour. How does the user view videos captured near the end of the hour? The user must click "Load more" multiple times and wait a bit on each load. If there are many captures, the user may need to press "Load more" 10 times. This is bad UX, in my opinion.

There are some options to improve this:

  • Show a list of all videos in the hour immediately. Don't load the thumbnails/previews eagerly. That can be loaded lazily as the user single-clicks a video (double click can open the video player).
  • Continuously load all thumbnails/previews for the hour. Don't make the user click "Load more" multiple times.
  • Allow the user to adjust the size of the interval on the slider. For example, if it were reduced to 10 or 15 minutes, the user could narrow down to the time of interest faster rather than clicking "Load more" over and over.

Also the grouping of videos is arbitrary and confusing. Why not just show a list of all videos for the hour?

Camera not showing rPi 4B 4GB RAM

The official Raspberry Pi Camera Module 2 is not showing on a Raspberry Pi 4B model its 4GB RAM, running the latest updated release of Bullseye.

What is happening on port 80?

I am running 7 Podman containers, which all stream to Kerberos Cloud.

When locking down my CCTV VLAN and firewall, I noticed that the kerberos.io containers attempt connections to the following hosts:

IP Address Protocol Port
159.65.215.225 TCP 1883
172.67.133.190 TCP 443
104.155.97.237 TCP 443
34.79.161.171 TCP 80

Now TCP Port 443 is not in question - I assume that kerberos.io containers push their streams via 443 to the above two servers. 1883 is MQTT and Port 80 is unencrypted HTTP!

My questions are as follows:

  1. Why are the containers connecting to 34.79.161.171 over port 80? What is this connection being used for?
  2. What is MQTT port 1883 being used for specifically?

FYI, I have been unable to find these answers in the documentation, faq, or list of resolved issues.

Error when I try compile Machinery

Please I need your help. I use Linux Ubuntu 20.4

When I try compile/run de machinery with "go run main.go run mycameraname 8080" like your example I got this message.

github.com/kerberos-io/joy4/cgo/ffmpeg

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libavresample.a(resample.o): undefined reference to symbol 'cos@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

github.com/kerberos-io/joy4/cgo/ffmpeg

../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go: In function ‘wrap_avcodec_decode_audio4’:
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:7:9: warning: ‘avcodec_decode_audio4’ is deprecated [-Wdeprecated-declarations]
7 | return avcodec_decode_audio4(ctx, frame, got, &pkt);
| ^~~~~~
In file included from /usr/include/x86_64-linux-gnu/libavformat/avformat.h:312,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/x86_64-linux-gnu/libavcodec/avcodec.h:3047:5: note: declared here
3047 | int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
| ^~~~~~~~~~~~~~~~~~~~~
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go: In function ‘wrap_avresample_convert’:
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:10:9: warning: ‘avresample_convert’ is deprecated [-Wdeprecated-declarations]
10 | return avresample_convert(avr, (void *)out, outsize, outcount, (void *)in, insize, incount);
| ^~~~~~
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:5,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/libavresample/avresample.h:451:5: note: declared here
451 | int avresample_convert(AVAudioResampleContext *avr, uint8_t **output,
| ^~~~~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avcodec_encode_audio2’:
cgo-gcc-prolog:153:2: warning: ‘avcodec_encode_audio2’ is deprecated [-Wdeprecated-declarations]
In file included from /usr/include/x86_64-linux-gnu/libavformat/avformat.h:312,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/x86_64-linux-gnu/libavcodec/avcodec.h:3688:5: note: declared here
3688 | int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
| ^~~~~~~~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avresample_alloc_context’:
cgo-gcc-prolog:287:2: warning: ‘avresample_alloc_context’ is deprecated [-Wdeprecated-declarations]
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:5,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/libavresample/avresample.h:194:25: note: declared here
194 | AVAudioResampleContext *avresample_alloc_context(void);
| ^~~~~~~~~~~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avresample_free’:
cgo-gcc-prolog:302:2: warning: ‘avresample_free’ is deprecated [-Wdeprecated-declarations]
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:5,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/libavresample/avresample.h:258:6: note: declared here
258 | void avresample_free(AVAudioResampleContext **avr);
| ^~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avresample_get_out_samples’:
cgo-gcc-prolog:320:2: warning: ‘avresample_get_out_samples’ is deprecated [-Wdeprecated-declarations]
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:5,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/libavresample/avresample.h:403:5: note: declared here
403 | int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avresample_open’:
cgo-gcc-prolog:339:2: warning: ‘avresample_open’ is deprecated [-Wdeprecated-declarations]
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:5,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/audio.go:4:
/usr/include/libavresample/avresample.h:214:5: note: declared here
214 | int avresample_open(AVAudioResampleContext *avr);
| ^~~~~~~~~~~~~~~

github.com/kerberos-io/joy4/cgo/ffmpeg

../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.go: In function ‘ffinit’:
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.go:7:9: warning: ‘av_register_all’ is deprecated [-Wdeprecated-declarations]
7 | av_register_all();
| ^~~~~~~~~~~~~~~
In file included from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.go:5:
/usr/include/x86_64-linux-gnu/libavformat/avformat.h:1955:6: note: declared here
1955 | void av_register_all(void);
| ^~~~~~~~~~~~~~~

github.com/kerberos-io/joy4/cgo/ffmpeg

../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go: In function ‘wrap_avcodec_decode_video2’:
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go:14:9: warning: ‘avcodec_decode_video2’ is deprecated [-Wdeprecated-declarations]
14 | return avcodec_decode_video2(ctx, frame, got, &pkt);
| ^~~~~~
In file included from /usr/include/x86_64-linux-gnu/libavformat/avformat.h:312,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go:11:
/usr/include/x86_64-linux-gnu/libavcodec/avcodec.h:3096:5: note: declared here
3096 | int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
| ^~~~~~~~~~~~~~~~~~~~~
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go: In function ‘wrap_avcodec_decode_video2_empty’:
../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go:18:9: warning: ‘avcodec_decode_video2’ is deprecated [-Wdeprecated-declarations]
18 | return avcodec_decode_video2(ctx, frame, got, &pkt);
| ^~~~~~
In file included from /usr/include/x86_64-linux-gnu/libavformat/avformat.h:312,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go:11:
/usr/include/x86_64-linux-gnu/libavcodec/avcodec.h:3096:5: note: declared here
3096 | int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
| ^~~~~~~~~~~~~~~~~~~~~
cgo-gcc-prolog: In function ‘_cgo_93cb7bf53f7a_Cfunc_avcodec_encode_video2’:
cgo-gcc-prolog:115:2: warning: ‘avcodec_encode_video2’ is deprecated [-Wdeprecated-declarations]
In file included from /usr/include/x86_64-linux-gnu/libavformat/avformat.h:312,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/ffmpeg.h:2,
from ../../../pkg/mod/github.com/kerberos-io/[email protected]/cgo/ffmpeg/video.go:11:
/usr/include/x86_64-linux-gnu/libavcodec/avcodec.h:3729:5: note: declared here
3729 | int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,

Connection resetting from agent to USB Camera (transformed to RTSP stream)

I have an USB camera on my Lenovo laptop (running Fedora 35 Linux) and I ran RTSP Simple server according to this guide https://github.com/kerberos-io/camera-to-rtsp to expose it via RTSP as a container.

The command I used is:
podman run --rm --name rtsp-server --network=host -d --privileged -v $PWD/rtsp-simple-server.yml:/rtsp-simple-server.yml kerberos/rtsp-simple-server

File rtsp-simple-server.yml changed according to the doc, added lines:

paths:
       usbcam:
        runOnInit: ffmpeg -f v4l2 -i /dev/video0 -preset ultrafast -c:v libx264 -f rtsp rtsp://<MY_IP>:$RTSP_PORT/$RTSP_PATH
        runOnInitRestart: yes 

The server is working and I can connect to the camera using VLC and see live video without any interruptions.

Then I ran agent using latest docker image using this command:
podman run --rm --name kerberos -p 8081:80 -d kerberos/agent:latest

Both containers are running on the same host (Lenovo with Fedora).

The agent is working and accessible via port 8081, and I can successfully add camera in agent UI using URL rtsp://<MY_IP>:8554/usbcam - if I click Verify connection it saying Camera settings are successfully verified.
However, the Live view doesn't work - it shows nothing (only button Configure connection).

Also in the dashboard the message in IP camera frame is flipping from "Connected" to "Disconnected"

If I enable Continuous recording - then recording is happening - I see files available in Recordings - and each file has length 16-20 sec. It means agent can connect to the camera and do recordings, but looks like the connection is interrupting.

In rtsp-simple-server container I see following log messages:

2022/12/01 01:22:12 INF [RTSP] [conn <MY IP>:36654] opened
2022/12/01 01:22:12 INF [RTSP] [session 250958557] created by <MY IP>:36654
2022/12/01 01:22:12 INF [RTSP] [session 250958557] is reading from path 'usbcam', with TCP, 1 track (H264)
2022/12/01 01:22:36 INF [RTSP] [conn <MY IP>:36654] closed (read tcp <MY IP>:8554-><MY IP>:36654: read: connection reset by peer)
2022/12/01 01:22:36 INF [RTSP] [session 250958557] destroyed (not in use)

Looks like the connection between agent and rtsp server is resetting each ~20 sec.

But this is not happening for VLC connection, it stays for any period of time, for example, if I open streaming in VLC:

2022/12/01 01:31:08 INF [RTSP] [conn <MY IP>:39496] opened
2022/12/01 01:31:08 INF [RTSP] [session 284726513] created by <MY IP>:39496
2022/12/01 01:31:08 INF [RTSP] [session 284726513] is reading from path 'usbcam', with UDP, 1 track (H264)

It stays forever and finish only when I stop streaming in VLC with this message in logs:

2022/12/01 01:44:35 INF [RTSP] [session 284726513] destroyed (teared down by 1<MY IP>:39496)
2022/12/01 01:44:35 INF [RTSP] [conn <MY IP>:39496] closed (EOF)

Also I noticed in Agent container logs that machinery is restarting constantly:

{"level":"info","msg":"ProcessMotion: Motion detection enabled.","time":"2022-12-01T02:02:37+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 3","time":"2022-12-01T02:02:40+01:00"}
{"level":"info","msg":"HandleStream: packet size 129966","time":"2022-12-01T02:02:41+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 4","time":"2022-12-01T02:02:45+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 4","time":"2022-12-01T02:02:50+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 4","time":"2022-12-01T02:02:55+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 4","time":"2022-12-01T02:03:00+01:00"}
{"level":"info","msg":"Main: Restarting machinery.","time":"2022-12-01T02:03:00+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 4","time":"2022-12-01T02:03:00+01:00"}
{"level":"info","msg":"Main: Restarting machinery.","time":"2022-12-01T02:03:00+01:00"}
{"level":"info","msg":"RunAgent: waiting 3 seconds to make sure everything is properly closed.","time":"2022-12-01T02:03:01+01:00"}
{"level":"info","msg":"Successfully Opened config.json from opensource","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"RunAgent: opening RTSP stream","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"RunAgent: opened RTSP stream","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"RunAgent: SetMaxGopCount was set with: 10","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"ConfigureMQTT: not starting as running in Offline mode.","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"HandleRecordStream: Start motion based recording ","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"ProcessMotion: Motion detection enabled.","time":"2022-12-01T02:03:04+01:00"}
{"level":"info","msg":"HandleStream: packet size 84577","time":"2022-12-01T02:03:06+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 5","time":"2022-12-01T02:03:07+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 5","time":"2022-12-01T02:03:12+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 5","time":"2022-12-01T02:03:17+01:00"}
{"level":"info","msg":"ControlAgent: Number of packets read 5","time":"2022-12-01T02:03:22+01:00"}
{"level":"info","msg":"Main: Restarting machinery.","time":"2022-12-01T02:03:22+01:00"}
{"level":"info","msg":"RunAgent: waiting 3 seconds to make sure everything is properly closed.","time":"2022-12-01T02:03:23+01:00"}

Troubleshooting Done
docker image kerberos/agent:latest
I tried to run agent on separate RPI4 host - and I'm having the same issue (USB camera on Lenovo Laptop and agent on RPI) - connection resetting after ~20 sec.

Host Specs:
Lenovo T260 with Fedora 36 + podman + USB camera
Agent tested also on RPI4 with Ubuntu 22.04

New Kerberos Agent: Plans for USBCamera and Raspberry PI camera

The new agent currently only supports a valid H264 stream (we plan to have H265 support). In the past (previous open source agent) we supported native integrations for USBCameras (v4l2) and Raspberry Pi Cameras (mmal), however this was very intensive to make sure the integrations are fully working. On top of that we required a different codebase for each camera.

To overcome this and make it easier to support cameras we are moving to a H264/H265 support only, this would mean that we will make a RTSP wrapper for USBCameras and Raspberry PI camera. So far this isn't documented properly, but we plan to ship an additional Docker container that will run next to the Kerberos Agent container.

Current work-a-round looks like this:

USB Camera

We rely on the rtsp-simple-server project, this allows us to run a RTSP server to which we can publish a stream and subscribe to from the Kerberos Agent. You can run the RTSP server as following.

docker run -d --network=host aler9/rtsp-simple-server

Above command will run the server in host mode and run as a deamon in background. Next we can use ffmpeg to inject the /dev/video1 or /dev/videox (you have to lookup the id) into the RTSP container. Notice that you'll need to add -c:v libx264 which will transcode the stream to H264, if your camera isn't outputting H264 but JPEG; this will require some compute.

ffmpeg -f v4l2 -i /dev/video1 -preset ultrafast -b:v 600k  -c:v libx264 -f rtsp rtsp://localhost:8554/mystream

Launch the Kerberos Agent and make sure to set the RTSP connection to rtsp://localhost:8554/mystream. You should see the stream coming up, and connected to Kerberos Hub. You will notice that all features are properly working just like if you would have connect to a real IP camera.

Raspberry Pi camera

The process is similar as above, make sure you first run the rtsp-simple-server container.

docker run -d --network=host aler9/rtsp-simple-server

Instead of using the ffmpeg command we can now use the libcamera library in a similar way. The benefit of the Raspberry Pi camera is that it comes with an H264 stream already, so no need to do any transcoding, only thing that happens is to send it into the RTSP server.

libcamera-vid -t 0 --inline -o - | ffmpeg -i pipe: -c copy -f rtsp rtsp://localhost:8554/mystream

Going next (need help)

The idea is to bundle this in a single container where you can just pass in some arguments with the type of camera you are target and which deviceID (/dev/video0, /dev/video1, etc). This container would then run next to the Kerberos Agent, on which the Kerberos Agent will read from the stream.

We are start the project here, feel free to collaborate on the Camera to RTSP repo.

Why does this matter

Converting any camera to a RTSP stream will make our code base much easier, and at the same time will allow us to work on features that are more important. We will handle any camera as a RTSP camera, by transforming the camera stream to a valid RTSP stream using the side container.

Once doing that we have a single integration and same capabilities such as H264 or H265 encoded recordings, livestreaming over MQTT and WEBRTC.

Recordings saved with no file type

Problem

I cannot view recordings in Kerberos Agent.

I get this error:
error

After downloading the recording, it is saved as "video" with no file extension.

I can see and watch the recordings just fine in my Kerberos Hub

Troubleshooting Done

  • Updating docker image kerberos/agent:latest.
  • Removed passing of volumes from host to container.

Host Specs

  • Ubuntu 20.04 VM

Problem creating a filemkdir open .data/snapshots/.test permission denied

When I start my containers using Docker Compose I receive the following errors in the log:

$ docker compose --file /srv/kerberos-agent/docker-compose.yml logs
ka-garage-south  | {"level":"fatal","msg":"Problem creating a file: open ./data/snapshots/.test: permission denied","time":"2022-12-19T20:37:39+01:00"}
ka-garage-south  | {"level":"fatal","msg":"Problem creating a file: open ./data/snapshots/.test: permission denied","time":"2022-12-19T20:37:42+01:00"}
ka-garage-north     | {"level":"fatal","msg":"Problem creating a file: open ./data/snapshots/.test: permission denied","time":"2022-12-19T20:37:39+01:00"}
ka-garage-north     | {"level":"fatal","msg":"Problem creating a file: open ./data/snapshots/.test: permission denied","time":"2022-12-19T20:37:42+01:00"}

Here is my sanitised docker-compose.yml configuration:

$ docker compose --file /srv/kerberos-agent/docker-compose.yml config
name: kerberos-agent
services:
  ka-garage-north:
    container_name: ka-garage-north
    environment:
      AGENT_AUTO_CLEAN: "true"
      AGENT_AUTO_CLEAN_MAX_SIZE: "102400"
      AGENT_CAPTURE_CONTINUOUS: "false"
      AGENT_CAPTURE_FRAGMENTED: "false"
      AGENT_CAPTURE_FRAGMENTED_DURATION: "8"
      AGENT_CAPTURE_IPCAMERA_RTSP: rtsp://[user]:[pass]@192.168.1.84:554/cam/realmonitor?channel=1&subtype=0
      AGENT_CAPTURE_IPCAMERA_SUB_RTSP: rtsp://[user]:[pass]@192.168.1.84:554/cam/realmonitor?channel=1&subtype=1
      AGENT_CAPTURE_MAXLENGTH: "600"
      AGENT_CAPTURE_PIXEL_CHANGE: "150"
      AGENT_CAPTURE_POSTRECORDING: "40"
      AGENT_CAPTURE_PRERECORDING: "20"
      AGENT_KEY: ""
      AGENT_MQTT_PASSWORD: ""
      AGENT_MQTT_URI: tcp://195.168.1.95:1883
      AGENT_MQTT_USERNAME: ""
      AGENT_NAME: garage-north
      AGENT_OFFLINE: "false"
      AGENT_PASSWORD: [password]
      AGENT_TIMEZONE: America/Edmonton
      AGENT_USERNAME: admin
    hostname: [hostname]
    image: kerberos/agent:latest
    networks:
      default: null
    ports:
    - mode: ingress
      target: 80
      published: "8083"
      protocol: tcp
    restart: unless-stopped
    user: 1000:1000
    volumes:
    - type: bind
      source: /srv/kerberos-agent/garage-north/config
      target: /home/agent/data/config
      bind:
        create_host_path: true
    - type: bind
      source: /media/nvr/kerberos/garage-north/recordings
      target: /home/agent/data/recordings
      bind:
        create_host_path: true
  ka-garage-south:
    container_name: ka-garage-south
    environment:
      AGENT_AUTO_CLEAN: "true"
      AGENT_AUTO_CLEAN_MAX_SIZE: "102400"
      AGENT_CAPTURE_CONTINUOUS: "false"
      AGENT_CAPTURE_FRAGMENTED: "false"
      AGENT_CAPTURE_FRAGMENTED_DURATION: "8"
      AGENT_CAPTURE_IPCAMERA_RTSP: rtsp://[user]:[pass]@192.168.1.83:554/cam/realmonitor?channel=1&subtype=0
      AGENT_CAPTURE_IPCAMERA_SUB_RTSP: rtsp://[user]:[pass]@192.168.1.83:554/cam/realmonitor?channel=1&subtype=1
      AGENT_CAPTURE_MAXLENGTH: "600"
      AGENT_CAPTURE_PIXEL_CHANGE: "150"
      AGENT_CAPTURE_POSTRECORDING: "40"
      AGENT_CAPTURE_PRERECORDING: "20"
      AGENT_KEY: ""
      AGENT_MQTT_PASSWORD: ""
      AGENT_MQTT_URI: tcp://195.168.1.95:1883
      AGENT_MQTT_USERNAME: ""
      AGENT_NAME: garage-south
      AGENT_OFFLINE: "false"
      AGENT_PASSWORD: [password]
      AGENT_TIMEZONE: America/Edmonton
      AGENT_USERNAME: admin
    hostname: [hostname]
    image: kerberos/agent:latest
    networks:
      default: null
    ports:
    - mode: ingress
      target: 80
      published: "8082"
      protocol: tcp
    restart: unless-stopped
    user: 1000:1000
    volumes:
    - type: bind
      source: /srv/kerberos-agent/garage-south/config
      target: /home/agent/data/config
      bind:
        create_host_path: true
    - type: bind
      source: /media/nvr/kerberos/garage-south/recordings
      target: /home/agent/data/recordings
      bind:
        create_host_path: true
networks:
  default:
    name: kerberos-agent_default

The mount points for these two services are as follows:

$ docker container inspect ka-garage-south -f '{{range .Mounts}}{{.Type}}:{{.Source}}:{{.Destination}}{{println}}{{ end }}'
bind:/srv/kerberos-agent/garage-south/config:/home/agent/data/config
bind:/media/nvr/kerberos/garage-south/recordings:/home/agent/data/recordings

$ docker container inspect ka-garage-east -f '{{range .Mounts}}{{.Type}}:{{.Source}}:{{.Destination}}{{println}}{{ end }}'
bind:/srv/kerberos-agent/garage-east/config:/home/agent/data/config
bind:/media/nvr/kerberos/garage-east/recordings:/home/agent/data/recordings

I am running the services under User idsvc:

$ id $user
uid=1000(idsvc) gid=1000(idsvc) groups=1000(idsvc),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),104(input),106(render),108(netdev),995(docker),997(gpio),998(i2c),999(spi)

Before starting the containers I ran the following commands:

$ mkdir /srv/kerberos-agent/garage-north /srv/kerberos-agent/garage-north/config
$ mkdir /srv/kerberos-agent/garage-south /srv/kerberos-agent/garage-south/config
$ sudo chown idsvc:idsvc /srv/kerberos-agent/ -R
$ sudo chmod 777 /srv/kerberos-agent/ -R

$ mkdir /media/nvr/kerberos/garage-north
$ mkdir /media/nvr/kerberos/garage-south
$ sudo chown idsvc:idsvc /media/nvr/kerberos/ -R
$ sudo chmod 777 /media/nvr/kerberos -R

The file permissions for the /home/agent/data/config mount look like this:

$ ls -la /srv/kerberos-agent/garage-north/
total 12
drwxrwxrwx 3 idsvc idsvc 4096 Dec 19 11:32 .
drwxrwxrwx 7 idsvc idsvc 4096 Dec 19 12:30 ..
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 config
$ ls -la /srv/kerberos-agent/garage-north/config/
total 8
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 .
drwxrwxrwx 3 idsvc idsvc 4096 Dec 19 11:32 ..
$ ls -la /srv/kerberos-agent/garage-south/
total 12
drwxrwxrwx 3 idsvc idsvc 4096 Dec 19 11:32 .
drwxrwxrwx 7 idsvc idsvc 4096 Dec 19 12:30 ..
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 config
$ ls -la /srv/kerberos-agent/garage-south/config/
total 8
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 .
drwxrwxrwx 3 idsvc idsvc 4096 Dec 19 11:32 ..

The file permissions for the /home/agent/data/recordings mount look like this:

$ ls -la /media/nvr/kerberos/garage-north/
total 16
drwxrwxrwx 4 idsvc idsvc 4096 Dec 19 12:37 .
drwxrwxrwx 7 idsvc idsvc 4096 Dec 19 11:32 ..
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 recordings
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:37 snapshots
$ ls -la /media/nvr/kerberos/garage-north/recordings/
total 8
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 .
drwxrwxrwx 4 idsvc idsvc 4096 Dec 19 12:37 ..

$ ls -la /media/nvr/kerberos/garage-south/
total 16
drwxrwxrwx 4 idsvc idsvc 4096 Dec 19 12:37 .
drwxrwxrwx 7 idsvc idsvc 4096 Dec 19 11:32 ..
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 recordings
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:37 snapshots
$ ls -la /media/nvr/kerberos/garage-south/recordings/
total 8
drwxrwxrwx 2 idsvc idsvc 4096 Dec 19 12:56 .
drwxrwxrwx 4 idsvc idsvc 4096 Dec 19 12:37 ..

My versions for reference:

$ docker --version
Docker version 20.10.21, build baeda1f
$ docker compose version
Docker Compose version v2.12.2

I have tried adding user: 1000:1000 to the services entries in the compose file, running the docker compose elevated, and I am stuck.

What incredibly obvious thing have I missed?

Live Stream/View Framerate

I'm running the latest Kerberos.io Agent via Docker on an Ubuntu 20 Server VM minimal install. That VM has 4 cores and 8GB of RAM dedicated. I was able to connect my S3VC PoE IP Camera via RTSP using the primary RTSP stream. The Steam is set to 3MP resolution with 20fps H265.

I have the Streaming Framerate set in the Agent to 20fps to match the RTSP stream.

The clips captured via Motion Detection in the Agent playback at the expected framerate, but the live view on the dashboard and the Stream provided via the Agent run at about 1/2fps, not even 1fps. I have tried dumbing down the RTSP stream to 1280x720 H264 and it still only runs about 1/2fps on the Live Stream. My plan was to plug several of the Live Streams from multiple cameras into a simple HTML Table to be able to view them all live simultaneously, but at this rate the Live Stream is running, this is not going to be viable.

Is there something I'm missing?

What logs can I pull to assist in troubleshooting?

Thanks!

Agent not displaying rpi camera on pi4 b and kios issues

Raspberry Pi 4 Model B 4GB
KiOS will not run without replacing fixup4.dat and start4.elf with Bullseye files.
Once running, KiOS dashboard does not show a stream of the rpi camera (v 2.1)
Camera confirmed working on rpi OS.
I'm guessing this has to do with the change in the board architecture and camera commands.
Do you intend to release a Pi 4 B/rpi camera compatible version?

Continuous recording with timestamped filenames

I have been investigating a handful of different RTSP -> Stream + File systems and this is one is very nice.

Is there a set of conditions that I can configure to enable to record all video from an IP based camera not just motion triggered events?

Prevent Machinery from crashing due not beeing able to connect to camera "Feature suggestion"

I experienced that the machinery is crashing if the camera can not be reached or similar.

in pseudo programming i suggest the following:

try
{
open camera stream with settings: settings.xml
}
catch (error)
{
if error == connection failed or not found
{
put error to log and say sorry
create dummy stream with tiny loop video on 8889
}
else{

something else happened, spam the logz

}

}

This is extremely helpfull also while buildimng up the Network. especially in container environments.... ( network routing issues)
You can fire up the container and check if You actually see a stream on 8889 without connecting the cam.

greetings

Thomas

Is my camera working? An overview of tested cameras.

New users, or existing community members, wonder if their old/new camera is expected to work with the Kerberos Agent. As reported on a previous issue kerberos-io/documentation#40, we want to provide a never-complete list of tested and approved cameras that work with the Kerberos Agent.

Call to action: If you have tested Kerberos Agent with your camera (with or without the sidecar for a USB camera), then feel free to add the camera name and model as a comment to this list. We will then update and maintain the approved camera list, so other community members can benefit from this, without buying or leveraging cameras that are not supported (or not yet supported).

USB cameras

  • Logitech BRIO 4K Stream Edition

IP Cameras

Avigilon

  • H3 H.264 (Zoom)
  • H4 H.264
  • H5A (Zoom)

Axis

  • P3245-LV
  • P3227-LV
  • M3066-V

Cantonk

CostarHD

  • RISE 4260HD Series (PTZ)
  • RISE 4261HD Series (PTZ)

Dahua

  • IPC-HFW2431S-S-S2

Eufy

  • Security Solo IndoorCam C24

Hanwha

  • RTSP support but ONVIF fails (investigating)

Hikvision

  • DS-2DE4415IW-DE (PTZ)
  • DS-2CD2043G2-I
  • DS-2CD2143G2-IS
  • DS-2CD2346G2-I Dome
  • DS-2CD6D54G1-IZ(S)

Reolink

  • E1 Pro (RTSP stream not stable, shows encoding issues) (Report)
  • TrackMix PoE (PTZ, Audio) (Only sub stream works). (Report)
  • E1 Outdoor (PTZ, Audio)

TP-link

  • Tapo C200 (PTZ, Audio) (Report)
  • Tapo C310

Wansview

  • W2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.