qrstream 0.4.1__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.
- qrstream-0.4.1/.github/workflows/publish.yml +37 -0
- qrstream-0.4.1/.github/workflows/test.yml +55 -0
- qrstream-0.4.1/.gitignore +31 -0
- qrstream-0.4.1/LICENSE +21 -0
- qrstream-0.4.1/PKG-INFO +292 -0
- qrstream-0.4.1/README-zh.md +238 -0
- qrstream-0.4.1/README.md +241 -0
- qrstream-0.4.1/benchmarks/benchmark.py +206 -0
- qrstream-0.4.1/main.py +13 -0
- qrstream-0.4.1/pyproject.toml +67 -0
- qrstream-0.4.1/src/qrstream/__init__.py +3 -0
- qrstream-0.4.1/src/qrstream/__main__.py +5 -0
- qrstream-0.4.1/src/qrstream/cli.py +144 -0
- qrstream-0.4.1/src/qrstream/decoder.py +876 -0
- qrstream-0.4.1/src/qrstream/encoder.py +323 -0
- qrstream-0.4.1/src/qrstream/lt_codec.py +213 -0
- qrstream-0.4.1/src/qrstream/protocol.py +357 -0
- qrstream-0.4.1/src/qrstream/qr_utils.py +230 -0
- qrstream-0.4.1/tests/test_decoder.py +130 -0
- qrstream-0.4.1/tests/test_lt_codec.py +171 -0
- qrstream-0.4.1/tests/test_optimizations.py +218 -0
- qrstream-0.4.1/tests/test_protocol.py +173 -0
- qrstream-0.4.1/tests/test_roundtrip.py +171 -0
- qrstream-0.4.1/uv.lock +473 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: publish-pypi
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/project/qrstream/
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- name: Check out code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: '3.13'
|
|
27
|
+
|
|
28
|
+
- name: Set up uv
|
|
29
|
+
uses: astral-sh/setup-uv@v6
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
|
|
33
|
+
- name: Build distributions
|
|
34
|
+
run: uv build
|
|
35
|
+
|
|
36
|
+
- name: Publish to PyPI
|
|
37
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- 'dev/**'
|
|
8
|
+
pull_request:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
test:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version:
|
|
21
|
+
- '3.10'
|
|
22
|
+
- '3.11'
|
|
23
|
+
- '3.12'
|
|
24
|
+
- '3.13'
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Check out code
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: ${{ matrix.python-version }}
|
|
34
|
+
|
|
35
|
+
- name: Set up uv
|
|
36
|
+
uses: astral-sh/setup-uv@v6
|
|
37
|
+
with:
|
|
38
|
+
enable-cache: true
|
|
39
|
+
|
|
40
|
+
- name: Install dependencies
|
|
41
|
+
run: uv sync --dev
|
|
42
|
+
|
|
43
|
+
- name: Run tests
|
|
44
|
+
run: uv run pytest tests/ -v
|
|
45
|
+
|
|
46
|
+
- name: Build distributions
|
|
47
|
+
if: matrix.python-version == '3.13'
|
|
48
|
+
run: uv build
|
|
49
|
+
|
|
50
|
+
- name: Upload built distributions
|
|
51
|
+
if: matrix.python-version == '3.13'
|
|
52
|
+
uses: actions/upload-artifact@v4
|
|
53
|
+
with:
|
|
54
|
+
name: python-package-distributions
|
|
55
|
+
path: dist/
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
|
|
9
|
+
# IDE
|
|
10
|
+
.idea/
|
|
11
|
+
.vscode/
|
|
12
|
+
.claude/
|
|
13
|
+
*.swp
|
|
14
|
+
*.swo
|
|
15
|
+
|
|
16
|
+
# CodeBuddy
|
|
17
|
+
.codebuddy/
|
|
18
|
+
|
|
19
|
+
# OS
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
|
|
23
|
+
# Project data (keep locally, exclude from repo)
|
|
24
|
+
inputs/
|
|
25
|
+
outputs/
|
|
26
|
+
output
|
|
27
|
+
skills/
|
|
28
|
+
|
|
29
|
+
# Test / cache
|
|
30
|
+
.pytest_cache/
|
|
31
|
+
*.egg
|
qrstream-0.4.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 David He
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
qrstream-0.4.1/PKG-INFO
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qrstream
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: Encode and decode files via QR code video streams using LT fountain codes
|
|
5
|
+
Project-URL: Homepage, https://github.com/ddddavid-he/qrstream-enhanced
|
|
6
|
+
Project-URL: Repository, https://github.com/ddddavid-he/qrstream-enhanced.git
|
|
7
|
+
Project-URL: Issues, https://github.com/ddddavid-he/qrstream-enhanced/issues
|
|
8
|
+
Author-email: David He <hewei201031l@outlook.com>
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 David He
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: erasure-code,fountain-code,lt-code,luby-transform,opencv,qr-code,video-transfer
|
|
32
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Operating System :: OS Independent
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Topic :: Multimedia :: Video
|
|
42
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
43
|
+
Requires-Python: >=3.10
|
|
44
|
+
Requires-Dist: numpy>=1.20.0
|
|
45
|
+
Requires-Dist: opencv-contrib-python>=4.5.0
|
|
46
|
+
Requires-Dist: qrcode[pil]>=7.0
|
|
47
|
+
Requires-Dist: tqdm>=4.60.0
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# QRStream
|
|
53
|
+
|
|
54
|
+
[中文文档](README-zh.md)
|
|
55
|
+
|
|
56
|
+
Transfer arbitrary files through QR code video streams. Built on **LT Fountain Codes (Luby Transform)** for reliable, feedback-free data transmission — the original file can be fully recovered even if some frames are lost.
|
|
57
|
+
|
|
58
|
+
## How It Works
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Encoder Decoder
|
|
62
|
+
┌──────────┐ LT Fountain ┌──────────┐ Screen cap ┌──────────┐ QR detect ┌──────────┐
|
|
63
|
+
│ File │ ────────────── → │ QR Video │ ──────────── → │ Video │ ────────────→ │ Recovered│
|
|
64
|
+
└──────────┘ zlib + COBS └──────────┘ └──────────┘ LT decode │ File │
|
|
65
|
+
└──────────┘
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
1. **Encode**: Split the file (optionally zlib-compressed) into blocks, generate redundant coded blocks via LT fountain codes, serialize each into a V3 protocol frame, COBS-encode, embed into QR codes, and output an MP4 video.
|
|
69
|
+
2. **Decode**: Extract QR codes from video using WeChatQRCode (highly robust), COBS-decode, CRC32-validate to discard corrupted frames, feed into the LT decoder for belief propagation (peeling), and reconstruct the original file. The decoder auto-detects V2/V3 protocols.
|
|
70
|
+
|
|
71
|
+
**Key Features**:
|
|
72
|
+
- **LT Fountain Codes**: Rateless erasure codes — naturally tolerant of frame loss, blur, and occlusion
|
|
73
|
+
- **COBS Encoding**: Only ~0.4% overhead, saves 33% capacity compared to base64
|
|
74
|
+
- **WeChatQRCode Detector**: Far more robust than standard QR detectors for phone-captured screens (perspective, moire, lighting)
|
|
75
|
+
- **Adaptive Sample Rate**: Automatically selects optimal sampling strategy based on detection rate and frame repetition
|
|
76
|
+
- **Targeted Recovery**: After initial scan, precisely re-scans video segments where missing blocks are expected
|
|
77
|
+
- **Low-Memory Paths**: mmap-backed encoding and streaming decode-to-file for large inputs
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
### From PyPI with pip
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install qrstream
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use either command after installation:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
qrstream <command> [options]
|
|
91
|
+
# or
|
|
92
|
+
qrs <command> [options]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
You can also run it as a module:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m qrstream <command> [options]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### From PyPI with uv
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv tool install qrstream
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Then run:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
qrstream <command> [options]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For one-off execution without a persistent install:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
uvx qrstream <command> [options]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Development Install
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git clone https://github.com/ddddavid-he/qrstream-enhanced.git && cd qrstream-enhanced
|
|
123
|
+
uv sync --dev
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Requirements
|
|
127
|
+
|
|
128
|
+
- Python >= 3.10
|
|
129
|
+
- Dependencies: `opencv-contrib-python`, `numpy`, `tqdm`, `qrcode[pil]`
|
|
130
|
+
|
|
131
|
+
## Usage
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
qrstream <command> [options]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`qrs` is kept as a short alias, and `python -m qrstream` works as well.
|
|
138
|
+
|
|
139
|
+
### Encode (File → QR Video)
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
qrstream encode <file> -o output.mp4 [options]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
| Option | Default | Description |
|
|
146
|
+
|--------|---------|-------------|
|
|
147
|
+
| `<file>` | - | Input file path |
|
|
148
|
+
| `-o, --output` | `<filename>.mp4` | Output video path |
|
|
149
|
+
| `--overhead` | `2.0` | Encoding redundancy ratio (multiple of source block count) |
|
|
150
|
+
| `--fps` | `10` | Output video frame rate |
|
|
151
|
+
| `--ec-level` | `1` | QR error correction: 0=L(7%), 1=M(15%), 2=Q(25%), 3=H(30%) |
|
|
152
|
+
| `--qr-version` | `20` | QR code version 1-40 (higher = denser) |
|
|
153
|
+
| `--no-compress` | - | Disable zlib compression |
|
|
154
|
+
| `--force-compress` | - | Force compression for large V3 inputs (higher memory usage) |
|
|
155
|
+
| `--base64-qr` | - | Use base64 encoding instead of COBS (better compat, 33% less capacity) |
|
|
156
|
+
| `--legacy-qr` | - | Use `qrcode` library for QR generation (slower, finer control) |
|
|
157
|
+
| `--codec` | `mp4v` | Video codec: `mp4v` or `mjpeg` (faster but larger files) |
|
|
158
|
+
| `--protocol` | `v3` | Protocol version: `v3` (default) or `v2` |
|
|
159
|
+
| `-w, --workers` | CPU count | Parallel workers for QR generation |
|
|
160
|
+
| `-v, --verbose` | - | Print extra detail (progress bars always shown) |
|
|
161
|
+
|
|
162
|
+
### Decode (QR Video → File)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
qrstream decode <video> -o output_file [options]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
| Option | Default | Description |
|
|
169
|
+
|--------|---------|-------------|
|
|
170
|
+
| `<video>` | - | Input video path (MP4, MOV, etc.) |
|
|
171
|
+
| `-o, --output` | `decoded_output` | Output file path |
|
|
172
|
+
| `-s, --sample-rate` | `0` (auto) | Sample every Nth frame (0 = adaptive probing) |
|
|
173
|
+
| `-w, --workers` | All CPU cores | Parallel workers for QR detection |
|
|
174
|
+
| `-v, --verbose` | - | Print detailed progress |
|
|
175
|
+
|
|
176
|
+
### Examples
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Encode a PDF (default: COBS binary mode, 2x redundancy)
|
|
180
|
+
qrstream encode report.pdf -o report.mp4 --overhead 2.0 -v
|
|
181
|
+
|
|
182
|
+
# Decode video (adaptive sample rate + targeted recovery)
|
|
183
|
+
qrstream decode report.mp4 -o report_recovered.pdf -v
|
|
184
|
+
|
|
185
|
+
# Encode with high error correction (for phone screen capture)
|
|
186
|
+
qrstream encode data.bin -o data.mp4 --ec-level 3 --qr-version 15
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Python API
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
from qrstream.encoder import encode_to_video
|
|
193
|
+
from qrstream.decoder import extract_qr_from_video, decode_blocks, decode_blocks_to_file
|
|
194
|
+
|
|
195
|
+
# Encode (default: COBS binary mode)
|
|
196
|
+
encode_to_video("input.bin", "output.mp4", overhead=2.0, verbose=True)
|
|
197
|
+
|
|
198
|
+
# Decode to memory
|
|
199
|
+
blocks = extract_qr_from_video("output.mp4", verbose=True)
|
|
200
|
+
result = decode_blocks(blocks, verbose=True)
|
|
201
|
+
|
|
202
|
+
# Better for large files: stream directly to file with incremental decompression
|
|
203
|
+
written = decode_blocks_to_file(blocks, "recovered.bin", verbose=True)
|
|
204
|
+
print(f"wrote {written} bytes")
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Project Structure
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
project-root/
|
|
211
|
+
├── pyproject.toml # Project config & dependencies
|
|
212
|
+
├── src/qrstream/
|
|
213
|
+
│ ├── cli.py # CLI entry (encode/decode subcommands)
|
|
214
|
+
│ ├── encoder.py # LT encode → QR frame generation → MP4 video
|
|
215
|
+
│ ├── decoder.py # Video frame extraction → QR detect → LT decode → file rebuild
|
|
216
|
+
│ ├── lt_codec.py # LT fountain code primitives (PRNG, RSD, BlockGraph)
|
|
217
|
+
│ ├── protocol.py # V2/V3 protocol serialization + COBS codec
|
|
218
|
+
│ └── qr_utils.py # QR generation (OpenCV) + detection (WeChatQRCode)
|
|
219
|
+
├── tests/
|
|
220
|
+
│ ├── test_lt_codec.py # LT codec unit tests
|
|
221
|
+
│ ├── test_protocol.py # V2/V3 protocol + COBS tests
|
|
222
|
+
│ ├── test_decoder.py # Decoder validation + probe strategy tests
|
|
223
|
+
│ ├── test_roundtrip.py # End-to-end roundtrip tests
|
|
224
|
+
│ └── test_optimizations.py # Perf optimizations + WeChatQR + COBS tests
|
|
225
|
+
└── benchmarks/
|
|
226
|
+
└── benchmark.py # Performance benchmarks
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Technical Details
|
|
230
|
+
|
|
231
|
+
### V3 Protocol Format (24-byte header + 4-byte trailing CRC)
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
Offset Size Field
|
|
235
|
+
0 1 version 0x03
|
|
236
|
+
1 1 flags bit0=zlib compressed, bit1=COBS binary mode
|
|
237
|
+
2 8 filesize uint64 BE (encoded payload size; compressed size when zlib is on)
|
|
238
|
+
10 2 blocksize uint16 BE
|
|
239
|
+
12 4 block_count uint32 BE K = ceil(filesize / blocksize)
|
|
240
|
+
16 4 seed uint32 BE PRNG seed
|
|
241
|
+
20 2 block_seq uint16 BE monotonically increasing sequence number
|
|
242
|
+
22 2 reserved reserved (currently 0)
|
|
243
|
+
24 ... data blocksize bytes of encoded data
|
|
244
|
+
... 4 crc32 CRC32(header[0:24] + data)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- Default encoding uses **V3**.
|
|
248
|
+
- The decoder auto-detects **V2** and **V3**.
|
|
249
|
+
- V3 extends `filesize` to `uint64` and `block_count` to `uint32`, supporting larger files and block counts.
|
|
250
|
+
|
|
251
|
+
### Encoding Modes
|
|
252
|
+
|
|
253
|
+
| Mode | QR Content | Capacity Overhead | Default |
|
|
254
|
+
|------|-----------|-------------------|---------|
|
|
255
|
+
| COBS binary | raw bytes → COBS → latin-1 string | ~0.4% | Yes |
|
|
256
|
+
| Base64 | raw bytes → base64 string | ~33% | No (`--base64-qr`) |
|
|
257
|
+
|
|
258
|
+
COBS (Consistent Overhead Byte Stuffing) eliminates all `\x00` bytes, allowing binary data to safely pass through QR string interfaces.
|
|
259
|
+
|
|
260
|
+
### Large Files & Low-Memory Paths
|
|
261
|
+
|
|
262
|
+
- For large **V3** inputs, the encoder uses `mmap` for random access, avoiding loading the entire file into memory.
|
|
263
|
+
- When the input is large enough, V3 encoding automatically disables `zlib` compression to preserve the low-memory path; use `--force-compress` to override.
|
|
264
|
+
- The decoder supports streaming writes with incremental decompression, reducing memory overhead.
|
|
265
|
+
- Large file decoding shows **LT block decoding progress** and **output write progress** bars.
|
|
266
|
+
|
|
267
|
+
### Decoding Pipeline
|
|
268
|
+
|
|
269
|
+
1. **Probe phase**: Sample 3 spread-out windows in the video (120 frames each by default), measure detection rate and repetition per window, pick the most conservative `sample_rate`
|
|
270
|
+
2. **Main scan**: Detect QR codes in parallel at the adaptive sample rate, feeding into the LT decoder in real time
|
|
271
|
+
3. **Targeted recovery**: If the first pass didn't recover all blocks, use linear regression on observed (seed, frame) pairs to locate missing seeds and re-scan those segments precisely
|
|
272
|
+
4. **LT decode**: Belief propagation (peeling) to recover all source blocks
|
|
273
|
+
5. **Output writeback**: Write recovered blocks sequentially; incremental decompression in compressed mode
|
|
274
|
+
|
|
275
|
+
### LT Fountain Code Parameters
|
|
276
|
+
|
|
277
|
+
| Parameter | Value | Notes |
|
|
278
|
+
|-----------|-------|-------|
|
|
279
|
+
| Degree distribution | Robust Soliton Distribution | c=0.1, delta=0.5 |
|
|
280
|
+
| PRNG | LCG (a=16807, m=2^31-1) | 5 warmup rounds to eliminate sequential seed bias |
|
|
281
|
+
| XOR | numpy vectorized + in-place | 10-50x faster than pure Python |
|
|
282
|
+
| Decoding | Belief Propagation (Peeling) | Iterative elimination on bipartite graph |
|
|
283
|
+
|
|
284
|
+
## Testing
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
uv run pytest tests/ -v
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
MIT
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# QRStream
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
通过 QR 码视频流传输任意文件。基于 **LT 喷泉码(Luby Transform Fountain Codes)** 实现可靠的无反馈信道数据传输——即使丢失部分帧也能完整恢复原始文件。
|
|
6
|
+
|
|
7
|
+
## 原理概览
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
编码端 解码端
|
|
11
|
+
┌──────────┐ LT 喷泉码 ┌──────────┐ 录屏/拍摄 ┌──────────┐ QR 识别 ┌──────────┐
|
|
12
|
+
│ 原始文件 │ ──────────── → │ QR 码视频 │ ──────────→ │ 视频文件 │ ──────────→ │ 还原文件 │
|
|
13
|
+
└──────────┘ zlib + COBS └──────────┘ └──────────┘ LT 解码 └──────────┘
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
1. **编码**:将文件(可选 zlib 压缩)分块,通过 LT 喷泉码生成冗余编码块,每块序列化为 V3 协议帧,经 COBS 编码后嵌入 QR 码,最终输出 MP4 视频。
|
|
17
|
+
2. **解码**:使用 WeChatQRCode 从视频中高鲁棒性地提取 QR 码,COBS 解码后 CRC32 校验去除损坏帧,喂入 LT 解码器进行信念传播(peeling),恢复所有源块后重建原始文件。解码端会自动兼容 V2/V3 协议。
|
|
18
|
+
|
|
19
|
+
**核心优势**:
|
|
20
|
+
- **LT 喷泉码**:无码率纠删码,天然容忍帧丢失、模糊、遮挡
|
|
21
|
+
- **COBS 编码**:仅 0.4% overhead,比 base64 节省 33% 容量
|
|
22
|
+
- **WeChatQRCode 检测器**:对手机拍摄场景(透视、摩尔纹、光照)鲁棒性远超标准 QR 检测器
|
|
23
|
+
- **自适应采样率**:根据检测率和帧重复数自动选择最优采样策略
|
|
24
|
+
- **定向恢复**:首轮扫描后针对缺失块的时间位置精准补扫
|
|
25
|
+
|
|
26
|
+
## 安装
|
|
27
|
+
|
|
28
|
+
### 通过 pip 从 PyPI 安装
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install qrstream
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
安装后可直接使用以下任一命令:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
qrstream <command> [options]
|
|
38
|
+
# 或
|
|
39
|
+
qrs <command> [options]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
也可以通过模块方式运行:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python -m qrstream <command> [options]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 通过 uv 从 PyPI 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv tool install qrstream
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
安装后运行:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
qrstream <command> [options]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
如果只想临时执行而不常驻安装:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uvx qrstream <command> [options]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 开发环境安装
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/ddddavid-he/qrstream-enhanced.git && cd qrstream-enhanced
|
|
70
|
+
uv sync --dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 系统要求
|
|
74
|
+
|
|
75
|
+
- Python >= 3.10
|
|
76
|
+
- 依赖:`opencv-contrib-python`, `numpy`, `tqdm`, `qrcode[pil]`
|
|
77
|
+
|
|
78
|
+
## 使用方式
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
qrstream <command> [options]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
同时保留 `qrs` 这个短命令别名,也支持 `python -m qrstream`。
|
|
85
|
+
|
|
86
|
+
### 编码(文件 → QR 码视频)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
qrstream encode <file> -o output.mp4 [options]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| 参数 | 默认值 | 说明 |
|
|
93
|
+
|------|--------|------|
|
|
94
|
+
| `<file>` | - | 输入文件路径 |
|
|
95
|
+
| `-o, --output` | `<filename>.mp4` | 输出视频路径 |
|
|
96
|
+
| `--overhead` | `2.0` | 编码冗余倍率(源块数的倍数) |
|
|
97
|
+
| `--fps` | `10` | 输出视频帧率 |
|
|
98
|
+
| `--ec-level` | `1` | QR 纠错等级:0=L(7%), 1=M(15%), 2=Q(25%), 3=H(30%) |
|
|
99
|
+
| `--qr-version` | `20` | QR 码版本 1-40(越大密度越高) |
|
|
100
|
+
| `--no-compress` | - | 禁用 zlib 压缩 |
|
|
101
|
+
| `--force-compress` | - | 对大文件的 V3 编码强制整体压缩(会占用更多内存) |
|
|
102
|
+
| `--base64-qr` | - | 使用 base64 编码代替 COBS(兼容性更好但容量少 33%) |
|
|
103
|
+
| `--legacy-qr` | - | 使用 qrcode 库生成 QR(更慢但参数控制更精细) |
|
|
104
|
+
| `--codec` | `mp4v` | 视频编码器:`mp4v` 或 `mjpeg`(更快但文件更大) |
|
|
105
|
+
| `--protocol` | `v3` | 编码协议版本:`v3`(默认)或 `v2` |
|
|
106
|
+
| `-w, --workers` | CPU 核心数 | 并行 QR 生成的工作进程数 |
|
|
107
|
+
| `-v, --verbose` | - | 输出额外详细信息(进度条始终显示) |
|
|
108
|
+
|
|
109
|
+
### 解码(QR 码视频 → 文件)
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
qrstream decode <video> -o output_file [options]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| 参数 | 默认值 | 说明 |
|
|
116
|
+
|------|--------|------|
|
|
117
|
+
| `<video>` | - | 输入视频路径(MP4, MOV 等) |
|
|
118
|
+
| `-o, --output` | `decoded_output` | 输出文件路径 |
|
|
119
|
+
| `-s, --sample-rate` | `0`(自动) | 每 N 帧采样一次(0=自适应探测) |
|
|
120
|
+
| `-w, --workers` | 全部 CPU 核心 | 并行 QR 识别的工作进程数 |
|
|
121
|
+
| `-v, --verbose` | - | 输出详细进度信息;大任务会显示 probe、扫描、LT 解码和写文件进度 |
|
|
122
|
+
|
|
123
|
+
### 示例
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# 编码 PDF 文件(默认 COBS 二进制模式,2 倍冗余)
|
|
127
|
+
qrstream encode report.pdf -o report.mp4 --overhead 2.0 -v
|
|
128
|
+
|
|
129
|
+
# 解码视频(自适应采样率 + 定向恢复)
|
|
130
|
+
qrstream decode report.mp4 -o report_recovered.pdf -v
|
|
131
|
+
|
|
132
|
+
# 编码时使用高纠错等级(适合手机拍屏场景)
|
|
133
|
+
qrstream encode data.bin -o data.mp4 --ec-level 3 --qr-version 15
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 编程接口
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from qrstream.encoder import encode_to_video
|
|
140
|
+
from qrstream.decoder import extract_qr_from_video, decode_blocks, decode_blocks_to_file
|
|
141
|
+
|
|
142
|
+
# 编码(默认使用 COBS 二进制模式)
|
|
143
|
+
encode_to_video("input.bin", "output.mp4", overhead=2.0, verbose=True)
|
|
144
|
+
|
|
145
|
+
# 解码到内存
|
|
146
|
+
blocks = extract_qr_from_video("output.mp4", verbose=True)
|
|
147
|
+
result = decode_blocks(blocks, verbose=True)
|
|
148
|
+
|
|
149
|
+
# 更适合大文件:直接写文件,降低额外内存占用
|
|
150
|
+
written = decode_blocks_to_file(blocks, "recovered.bin", verbose=True)
|
|
151
|
+
print(f"wrote {written} bytes")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 项目结构
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
project-root/
|
|
158
|
+
├── pyproject.toml # 项目配置与依赖
|
|
159
|
+
├── src/qrstream/
|
|
160
|
+
│ ├── cli.py # CLI 入口(encode/decode 子命令)
|
|
161
|
+
│ ├── encoder.py # LT 编码 → QR 帧生成 → MP4 视频写入
|
|
162
|
+
│ ├── decoder.py # 视频帧提取 → QR 检测 → LT 解码 → 文件重建
|
|
163
|
+
│ ├── lt_codec.py # LT 喷泉码原语(PRNG、RSD、BlockGraph)
|
|
164
|
+
│ ├── protocol.py # V2/V3 协议序列化 + COBS 编解码
|
|
165
|
+
│ └── qr_utils.py # QR 生成(OpenCV)+ 检测(WeChatQRCode)
|
|
166
|
+
├── tests/
|
|
167
|
+
│ ├── test_lt_codec.py # LT 编解码器单元测试
|
|
168
|
+
│ ├── test_protocol.py # V2/V3 协议 + COBS 测试
|
|
169
|
+
│ ├── test_roundtrip.py # 端到端回环测试
|
|
170
|
+
│ └── test_optimizations.py # 性能优化 + WeChatQR + COBS 测试
|
|
171
|
+
└── benchmarks/
|
|
172
|
+
└── benchmark.py # 性能基准测试
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 技术细节
|
|
176
|
+
|
|
177
|
+
### V3 协议格式(24 字节头部 + 4 字节尾部 CRC)
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
Offset Size Field
|
|
181
|
+
0 1 version 0x03
|
|
182
|
+
1 1 flags bit0=zlib 压缩, bit1=COBS 二进制模式
|
|
183
|
+
2 8 filesize uint64 BE(编码载荷大小;压缩时为压缩后大小)
|
|
184
|
+
10 2 blocksize uint16 BE
|
|
185
|
+
12 4 block_count uint32 BE K = ceil(filesize / blocksize)
|
|
186
|
+
16 4 seed uint32 BE PRNG 种子
|
|
187
|
+
20 2 block_seq uint16 BE 单调递增序号
|
|
188
|
+
22 2 reserved 预留(当前为 0)
|
|
189
|
+
24 ... data blocksize 字节的编码数据
|
|
190
|
+
... 4 crc32 CRC32(header[0:24] + data)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
- 默认编码使用 **V3**。
|
|
194
|
+
- 解码器会自动兼容 **V2** 和 **V3**。
|
|
195
|
+
- V3 将 `filesize` 扩展为 `uint64`,`block_count` 扩展为 `uint32`,适合更大的文件和块数。
|
|
196
|
+
|
|
197
|
+
### 编码模式
|
|
198
|
+
|
|
199
|
+
| 模式 | QR 内容 | 容量开销 | 默认 |
|
|
200
|
+
|------|---------|----------|------|
|
|
201
|
+
| COBS 二进制 | raw bytes → COBS → latin-1 string | ~0.4% | 是 |
|
|
202
|
+
| Base64 | raw bytes → base64 string | ~33% | 否(`--base64-qr`) |
|
|
203
|
+
|
|
204
|
+
COBS(Consistent Overhead Byte Stuffing)消除所有 `\x00` 字节,使数据可安全通过 QR 字符串接口传递。
|
|
205
|
+
|
|
206
|
+
### 大文件与低内存路径
|
|
207
|
+
|
|
208
|
+
- 对于较大的 **V3** 输入文件,编码端会优先使用 `mmap` 做随机访问,避免把原文件整体复制进内存。
|
|
209
|
+
- 当输入足够大时,V3 编码默认会关闭整体 `zlib` 压缩,以保留低内存路径;如需强制压缩可使用 `--force-compress`。
|
|
210
|
+
- 解码端在恢复完成后支持直接写文件,并在压缩模式下使用增量解压,降低额外内存占用。
|
|
211
|
+
- 大文件解码会额外显示 **LT block 解码进度** 和 **输出写入进度**,避免在提取 QR 完成后长时间无输出。
|
|
212
|
+
|
|
213
|
+
### 解码管线
|
|
214
|
+
|
|
215
|
+
1. **探测阶段**:在视频中段的 3 个分散窗口中采样(默认每窗 120 帧),分别测量检测率和重复度,并取最保守的 `sample_rate`
|
|
216
|
+
2. **主扫描**:按自适应采样率并行检测 QR 码,实时喂入 LT 解码器
|
|
217
|
+
3. **定向恢复**:若首轮未恢复完整,定位缺失 seed 对应的视频时间段精准补扫
|
|
218
|
+
4. **LT 解码**:信念传播(peeling)算法恢复所有源块,并对大任务显示 block 解码进度
|
|
219
|
+
5. **输出写回**:按序写回恢复块;压缩模式下使用增量解压,并显示写文件进度
|
|
220
|
+
|
|
221
|
+
### LT 喷泉码参数
|
|
222
|
+
|
|
223
|
+
| 参数 | 值 | 说明 |
|
|
224
|
+
|------|-----|------|
|
|
225
|
+
| 度分布 | Robust Soliton Distribution | c=0.1, delta=0.5 |
|
|
226
|
+
| PRNG | LCG (a=16807, m=2^31-1) | 5 轮预热消除序列种子偏差 |
|
|
227
|
+
| XOR | numpy 向量化 + 原地操作 | 比纯 Python 快 10-50x |
|
|
228
|
+
| 解码 | Belief Propagation (Peeling) | 基于二部图的迭代消元 |
|
|
229
|
+
|
|
230
|
+
## 测试
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
uv run pytest tests/ -v
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 许可证
|
|
237
|
+
|
|
238
|
+
MIT
|