hikcloudstream 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hikcloudstream-0.1.0/.env.example +3 -0
- hikcloudstream-0.1.0/.github/workflows/ci.yml +36 -0
- hikcloudstream-0.1.0/.gitignore +14 -0
- hikcloudstream-0.1.0/.python-version +1 -0
- hikcloudstream-0.1.0/AGENT.md +88 -0
- hikcloudstream-0.1.0/CHANGELOG.md +16 -0
- hikcloudstream-0.1.0/CONTRIBUTING.md +45 -0
- hikcloudstream-0.1.0/LICENSE +0 -0
- hikcloudstream-0.1.0/NOTICE +12 -0
- hikcloudstream-0.1.0/PKG-INFO +148 -0
- hikcloudstream-0.1.0/README.md +108 -0
- hikcloudstream-0.1.0/docs/MAINTAINER_BLUEPRINT.md +55 -0
- hikcloudstream-0.1.0/docs/architecture.md +45 -0
- hikcloudstream-0.1.0/docs/limitations.md +24 -0
- hikcloudstream-0.1.0/docs/quickstart.md +70 -0
- hikcloudstream-0.1.0/docs/streaming.md +56 -0
- hikcloudstream-0.1.0/examples/cloud_snapshot.py +31 -0
- hikcloudstream-0.1.0/examples/list_cameras.py +25 -0
- hikcloudstream-0.1.0/examples/live_frame.py +31 -0
- hikcloudstream-0.1.0/examples/mjpeg_proxy.py +30 -0
- hikcloudstream-0.1.0/examples/record_clip.py +31 -0
- hikcloudstream-0.1.0/pyproject.toml +83 -0
- hikcloudstream-0.1.0/src/hikcloudstream/__init__.py +39 -0
- hikcloudstream-0.1.0/src/hikcloudstream/_config.py +15 -0
- hikcloudstream-0.1.0/src/hikcloudstream/auth.py +30 -0
- hikcloudstream-0.1.0/src/hikcloudstream/capture.py +37 -0
- hikcloudstream-0.1.0/src/hikcloudstream/cli/__init__.py +1 -0
- hikcloudstream-0.1.0/src/hikcloudstream/cli/_common.py +140 -0
- hikcloudstream-0.1.0/src/hikcloudstream/cli/snapshot.py +125 -0
- hikcloudstream-0.1.0/src/hikcloudstream/cli/stream.py +226 -0
- hikcloudstream-0.1.0/src/hikcloudstream/client.py +296 -0
- hikcloudstream-0.1.0/src/hikcloudstream/exceptions.py +48 -0
- hikcloudstream-0.1.0/src/hikcloudstream/models.py +48 -0
- hikcloudstream-0.1.0/src/hikcloudstream/py.typed +0 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/__init__.py +26 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/adapter.py +123 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/crypto.py +178 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/probe.py +62 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/rtp.py +31 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/session.py +391 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/sinks/__init__.py +1 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/sinks/annex_b.py +76 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/sinks/http.py +250 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/sinks/mjpeg.py +126 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/sinks/mpegts.py +167 -0
- hikcloudstream-0.1.0/src/hikcloudstream/stream/tokens.py +107 -0
- hikcloudstream-0.1.0/tests/unit/test_crypto.py +35 -0
- hikcloudstream-0.1.0/tests/unit/test_probe.py +22 -0
- hikcloudstream-0.1.0/tests/unit/test_rtp.py +34 -0
- hikcloudstream-0.1.0/uv.lock +1057 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --all-extras --python ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Ruff
|
|
30
|
+
run: uv run ruff check src tests
|
|
31
|
+
|
|
32
|
+
- name: Unit tests
|
|
33
|
+
run: uv run pytest tests/unit -v
|
|
34
|
+
|
|
35
|
+
- name: Build wheel
|
|
36
|
+
run: uv build
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Agent directives
|
|
2
|
+
|
|
3
|
+
> **Entry point for LLM agents and contributors working in this repository.**
|
|
4
|
+
|
|
5
|
+
## What this repo is
|
|
6
|
+
|
|
7
|
+
**hikcloudstream** is an unofficial Python SDK for **Hik-Connect cloud cameras**:
|
|
8
|
+
|
|
9
|
+
- REST login, device list, cloud snapshots
|
|
10
|
+
- Live video via **cloud VTM relay** (not LAN RTSP, not P2P)
|
|
11
|
+
|
|
12
|
+
It is a **public open-source library** (Apache-2.0), not a sandbox experiment.
|
|
13
|
+
|
|
14
|
+
## Language policy (non-negotiable)
|
|
15
|
+
|
|
16
|
+
**All code artifacts must be in English:**
|
|
17
|
+
|
|
18
|
+
- Identifiers, docstrings, comments, CLI help, error messages, HTTP viewer HTML
|
|
19
|
+
- README and docs inside the repo
|
|
20
|
+
- Commit messages (Conventional Commits)
|
|
21
|
+
|
|
22
|
+
You may chat with the user in their language; never mirror it in the codebase.
|
|
23
|
+
|
|
24
|
+
## Sensitive data policy
|
|
25
|
+
|
|
26
|
+
**Never commit:**
|
|
27
|
+
|
|
28
|
+
- Real usernames, passwords, device serials, validate codes
|
|
29
|
+
- APK decompile trees or proprietary SDK blobs
|
|
30
|
+
- Condominium-specific names or private regional host examples beyond public `api.hik-connect.com`
|
|
31
|
+
|
|
32
|
+
Use `.env` locally (gitignored). Examples use `user@example.com` placeholders only.
|
|
33
|
+
|
|
34
|
+
## Architecture map
|
|
35
|
+
|
|
36
|
+
| Module | Responsibility |
|
|
37
|
+
|--------|----------------|
|
|
38
|
+
| `src/hikcloudstream/client.py` | REST API, login, list, snapshot |
|
|
39
|
+
| `src/hikcloudstream/capture.py` | Cloud snapshot AES decrypt |
|
|
40
|
+
| `src/hikcloudstream/stream/session.py` | VTM session, `LiveStreamSession`, record/capture helpers |
|
|
41
|
+
| `src/hikcloudstream/stream/probe.py` | Auto stream type (substream vs main) |
|
|
42
|
+
| `src/hikcloudstream/stream/rtp.py` | RTP → Annex B |
|
|
43
|
+
| `src/hikcloudstream/stream/crypto.py` | Encrypted NAL decrypt |
|
|
44
|
+
| `src/hikcloudstream/stream/sinks/` | MPEG-TS, MJPEG, HTTP viewer |
|
|
45
|
+
| `src/hikcloudstream/cli/` | Thin CLI over public API only |
|
|
46
|
+
|
|
47
|
+
Stable exports live in `src/hikcloudstream/__init__.py` and `src/hikcloudstream/stream/__init__.py`.
|
|
48
|
+
|
|
49
|
+
## How to change things safely
|
|
50
|
+
|
|
51
|
+
1. Read surrounding code; match naming and patterns.
|
|
52
|
+
2. Keep CLI and examples on the **public API** — no direct `pyezvizapi` in `cli/`.
|
|
53
|
+
3. Breaking API changes → update `CHANGELOG.md` and README examples.
|
|
54
|
+
4. Prefer typed exceptions from `exceptions.py` over bare `RuntimeError`.
|
|
55
|
+
5. Unit-test protocol logic (RTP, crypto) with redacted fixtures — no live credentials in CI.
|
|
56
|
+
|
|
57
|
+
## Common pitfalls
|
|
58
|
+
|
|
59
|
+
| Issue | Cause | Note |
|
|
60
|
+
|-------|-------|------|
|
|
61
|
+
| Black video on main stream | Proprietary RTP on some DVR channels | Auto substream (`stream=2`) |
|
|
62
|
+
| VTDU token failure | Wrong auth path for Hik-Connect | Primary: `POST /api/user/token/get` |
|
|
63
|
+
| MJPEG viewer + encryption | Decrypt not wired in viewer | Use `validate_code` with record/snapshot only |
|
|
64
|
+
| N viewers = N VTM sessions | One TCP session per consumer | Document fan-out / HLS for scale |
|
|
65
|
+
|
|
66
|
+
## Testing expectations
|
|
67
|
+
|
|
68
|
+
- `tests/unit/` must pass in CI without secrets
|
|
69
|
+
- Integration tests: `@pytest.mark.integration`, env-gated only
|
|
70
|
+
- Run `uv run ruff check src tests` before finishing
|
|
71
|
+
|
|
72
|
+
## Routing
|
|
73
|
+
|
|
74
|
+
| Need | Go to |
|
|
75
|
+
|------|--------|
|
|
76
|
+
| User-facing overview | [README.md](README.md) |
|
|
77
|
+
| Streaming API detail | [docs/streaming.md](docs/streaming.md) |
|
|
78
|
+
| Maintainer blueprint | [docs/MAINTAINER_BLUEPRINT.md](docs/MAINTAINER_BLUEPRINT.md) |
|
|
79
|
+
| Legal / OSS notes | MAINTAINER_BLUEPRINT § License |
|
|
80
|
+
|
|
81
|
+
## Conflict resolution
|
|
82
|
+
|
|
83
|
+
1. User explicit choice
|
|
84
|
+
2. This `AGENT.md` for repo-specific rules
|
|
85
|
+
3. Target module conventions
|
|
86
|
+
4. Generic best practice
|
|
87
|
+
|
|
88
|
+
If the developer also uses the **pkb** workspace, engineering discipline from `pkb/CLAUDE.md` applies unless it conflicts with this file.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-06-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial public release migrated from sandbox prototype
|
|
13
|
+
- `HikConnectClient` — login, list cameras, cloud snapshot
|
|
14
|
+
- `hikcloudstream.stream` — VTM live sessions, auto stream probe, MPEG-TS record, MJPEG viewer
|
|
15
|
+
- CLI: `hikcloudstream-snapshot`, `hikcloudstream-stream`
|
|
16
|
+
- Examples, docs, unit tests, GitHub Actions CI
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve **hikcloudstream**. This project is early-stage (0.x); APIs may change.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/cristianojmiranda/hikcloudstream.git
|
|
9
|
+
cd hikcloudstream
|
|
10
|
+
uv sync --all-extras
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Run tests
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv run pytest tests/unit -v
|
|
17
|
+
uv run ruff check src tests
|
|
18
|
+
uv run mypy src/hikcloudstream
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Integration tests (live Hik-Connect account) are optional:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
export HIK_CONNECT_USER=...
|
|
25
|
+
export HIK_CONNECT_PASSWORD=...
|
|
26
|
+
uv run pytest -m integration # when added
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Never commit credentials or device serials from your environment.
|
|
30
|
+
|
|
31
|
+
## Pull request checklist
|
|
32
|
+
|
|
33
|
+
- [ ] English for code, comments, CLI help, and user-facing errors
|
|
34
|
+
- [ ] No secrets, real account names, or private URLs in the diff
|
|
35
|
+
- [ ] Unit tests for behavior changes (rtp, crypto, probe logic)
|
|
36
|
+
- [ ] Public API changes documented in `CHANGELOG.md`
|
|
37
|
+
- [ ] `uv run ruff check` and `uv run pytest tests/unit` pass
|
|
38
|
+
|
|
39
|
+
## Commits
|
|
40
|
+
|
|
41
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, etc.
|
|
42
|
+
|
|
43
|
+
## AI-assisted changes
|
|
44
|
+
|
|
45
|
+
Read [AGENT.md](AGENT.md) before editing. Keep diffs focused; match existing module layout.
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
hikcloudstream
|
|
2
|
+
Copyright 2026 Cristiano Miranda
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0.
|
|
5
|
+
|
|
6
|
+
This project depends on:
|
|
7
|
+
|
|
8
|
+
- pyezvizapi (Apache-2.0) — https://github.com/RenierM26/pyEzvizApi
|
|
9
|
+
- httpx (BSD-3-Clause) — https://github.com/encode/httpx
|
|
10
|
+
- pycryptodome (BSD) — https://github.com/Legrandin/pycryptodome
|
|
11
|
+
- pillow (MIT-CMU) — optional extra [cli]/[viewer]
|
|
12
|
+
- av / PyAV (BSD-3-Clause) — optional extra [viewer]
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hikcloudstream
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial Python SDK for Hik-Connect cloud cameras: list devices, snapshots, and live VTM streaming
|
|
5
|
+
Project-URL: Homepage, https://github.com/cristianojmiranda/hikcloudstream
|
|
6
|
+
Project-URL: Documentation, https://github.com/cristianojmiranda/hikcloudstream#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/cristianojmiranda/hikcloudstream
|
|
8
|
+
Project-URL: Issues, https://github.com/cristianojmiranda/hikcloudstream/issues
|
|
9
|
+
Author: Cristiano Miranda
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: NOTICE
|
|
13
|
+
Keywords: camera,cctv,cloud,ezviz,hik-connect,hikvision,nvr,streaming,vtm
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Multimedia :: Video :: Capture
|
|
21
|
+
Classifier: Topic :: System :: Networking
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: httpx>=0.28.0
|
|
25
|
+
Requires-Dist: pycryptodome>=3.21.0
|
|
26
|
+
Requires-Dist: pyezvizapi>=1.0.4.5
|
|
27
|
+
Provides-Extra: cli
|
|
28
|
+
Requires-Dist: pillow>=11.0.0; extra == 'cli'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: av>=17.1.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
32
|
+
Requires-Dist: pillow>=11.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
36
|
+
Provides-Extra: viewer
|
|
37
|
+
Requires-Dist: av>=17.1.0; extra == 'viewer'
|
|
38
|
+
Requires-Dist: pillow>=11.0.0; extra == 'viewer'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# hikcloudstream
|
|
42
|
+
|
|
43
|
+
[](https://github.com/cristianojmiranda/hikcloudstream/actions/workflows/ci.yml)
|
|
44
|
+

|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
**Unofficial** Python SDK for **Hik-Connect cloud cameras** — list devices, cloud snapshots, and live streaming over the VTM relay.
|
|
48
|
+
|
|
49
|
+
> If you have Hik-Connect cameras in the cloud (condo, shared NVR, no RTSP URL) and found almost nothing on GitHub — that's why this exists. This is a **community library**, not an official Hikvision or EZVIZ product. APIs can change without notice.
|
|
50
|
+
|
|
51
|
+
## What it does
|
|
52
|
+
|
|
53
|
+
- Log in with your Hik-Connect account (same credentials as the mobile app)
|
|
54
|
+
- List cameras and channels on the account
|
|
55
|
+
- Cloud snapshot (~352×288 thumbnail via API)
|
|
56
|
+
- **Live stream** via cloud VTM relay (H.264 → Annex B, MPEG-TS, MJPEG viewer)
|
|
57
|
+
- Auto-select substream vs main stream per camera
|
|
58
|
+
|
|
59
|
+
## What it does **not** do
|
|
60
|
+
|
|
61
|
+
- LAN RTSP / ONVIF / ISAPI (use FFmpeg, go2rtc, or HCNetSDK for local NVR access)
|
|
62
|
+
- P2P hole-punching (the app uses P2P at home; remote cloud preview uses **VTM relay** — same path as this library)
|
|
63
|
+
- Official support or guaranteed API stability
|
|
64
|
+
|
|
65
|
+
## Quick start
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/cristianojmiranda/hikcloudstream.git
|
|
69
|
+
cd hikcloudstream
|
|
70
|
+
uv sync --extra viewer
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
75
|
+
|
|
76
|
+
with HikConnectClient() as client:
|
|
77
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
78
|
+
for cam in client.list_cameras():
|
|
79
|
+
print(cam.index, cam.name, cam.device_serial, cam.channel_no)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Install
|
|
83
|
+
|
|
84
|
+
| Extra | Purpose | Command |
|
|
85
|
+
|-------|---------|---------|
|
|
86
|
+
| core | API + streaming protocol | `pip install hikcloudstream` or `uv sync` |
|
|
87
|
+
| `cli` | Command-line tools + Pillow | `uv sync --extra cli` |
|
|
88
|
+
| `viewer` | MJPEG HTTP viewer (PyAV) | `uv sync --extra viewer` |
|
|
89
|
+
| `dev` | Tests, ruff, mypy | `uv sync --extra dev` |
|
|
90
|
+
|
|
91
|
+
**System dependency:** [FFmpeg](https://ffmpeg.org/) (`ffmpeg` on PATH) for recording, HD frame capture, and MPEG-TS remux.
|
|
92
|
+
|
|
93
|
+
## CLI
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
export HIK_CONNECT_USER="user@example.com"
|
|
97
|
+
export HIK_CONNECT_PASSWORD="your_password"
|
|
98
|
+
|
|
99
|
+
uv run hikcloudstream-snapshot "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" --list
|
|
100
|
+
uv run hikcloudstream-snapshot "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 -o thumb.jpg
|
|
101
|
+
uv run hikcloudstream-stream "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 --proxy
|
|
102
|
+
uv run hikcloudstream-stream "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 -o frame.jpg --duration 6s
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Open `http://127.0.0.1:8558/` in a browser when using `--proxy`.
|
|
106
|
+
|
|
107
|
+
## Stream types
|
|
108
|
+
|
|
109
|
+
| `stream=` | Typical use |
|
|
110
|
+
|-----------|-------------|
|
|
111
|
+
| **2** (substream) | Lower bandwidth, standard H.264 — works on most DVR channels |
|
|
112
|
+
| **1** (main) | Higher resolution; some cameras only expose this stream |
|
|
113
|
+
| **auto** (default) | Probes substream for 5s, falls back to main |
|
|
114
|
+
|
|
115
|
+
Force main stream in Python: `StreamType.MAIN`. In CLI: `--main-stream`.
|
|
116
|
+
|
|
117
|
+
## Examples
|
|
118
|
+
|
|
119
|
+
See [`examples/`](examples/) — each script documents required extras and env vars.
|
|
120
|
+
|
|
121
|
+
## Documentation
|
|
122
|
+
|
|
123
|
+
- [Quickstart](docs/quickstart.md)
|
|
124
|
+
- [Streaming API](docs/streaming.md)
|
|
125
|
+
- [Limitations](docs/limitations.md)
|
|
126
|
+
- [Architecture](docs/architecture.md)
|
|
127
|
+
|
|
128
|
+
## Origin
|
|
129
|
+
|
|
130
|
+
Live streaming was reverse-engineered from the **Hik-Connect for End User** mobile app and aligned with [pyezvizapi](https://github.com/RenierM26/pyEzvizApi). The implementation uses the **cloud VTM relay protocol**.
|
|
131
|
+
|
|
132
|
+
## Related projects
|
|
133
|
+
|
|
134
|
+
- [pyezvizapi](https://github.com/RenierM26/pyEzvizApi) — VTM protocol (Apache-2.0)
|
|
135
|
+
- [Home Assistant EZVIZ](https://www.home-assistant.io/integrations/ezviz/) — integration using pyezvizapi
|
|
136
|
+
- [go2rtc](https://github.com/AlexxIT/go2rtc) — LAN RTSP/WebRTC aggregator
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). AI agents: read [AGENT.md](AGENT.md) first.
|
|
141
|
+
|
|
142
|
+
## Legal disclaimer
|
|
143
|
+
|
|
144
|
+
This is an **unofficial** community project. It is **not** affiliated with, endorsed by, or supported by Hangzhou Hikvision Digital Technology Co., Ltd. or EZVIZ. Use at your own risk. You are responsible for complying with Hik-Connect / EZVIZ Terms of Service and applicable law. Trademarks belong to their respective owners.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# hikcloudstream
|
|
2
|
+
|
|
3
|
+
[](https://github.com/cristianojmiranda/hikcloudstream/actions/workflows/ci.yml)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**Unofficial** Python SDK for **Hik-Connect cloud cameras** — list devices, cloud snapshots, and live streaming over the VTM relay.
|
|
8
|
+
|
|
9
|
+
> If you have Hik-Connect cameras in the cloud (condo, shared NVR, no RTSP URL) and found almost nothing on GitHub — that's why this exists. This is a **community library**, not an official Hikvision or EZVIZ product. APIs can change without notice.
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
- Log in with your Hik-Connect account (same credentials as the mobile app)
|
|
14
|
+
- List cameras and channels on the account
|
|
15
|
+
- Cloud snapshot (~352×288 thumbnail via API)
|
|
16
|
+
- **Live stream** via cloud VTM relay (H.264 → Annex B, MPEG-TS, MJPEG viewer)
|
|
17
|
+
- Auto-select substream vs main stream per camera
|
|
18
|
+
|
|
19
|
+
## What it does **not** do
|
|
20
|
+
|
|
21
|
+
- LAN RTSP / ONVIF / ISAPI (use FFmpeg, go2rtc, or HCNetSDK for local NVR access)
|
|
22
|
+
- P2P hole-punching (the app uses P2P at home; remote cloud preview uses **VTM relay** — same path as this library)
|
|
23
|
+
- Official support or guaranteed API stability
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/cristianojmiranda/hikcloudstream.git
|
|
29
|
+
cd hikcloudstream
|
|
30
|
+
uv sync --extra viewer
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
35
|
+
|
|
36
|
+
with HikConnectClient() as client:
|
|
37
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
38
|
+
for cam in client.list_cameras():
|
|
39
|
+
print(cam.index, cam.name, cam.device_serial, cam.channel_no)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
| Extra | Purpose | Command |
|
|
45
|
+
|-------|---------|---------|
|
|
46
|
+
| core | API + streaming protocol | `pip install hikcloudstream` or `uv sync` |
|
|
47
|
+
| `cli` | Command-line tools + Pillow | `uv sync --extra cli` |
|
|
48
|
+
| `viewer` | MJPEG HTTP viewer (PyAV) | `uv sync --extra viewer` |
|
|
49
|
+
| `dev` | Tests, ruff, mypy | `uv sync --extra dev` |
|
|
50
|
+
|
|
51
|
+
**System dependency:** [FFmpeg](https://ffmpeg.org/) (`ffmpeg` on PATH) for recording, HD frame capture, and MPEG-TS remux.
|
|
52
|
+
|
|
53
|
+
## CLI
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export HIK_CONNECT_USER="user@example.com"
|
|
57
|
+
export HIK_CONNECT_PASSWORD="your_password"
|
|
58
|
+
|
|
59
|
+
uv run hikcloudstream-snapshot "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" --list
|
|
60
|
+
uv run hikcloudstream-snapshot "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 -o thumb.jpg
|
|
61
|
+
uv run hikcloudstream-stream "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 --proxy
|
|
62
|
+
uv run hikcloudstream-stream "$HIK_CONNECT_USER" "$HIK_CONNECT_PASSWORD" 1 -o frame.jpg --duration 6s
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Open `http://127.0.0.1:8558/` in a browser when using `--proxy`.
|
|
66
|
+
|
|
67
|
+
## Stream types
|
|
68
|
+
|
|
69
|
+
| `stream=` | Typical use |
|
|
70
|
+
|-----------|-------------|
|
|
71
|
+
| **2** (substream) | Lower bandwidth, standard H.264 — works on most DVR channels |
|
|
72
|
+
| **1** (main) | Higher resolution; some cameras only expose this stream |
|
|
73
|
+
| **auto** (default) | Probes substream for 5s, falls back to main |
|
|
74
|
+
|
|
75
|
+
Force main stream in Python: `StreamType.MAIN`. In CLI: `--main-stream`.
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
See [`examples/`](examples/) — each script documents required extras and env vars.
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
- [Quickstart](docs/quickstart.md)
|
|
84
|
+
- [Streaming API](docs/streaming.md)
|
|
85
|
+
- [Limitations](docs/limitations.md)
|
|
86
|
+
- [Architecture](docs/architecture.md)
|
|
87
|
+
|
|
88
|
+
## Origin
|
|
89
|
+
|
|
90
|
+
Live streaming was reverse-engineered from the **Hik-Connect for End User** mobile app and aligned with [pyezvizapi](https://github.com/RenierM26/pyEzvizApi). The implementation uses the **cloud VTM relay protocol**.
|
|
91
|
+
|
|
92
|
+
## Related projects
|
|
93
|
+
|
|
94
|
+
- [pyezvizapi](https://github.com/RenierM26/pyEzvizApi) — VTM protocol (Apache-2.0)
|
|
95
|
+
- [Home Assistant EZVIZ](https://www.home-assistant.io/integrations/ezviz/) — integration using pyezvizapi
|
|
96
|
+
- [go2rtc](https://github.com/AlexxIT/go2rtc) — LAN RTSP/WebRTC aggregator
|
|
97
|
+
|
|
98
|
+
## Contributing
|
|
99
|
+
|
|
100
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). AI agents: read [AGENT.md](AGENT.md) first.
|
|
101
|
+
|
|
102
|
+
## Legal disclaimer
|
|
103
|
+
|
|
104
|
+
This is an **unofficial** community project. It is **not** affiliated with, endorsed by, or supported by Hangzhou Hikvision Digital Technology Co., Ltd. or EZVIZ. Use at your own risk. You are responsible for complying with Hik-Connect / EZVIZ Terms of Service and applicable law. Trademarks belong to their respective owners.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Maintainer blueprint
|
|
2
|
+
|
|
3
|
+
Internal planning notes for **hikcloudstream** maintainers. The public README is the user-facing source of truth.
|
|
4
|
+
|
|
5
|
+
## Protocol clarification
|
|
6
|
+
|
|
7
|
+
Live video uses **cloud VTM relay**, not LAN RTSP and not classic P2P hole-punching:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Account login (REST)
|
|
11
|
+
→ device/channel discovery (pagelist + VTM metadata)
|
|
12
|
+
→ VTDU stream tokens
|
|
13
|
+
→ TCP session to regional VTM server (ysproto://…)
|
|
14
|
+
→ RTP carrying H.264
|
|
15
|
+
→ depacketize / decode / remux
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The Hik-Connect mobile app also uses VTM for remote preview when P2P/LAN is unavailable. Do **not** describe this project as a “P2P stream fix.”
|
|
19
|
+
|
|
20
|
+
## Trade-offs
|
|
21
|
+
|
|
22
|
+
| Decision | Pros | Cons |
|
|
23
|
+
|----------|------|------|
|
|
24
|
+
| Build on pyezvizapi | Battle-tested VTM framing | Hik-Connect adapter layer forever |
|
|
25
|
+
| VTM-only (no P2P) | Matches cloud condo use case | No LAN optimizations |
|
|
26
|
+
| PyAV for MJPEG | Low latency | Heavy optional dep; CPU per viewer |
|
|
27
|
+
| Auto stream probe | Works across DVR channels | ~5s connect delay |
|
|
28
|
+
| Alpha 0.x semver | API flexibility | Breaking changes possible |
|
|
29
|
+
|
|
30
|
+
## License, copyright, and open-source safety
|
|
31
|
+
|
|
32
|
+
> Not legal advice.
|
|
33
|
+
|
|
34
|
+
Publishing as unofficial OSS is **reasonable** (same category as pyezvizapi, Home Assistant EZVIZ). Main risks: **ToS**, **trademark**, **secrets in repo** — not “you cannot copyright your Python.”
|
|
35
|
+
|
|
36
|
+
| Do | Don't |
|
|
37
|
+
|----|-------|
|
|
38
|
+
| Apache-2.0 + NOTICE | APK decompile, SDK blobs |
|
|
39
|
+
| README disclaimer | Official logos / “Hikvision SDK” naming |
|
|
40
|
+
| Placeholder examples | Real credentials or device serials |
|
|
41
|
+
|
|
42
|
+
See README legal disclaimer. Confirm employer IP if applicable.
|
|
43
|
+
|
|
44
|
+
## Deferred (post-0.1.0)
|
|
45
|
+
|
|
46
|
+
- PyPI publish
|
|
47
|
+
- Async API (`httpx.AsyncClient`)
|
|
48
|
+
- P2P / LAN RTSP
|
|
49
|
+
- Encrypted live MJPEG viewer
|
|
50
|
+
- Home Assistant integration
|
|
51
|
+
- Dependabot, SECURITY.md, integration CI nightly
|
|
52
|
+
|
|
53
|
+
## Public API stability
|
|
54
|
+
|
|
55
|
+
Exports in `hikcloudstream/__init__.py` and `hikcloudstream/stream/__init__.py` are the stable surface for 0.1.x. Breaking changes require CHANGELOG entry.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
High-level data flow (no internal endpoint catalog):
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────┐ REST ┌──────────────────┐
|
|
7
|
+
│ Your app │ ────────────► │ HikConnectClient │
|
|
8
|
+
│ or CLI │ │ (httpx) │
|
|
9
|
+
└──────┬──────┘ └────────┬─────────┘
|
|
10
|
+
│ │
|
|
11
|
+
│ stream │ sessionId
|
|
12
|
+
▼ ▼
|
|
13
|
+
┌──────────────────┐ VTDU tokens ┌─────────────────┐
|
|
14
|
+
│ LiveStreamSession│ ◄──────────── │ stream/adapter │
|
|
15
|
+
└────────┬─────────┘ └─────────────────┘
|
|
16
|
+
│ ysproto://VTM:8554
|
|
17
|
+
▼
|
|
18
|
+
┌──────────────────┐ RTP H.264 ┌──────────────────┐
|
|
19
|
+
│ pyezvizapi VTM │ ────────────► │ stream/rtp │
|
|
20
|
+
│ client │ │ stream/sinks/* │
|
|
21
|
+
└──────────────────┘ └──────────────────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Package layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
src/hikcloudstream/
|
|
28
|
+
├── client.py # REST API
|
|
29
|
+
├── capture.py # Snapshot decrypt
|
|
30
|
+
├── stream/
|
|
31
|
+
│ ├── session.py # VTM lifecycle
|
|
32
|
+
│ ├── probe.py # Auto stream type
|
|
33
|
+
│ ├── rtp.py # Depacketization
|
|
34
|
+
│ ├── crypto.py # Encrypted NAL
|
|
35
|
+
│ └── sinks/ # MPEG-TS, MJPEG, HTTP
|
|
36
|
+
└── cli/ # Optional commands
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Dependencies
|
|
40
|
+
|
|
41
|
+
- **httpx** — REST
|
|
42
|
+
- **pyezvizapi** — VTM TCP protocol
|
|
43
|
+
- **pycryptodome** — AES for snapshots and encrypted streams
|
|
44
|
+
- **av** (optional) — PyAV MJPEG decoder
|
|
45
|
+
- **FFmpeg** (system) — remux and frame extract
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Limitations
|
|
2
|
+
|
|
3
|
+
| Issue | Impact | Workaround |
|
|
4
|
+
|-------|--------|------------|
|
|
5
|
+
| Unofficial API | Endpoints may change | Pin `ClientConfig.client_version`; watch app updates |
|
|
6
|
+
| VTM session limits | N viewers = N cloud connections | Single ingest + HLS/WebRTC fan-out |
|
|
7
|
+
| Encrypted live MJPEG | Viewer raises error | `validate_code` on record/snapshot only |
|
|
8
|
+
| Proprietary RTP on main | Some channels black on `stream=1` | Auto substream (`stream=2`) |
|
|
9
|
+
| Channels without VTM | `Could not find VTM resource` | Channel offline or unlicensed |
|
|
10
|
+
| Cloud snapshot resolution | Fixed ~352×288 | Live frame capture for HD |
|
|
11
|
+
| CAPTCHA / 2FA | Login fails | Log in via official app first |
|
|
12
|
+
| No P2P / LAN RTSP | No direct NVR URL | Use go2rtc / RTSP for local access |
|
|
13
|
+
| Token / firewall | VTDU auth blocked | Ensure outbound HTTPS to Hik-Connect auth hosts |
|
|
14
|
+
|
|
15
|
+
## Performance (single viewer)
|
|
16
|
+
|
|
17
|
+
Approximate values — vary by CPU, camera, and stream type:
|
|
18
|
+
|
|
19
|
+
| Profile | RAM | Egress |
|
|
20
|
+
|---------|-----|--------|
|
|
21
|
+
| Substream MJPEG | ~65 MB | ~0.7 Mbps |
|
|
22
|
+
| Main HD MJPEG | ~100 MB | ~10–15 Mbps |
|
|
23
|
+
|
|
24
|
+
Not suitable for 50+ viewers without architecture change — see [streaming.md](streaming.md).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Quickstart
|
|
2
|
+
|
|
3
|
+
## Install
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
uv sync --extra viewer
|
|
7
|
+
# or: pip install "hikcloudstream[viewer]"
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Install [FFmpeg](https://ffmpeg.org/) for recording and HD frame capture.
|
|
11
|
+
|
|
12
|
+
## Environment (optional)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
cp .env.example .env
|
|
16
|
+
# fill HIK_CONNECT_USER and HIK_CONNECT_PASSWORD
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## List cameras
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
23
|
+
|
|
24
|
+
with HikConnectClient() as client:
|
|
25
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
26
|
+
for cam in client.list_cameras():
|
|
27
|
+
print(cam.index, cam.name, cam.device_serial, cam.channel_no)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Cloud snapshot
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
35
|
+
|
|
36
|
+
with HikConnectClient() as client:
|
|
37
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
38
|
+
cameras = client.list_cameras()
|
|
39
|
+
jpeg = client.capture_snapshot(cameras[0])
|
|
40
|
+
Path("thumb.jpg").write_bytes(jpeg)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Resolution is capped at **352×288** by the Hik-Connect cloud API.
|
|
44
|
+
|
|
45
|
+
## Live stream frame (HD)
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
50
|
+
from hikcloudstream.stream import capture_live_snapshot
|
|
51
|
+
|
|
52
|
+
with HikConnectClient() as client:
|
|
53
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
54
|
+
cameras = client.list_cameras()
|
|
55
|
+
capture_live_snapshot(client, cameras[0], Path("frame.jpg"), warmup_seconds=6.0)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## MJPEG browser viewer
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from hikcloudstream import Credentials, HikConnectClient
|
|
62
|
+
from hikcloudstream.stream import MjpegServer
|
|
63
|
+
|
|
64
|
+
with HikConnectClient() as client:
|
|
65
|
+
client.login(Credentials("user@example.com", "your_password"))
|
|
66
|
+
cameras = client.list_cameras()
|
|
67
|
+
MjpegServer(client, cameras[0], host="127.0.0.1", port=8558).serve_forever()
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Open `http://127.0.0.1:8558/`.
|