framelock 0.3.0__py3-none-any.whl
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.
- framelock/__init__.py +115 -0
- framelock/__main__.py +6 -0
- framelock/_compat.py +49 -0
- framelock/assets/chirps/00_reference_linear_ramp_chirp.wav +0 -0
- framelock/assets/chirps/01_hidden_chirp_water_ringtone.wav +0 -0
- framelock/assets/chirps/02_glass_plink_hidden_probe.wav +0 -0
- framelock/assets/chirps/03_bubble_code_microchirps.wav +0 -0
- framelock/assets/chirps/04_tiny_sparkle_notification_good_sync.wav +0 -0
- framelock/assets/chirps/05_natural_water_wood_phrase_no_obvious_ramp.wav +0 -0
- framelock/audioalign.py +1068 -0
- framelock/chirps.py +679 -0
- framelock/cli.py +349 -0
- framelock/clock.py +53 -0
- framelock/controls.py +247 -0
- framelock/correspondence.py +765 -0
- framelock/diagnostics.py +643 -0
- framelock/odometry.py +374 -0
- framelock/preview.py +591 -0
- framelock/registration/__init__.py +183 -0
- framelock/registration/_se3.py +81 -0
- framelock/registration/acoustic.py +517 -0
- framelock/registration/board.py +571 -0
- framelock/registration/cli.py +268 -0
- framelock/registration/store.py +252 -0
- framelock/registration/tagcli.py +127 -0
- framelock/registration/tags.py +793 -0
- framelock/registration/visual.py +171 -0
- framelock/registration/wave.py +1242 -0
- framelock/session.py +1781 -0
- framelock/soundspeed.py +370 -0
- framelock/sources/__init__.py +6 -0
- framelock/sources/base.py +177 -0
- framelock/sources/mic.py +356 -0
- framelock/sources/oak.py +1520 -0
- framelock/sources/phonedata.py +559 -0
- framelock/sources/rtsp.py +778 -0
- framelock/sync.py +242 -0
- framelock/viz.py +931 -0
- framelock-0.3.0.dist-info/METADATA +283 -0
- framelock-0.3.0.dist-info/RECORD +43 -0
- framelock-0.3.0.dist-info/WHEEL +4 -0
- framelock-0.3.0.dist-info/entry_points.txt +9 -0
- framelock-0.3.0.dist-info/licenses/LICENSE +21 -0
framelock/__init__.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Synchronized multi-camera recording.
|
|
2
|
+
|
|
3
|
+
Compose a recording session from heterogeneous sources — OAK-D devices
|
|
4
|
+
(all three cameras, hardware-synced where possible), RTSP streams (e.g. an
|
|
5
|
+
iPhone camera app), and anything else that can produce timestamped frames —
|
|
6
|
+
and record them all into one session folder with per-device subfolders,
|
|
7
|
+
per-frame timestamps, and cross-device sync groups.
|
|
8
|
+
|
|
9
|
+
from framelock import Session, OakD, RtspCamera, Ramp
|
|
10
|
+
|
|
11
|
+
oak = OakD(shutter_sync=True, shutter=1/125, iso=800)
|
|
12
|
+
phone = RtspCamera("rtsp://192.168.1.23:8554/live", name="iphone")
|
|
13
|
+
|
|
14
|
+
with Session("recordings", name="take1", warmup="auto") as session:
|
|
15
|
+
session.record(oak, phone)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from framelock.audioalign import AirConditions, AlignmentResult, align_session
|
|
22
|
+
from framelock.soundspeed import SoundModel
|
|
23
|
+
from framelock.clock import ClockMap
|
|
24
|
+
from framelock.correspondence import Correspondence, write_correspondence
|
|
25
|
+
from framelock.controls import (
|
|
26
|
+
Automation, Control, ShutterFunc, ShutterRamp, ShutterStep,
|
|
27
|
+
FocusFunc, FocusRamp, FocusStep, Func, Interpolation, IsoFunc, IsoRamp,
|
|
28
|
+
IsoStep, Ramp, Step, ZoomFunc, ZoomRamp, ZoomStep,
|
|
29
|
+
)
|
|
30
|
+
from framelock.session import Session, Warmup
|
|
31
|
+
from framelock.sources.base import Source, SyncSample
|
|
32
|
+
from framelock.sources.mic import Microphone
|
|
33
|
+
from framelock.sources.oak import (
|
|
34
|
+
ExternalSync, OakD, Resolution, VideoFormat,
|
|
35
|
+
)
|
|
36
|
+
from framelock.sources.rtsp import RtspCamera, Transport
|
|
37
|
+
from framelock.sync import SyncGroup, Synchronizer
|
|
38
|
+
from framelock.chirps import (
|
|
39
|
+
BubbleCodeMicro,
|
|
40
|
+
GlassPlinkHidden,
|
|
41
|
+
HiddenChirpWater,
|
|
42
|
+
MLS,
|
|
43
|
+
NaturalWaterWood,
|
|
44
|
+
ReferenceLinearRamp,
|
|
45
|
+
Sweep,
|
|
46
|
+
Chirp,
|
|
47
|
+
TinySparkle,
|
|
48
|
+
ChirpKind,
|
|
49
|
+
Velvet,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Lazy imports (PEP 562): importing framelock stays instant and does not
|
|
53
|
+
# pull in depthai/av until the corresponding source is actually used.
|
|
54
|
+
_EXPORTS = {
|
|
55
|
+
"ClockMap": "framelock.clock",
|
|
56
|
+
"Correspondence": "framelock.correspondence",
|
|
57
|
+
"write_correspondence": "framelock.correspondence",
|
|
58
|
+
"Automation": "framelock.controls",
|
|
59
|
+
"Control": "framelock.controls",
|
|
60
|
+
"Interpolation": "framelock.controls",
|
|
61
|
+
"Func": "framelock.controls",
|
|
62
|
+
"Ramp": "framelock.controls",
|
|
63
|
+
"Step": "framelock.controls",
|
|
64
|
+
"ZoomRamp": "framelock.controls",
|
|
65
|
+
"ZoomFunc": "framelock.controls",
|
|
66
|
+
"ZoomStep": "framelock.controls",
|
|
67
|
+
"FocusRamp": "framelock.controls",
|
|
68
|
+
"FocusFunc": "framelock.controls",
|
|
69
|
+
"FocusStep": "framelock.controls",
|
|
70
|
+
"ShutterRamp": "framelock.controls",
|
|
71
|
+
"ShutterFunc": "framelock.controls",
|
|
72
|
+
"ShutterStep": "framelock.controls",
|
|
73
|
+
"IsoRamp": "framelock.controls",
|
|
74
|
+
"IsoFunc": "framelock.controls",
|
|
75
|
+
"IsoStep": "framelock.controls",
|
|
76
|
+
"Session": "framelock.session",
|
|
77
|
+
"Warmup": "framelock.session",
|
|
78
|
+
"Source": "framelock.sources.base",
|
|
79
|
+
"SyncSample": "framelock.sources.base",
|
|
80
|
+
"Microphone": "framelock.sources.mic",
|
|
81
|
+
"OakD": "framelock.sources.oak",
|
|
82
|
+
"Resolution": "framelock.sources.oak",
|
|
83
|
+
"VideoFormat": "framelock.sources.oak",
|
|
84
|
+
"ExternalSync": "framelock.sources.oak",
|
|
85
|
+
"RtspCamera": "framelock.sources.rtsp",
|
|
86
|
+
"Transport": "framelock.sources.rtsp",
|
|
87
|
+
"SyncGroup": "framelock.sync",
|
|
88
|
+
"Synchronizer": "framelock.sync",
|
|
89
|
+
"Chirp": "framelock.chirps",
|
|
90
|
+
"MLS": "framelock.chirps",
|
|
91
|
+
"Velvet": "framelock.chirps",
|
|
92
|
+
"Sweep": "framelock.chirps",
|
|
93
|
+
"ReferenceLinearRamp": "framelock.chirps",
|
|
94
|
+
"HiddenChirpWater": "framelock.chirps",
|
|
95
|
+
"GlassPlinkHidden": "framelock.chirps",
|
|
96
|
+
"BubbleCodeMicro": "framelock.chirps",
|
|
97
|
+
"TinySparkle": "framelock.chirps",
|
|
98
|
+
"NaturalWaterWood": "framelock.chirps",
|
|
99
|
+
"ChirpKind": "framelock.chirps",
|
|
100
|
+
"AirConditions": "framelock.audioalign",
|
|
101
|
+
"SoundModel": "framelock.soundspeed",
|
|
102
|
+
"align_session": "framelock.audioalign",
|
|
103
|
+
"AlignmentResult": "framelock.audioalign",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
__all__ = sorted(_EXPORTS)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def __getattr__(name: str):
|
|
110
|
+
module = _EXPORTS.get(name)
|
|
111
|
+
if module is None:
|
|
112
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
113
|
+
import importlib
|
|
114
|
+
|
|
115
|
+
return getattr(importlib.import_module(module), name)
|
framelock/__main__.py
ADDED
framelock/_compat.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Environment quirks, contained.
|
|
2
|
+
|
|
3
|
+
macOS + opencv-python + PyAV: each wheel bundles its OWN copy of FFmpeg,
|
|
4
|
+
and when the second library loads, the Objective-C runtime prints
|
|
5
|
+
duplicate-class warnings for FFmpeg's AVFoundation capture classes
|
|
6
|
+
(AVFFrameReceiver / AVFAudioReceiver):
|
|
7
|
+
|
|
8
|
+
objc[…]: Class AVFFrameReceiver is implemented in both … libavdevice …
|
|
9
|
+
|
|
10
|
+
Scary wording, benign here: those classes belong to libavdevice's camera
|
|
11
|
+
capture, which framelock never uses through either library (we read and
|
|
12
|
+
write files; live capture goes through DepthAI and RTSP). The wheels
|
|
13
|
+
double-bundling is upstream's to fix; the noise is ours to silence — by
|
|
14
|
+
importing both libraries together, early, with stderr muted at the file
|
|
15
|
+
descriptor level (the objc runtime writes straight to fd 2, so Python's
|
|
16
|
+
sys.stderr redirection cannot catch it).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import contextlib
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@contextlib.contextmanager
|
|
27
|
+
def _fd_stderr_silenced():
|
|
28
|
+
saved = os.dup(2)
|
|
29
|
+
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
30
|
+
try:
|
|
31
|
+
os.dup2(devnull, 2)
|
|
32
|
+
yield
|
|
33
|
+
finally:
|
|
34
|
+
os.dup2(saved, 2)
|
|
35
|
+
os.close(saved)
|
|
36
|
+
os.close(devnull)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def preload_media_libs() -> None:
|
|
40
|
+
"""Import av and cv2 up front, muting the macOS duplicate-FFmpeg
|
|
41
|
+
warnings their combined load triggers. Call at CLI entry points; a
|
|
42
|
+
real ImportError still propagates (raised, not printed)."""
|
|
43
|
+
if sys.platform != "darwin":
|
|
44
|
+
return
|
|
45
|
+
with _fd_stderr_silenced():
|
|
46
|
+
with contextlib.suppress(ImportError):
|
|
47
|
+
import av # noqa: F401
|
|
48
|
+
with contextlib.suppress(ImportError):
|
|
49
|
+
import cv2 # noqa: F401
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|