obsbot-mcp 0.1.1 → 0.3.0
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.
- package/README.md +77 -9
- package/dist/capture/ffmpeg-args.d.ts +36 -2
- package/dist/capture/ffmpeg-args.js +137 -4
- package/dist/capture/ffmpeg-args.js.map +1 -1
- package/dist/capture/manager.d.ts +13 -1
- package/dist/capture/manager.js +125 -17
- package/dist/capture/manager.js.map +1 -1
- package/dist/codec/commands.d.ts +10 -0
- package/dist/codec/commands.js +21 -0
- package/dist/codec/commands.js.map +1 -1
- package/dist/device/manager.d.ts +1 -0
- package/dist/device/manager.js +29 -4
- package/dist/device/manager.js.map +1 -1
- package/dist/mcp/tools.js +21 -11
- package/dist/mcp/tools.js.map +1 -1
- package/dist/transport/helper-process.js +5 -1
- package/dist/transport/helper-process.js.map +1 -1
- package/dist/transport/linux.d.ts +40 -0
- package/dist/transport/linux.js +66 -0
- package/dist/transport/linux.js.map +1 -0
- package/dist/transport/macos.d.ts +34 -0
- package/dist/transport/macos.js +62 -0
- package/dist/transport/macos.js.map +1 -0
- package/native/prebuilt/darwin-arm64/obsbot-helper +0 -0
- package/native/prebuilt/darwin-x64/obsbot-helper +0 -0
- package/native/prebuilt/linux-x64/obsbot-helper +0 -0
- package/native/prebuilt/win32-x64/obsbot-helper.exe +0 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -127,10 +127,78 @@ need ffmpeg — it grabs the frame through the native helper.
|
|
|
127
127
|
|
|
128
128
|
- **Windows x64** — supported today. The native helper is built from source in `native/windows/`
|
|
129
129
|
(CMake + MSVC); the published npm package ships a prebuilt binary so end users need no toolchain.
|
|
130
|
-
- **Linux
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
- **Linux x64** — supported from v0.2. The native helper is in `native/linux/` (CMake + GCC);
|
|
131
|
+
it uses **V4L2** for standard UVC controls (zoom, focus, exposure, pan/tilt, white balance,
|
|
132
|
+
image controls) and `UVCIOC_CTRL_QUERY` for vendor Extension Unit commands (gimbal, AI tracking,
|
|
133
|
+
wake/sleep, HDR, FOV). Snapshots capture a MJPEG or YUYV frame via V4L2 mmap streaming and encode
|
|
134
|
+
to JPEG using **libjpeg**. The `linux-x64` prebuilt binary ships with the published npm package.
|
|
135
|
+
Build dependencies: `build-essential cmake libjpeg-dev libv4l-dev`.
|
|
136
|
+
- **macOS 14+ (Apple Silicon and Intel)** — supported. The native helper is in `native/macos/`
|
|
137
|
+
(Objective-C + **IOKit**/**AVFoundation**). It uses IOKit USB control transfers for both standard
|
|
138
|
+
UVC controls and vendor Extension Unit commands, and AVFoundation for enumeration and snapshots.
|
|
139
|
+
Both `darwin-arm64` and `darwin-x64` prebuilt binaries ship with the published npm package
|
|
140
|
+
(`darwin-x64` also covers Apple Silicon running Node under Rosetta, where `process.arch` reports
|
|
141
|
+
`x64`). macOS 14 is the floor because the helper uses `AVCaptureDeviceTypeExternal`; the build
|
|
142
|
+
pins `-mmacosx-version-min` so the binary does not inherit the build machine's OS as its
|
|
143
|
+
minimum.
|
|
144
|
+
|
|
145
|
+
Note on macOS specifically: `UVCAssistant` (a DriverKit system extension) owns the camera's UVC
|
|
146
|
+
*interfaces* exclusively, so `USBInterfaceOpen` — and even `USBInterfaceOpenSeize` — fail with
|
|
147
|
+
`kIOReturnExclusiveAccess`. The helper therefore opens the USB *device*, which is not locked, and
|
|
148
|
+
issues UVC control requests on its default control endpoint. This coexists with `UVCAssistant`:
|
|
149
|
+
the camera keeps working as a normal webcam while under control, so no driver-replacement step
|
|
150
|
+
is needed.
|
|
151
|
+
|
|
152
|
+
### Building the native helper (Linux)
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
cd native/linux
|
|
156
|
+
mkdir build && cd build
|
|
157
|
+
cmake ..
|
|
158
|
+
make -j$(nproc)
|
|
159
|
+
make install # copies to native/prebuilt/linux-x64/
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Building the native helper (macOS)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
make -C native/macos # -> native/prebuilt/darwin-arm64/obsbot-helper
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Requires the Xcode command line tools. CMake works too (`cmake -S native/macos -B
|
|
169
|
+
native/macos/build && cmake --build native/macos/build`), which is what CI uses.
|
|
170
|
+
|
|
171
|
+
## Known limitations
|
|
172
|
+
|
|
173
|
+
What has actually been exercised against hardware, and what hasn't:
|
|
174
|
+
|
|
175
|
+
| Platform | Status |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `win32-x64` | Builds in CI |
|
|
178
|
+
| `linux-x64` | Builds in CI |
|
|
179
|
+
| `darwin-arm64` | **Hardware-verified** — control, gimbal, zoom, and snapshot on a real Tiny 2 |
|
|
180
|
+
| `darwin-x64` | **Build-verified only** — compiles with the right architecture and deployment target, never executed |
|
|
181
|
+
|
|
182
|
+
- **The Intel (`darwin-x64`) helper has never been run.** No Intel Mac was available to test it. It
|
|
183
|
+
cross-compiles cleanly and is packaged, but nothing has confirmed it talks to a camera. It also
|
|
184
|
+
covers Apple Silicon running Node under Rosetta, where `process.arch` reports `x64` — likewise
|
|
185
|
+
untested. Reports from Intel users are welcome.
|
|
186
|
+
- **macOS 14 or newer is required**, and macOS runtime is verified on **26.5 only**. The helper uses
|
|
187
|
+
`AVCaptureDeviceTypeExternal` (macOS 14+), so the build pins `-mmacosx-version-min=14.0`. The
|
|
188
|
+
binary will *load* on 14 through 25, but behavior there is untested — in particular the UVC
|
|
189
|
+
control path relies on `UVCAssistant` holding the camera's UVC interfaces while leaving the USB
|
|
190
|
+
device itself openable. That is how current macOS behaves; older releases are unconfirmed.
|
|
191
|
+
- **The first snapshot on macOS raises a camera permission prompt.** The helper is a plain CLI tool
|
|
192
|
+
with no bundle identifier, so macOS attributes camera access to whichever app spawned it — your
|
|
193
|
+
MCP client — and that app is named in the prompt and holds the grant. Approve once; the grant
|
|
194
|
+
survives helper updates, since it is keyed to the client rather than to the helper's signature.
|
|
195
|
+
- **The camera may not enumerate through a USB hub or dock.** A Tiny 2 connected through a USB-C
|
|
196
|
+
dock was invisible to `ioreg` and `system_profiler` entirely — not just to this server. If
|
|
197
|
+
`obsbot_list_devices` comes back empty, try a direct connection before assuming a software fault.
|
|
198
|
+
- **Only the OBSBOT Tiny 2 is supported.** On macOS the USB vendor/product IDs are hardcoded
|
|
199
|
+
(`0x3564`/`0xFEF8`), so no other model is detected at all. Windows and Linux match devices by
|
|
200
|
+
name, so a different OBSBOT may be *found* — but the vendor command set is Tiny 2 specific
|
|
201
|
+
either way.
|
|
134
202
|
|
|
135
203
|
## No proprietary SDK
|
|
136
204
|
|
|
@@ -151,11 +219,11 @@ mediating access and the camera remains usable as a normal webcam at the same ti
|
|
|
151
219
|
are sent through the camera's UVC Extension Unit, driven via `IKsControl::KsProperty` against the
|
|
152
220
|
XU's topology node on Windows.
|
|
153
221
|
|
|
154
|
-
Both are issued through a small native helper process (`obsbot-helper.exe` on Windows
|
|
155
|
-
server spawns and talks to over a line-delimited JSON-RPC protocol on
|
|
156
|
-
only platform-specific piece; the codec (frame encoding, CRC-16/USB
|
|
157
|
-
abstraction, device manager, and MCP tool definitions are all pure
|
|
158
|
-
platforms.
|
|
222
|
+
Both are issued through a small native helper process (`obsbot-helper.exe` on Windows, `obsbot-helper`
|
|
223
|
+
on Linux) that the Node server spawns and talks to over a line-delimited JSON-RPC protocol on
|
|
224
|
+
stdin/stdout. The helper is the only platform-specific piece; the codec (frame encoding, CRC-16/USB
|
|
225
|
+
checksum, command table), transport abstraction, device manager, and MCP tool definitions are all pure
|
|
226
|
+
TypeScript/JavaScript and shared across platforms.
|
|
159
227
|
|
|
160
228
|
## Verifying against real hardware
|
|
161
229
|
|
|
@@ -3,9 +3,20 @@ export interface DshowDevices {
|
|
|
3
3
|
video: string[];
|
|
4
4
|
audio: string[];
|
|
5
5
|
}
|
|
6
|
+
export interface V4l2DeviceInfo {
|
|
7
|
+
path: string;
|
|
8
|
+
card: string;
|
|
9
|
+
}
|
|
10
|
+
export interface V4l2Devices {
|
|
11
|
+
video: V4l2DeviceInfo[];
|
|
12
|
+
audio: string[];
|
|
13
|
+
}
|
|
14
|
+
export type DeviceList = DshowDevices | V4l2Devices;
|
|
6
15
|
export declare function parseDshowDevices(stderr: string): DshowDevices;
|
|
7
|
-
export declare function resolveVideoName(devices:
|
|
8
|
-
export declare function resolveAudioName(devices:
|
|
16
|
+
export declare function resolveVideoName(devices: DeviceList, source: CaptureSource): string | undefined;
|
|
17
|
+
export declare function resolveAudioName(devices: DeviceList): string | undefined;
|
|
18
|
+
/** Parse the v4l2 device name from `ffmpeg -f v4l2 -i /dev/videoN` stderr. */
|
|
19
|
+
export declare function parseV4l2DeviceName(stderr: string): string | undefined;
|
|
9
20
|
export declare function buildRecordArgs(o: {
|
|
10
21
|
videoName: string;
|
|
11
22
|
audioName?: string;
|
|
@@ -15,3 +26,26 @@ export declare function buildRecordArgs(o: {
|
|
|
15
26
|
export declare function buildPreviewArgs(o: {
|
|
16
27
|
videoName: string;
|
|
17
28
|
}): string[];
|
|
29
|
+
export interface AvfDevices {
|
|
30
|
+
/** Device indices, keyed by display name (the name shown by ffmpeg). */
|
|
31
|
+
video: Record<string, number>;
|
|
32
|
+
audio: Record<string, number>;
|
|
33
|
+
}
|
|
34
|
+
export declare function parseAvfDevices(stderr: string): AvfDevices;
|
|
35
|
+
export declare function resolveAvfVideoName(devices: AvfDevices, source: CaptureSource): {
|
|
36
|
+
name: string;
|
|
37
|
+
index: number;
|
|
38
|
+
} | undefined;
|
|
39
|
+
export declare function resolveAvfAudioName(devices: AvfDevices): {
|
|
40
|
+
name: string;
|
|
41
|
+
index: number;
|
|
42
|
+
} | undefined;
|
|
43
|
+
export declare function buildAvfRecordArgs(o: {
|
|
44
|
+
videoIndex: number;
|
|
45
|
+
audioIndex?: number;
|
|
46
|
+
durationSec: number;
|
|
47
|
+
outputPath: string;
|
|
48
|
+
}): string[];
|
|
49
|
+
export declare function buildAvfPreviewArgs(o: {
|
|
50
|
+
videoIndex: number;
|
|
51
|
+
}): string[];
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
// Pure helpers for the recording/preview subsystem: parse ffmpeg's dshow
|
|
2
|
+
// (Windows), v4l2 (Linux), or avfoundation (macOS) device listing and build the
|
|
3
|
+
// exact ffmpeg/ffplay argv arrays. No side effects.
|
|
4
|
+
// ---------- Windows (dshow) helpers ----------
|
|
1
5
|
// ffmpeg -f dshow -list_devices prints one line per device on stderr:
|
|
2
6
|
// [dshow @ ..] "Friendly Name" (video)
|
|
3
|
-
// The name is the first quoted span; the trailing "(video)"/"(audio)" is the type.
|
|
4
7
|
export function parseDshowDevices(stderr) {
|
|
5
8
|
const video = [];
|
|
6
9
|
const audio = [];
|
|
@@ -16,16 +19,61 @@ export function parseDshowDevices(stderr) {
|
|
|
16
19
|
return { video, audio };
|
|
17
20
|
}
|
|
18
21
|
export function resolveVideoName(devices, source) {
|
|
19
|
-
|
|
22
|
+
const isV4l = (d) => "video" in d && d.video.length > 0 && typeof d.video[0] !== "string";
|
|
23
|
+
if (source === "virtual") {
|
|
24
|
+
if (isV4l(devices)) {
|
|
25
|
+
return devices.video.find((n) => /OBSBOT Virtual Camera/i.test(n.card))?.path;
|
|
26
|
+
}
|
|
20
27
|
return devices.video.find((n) => /OBSBOT Virtual Camera/i.test(n));
|
|
21
|
-
|
|
28
|
+
}
|
|
29
|
+
if (source === "ndi") {
|
|
30
|
+
if (isV4l(devices)) {
|
|
31
|
+
return devices.video.find((n) => /NDI Webcam/i.test(n.card))?.path;
|
|
32
|
+
}
|
|
22
33
|
return devices.video.find((n) => /NDI Webcam/i.test(n));
|
|
34
|
+
}
|
|
35
|
+
// Platform-specific device matching
|
|
36
|
+
if (isV4l(devices)) {
|
|
37
|
+
const found = devices.video.find((n) => /OBSBOT/i.test(n.card));
|
|
38
|
+
return found ? found.path : undefined;
|
|
39
|
+
}
|
|
40
|
+
// dshow on Windows
|
|
23
41
|
return devices.video.find((n) => /OBSBOT Tiny 2/i.test(n) && !/Virtual/i.test(n));
|
|
24
42
|
}
|
|
25
43
|
export function resolveAudioName(devices) {
|
|
26
|
-
|
|
44
|
+
if ("audio" in devices && Array.isArray(devices.audio)) {
|
|
45
|
+
return devices.audio.find((n) => /OBSBOT.*Mic/i.test(n));
|
|
46
|
+
}
|
|
47
|
+
// Linux v4l2 audio is typically a separate ALSA device
|
|
48
|
+
// Return undefined — callers should check and warn
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
// ---------- Linux (v4l2) helpers ----------
|
|
52
|
+
// ffmpeg -f v4l2 -list_formats all -i /dev/videoN lists formats on stderr.
|
|
53
|
+
/** Parse the v4l2 device name from `ffmpeg -f v4l2 -i /dev/videoN` stderr. */
|
|
54
|
+
export function parseV4l2DeviceName(stderr) {
|
|
55
|
+
// ffmpeg prints something like:
|
|
56
|
+
// [video4linux2,v4l2 @ 0x...] VideoDevice: /dev/videoN
|
|
57
|
+
// [video4linux2,v4l2 @ 0x...] driver : uvcvideo
|
|
58
|
+
// [video4linux2,v4l2 @ 0x...] card : OBSBOT Tiny 2 ...
|
|
59
|
+
const m = stderr.match(/card\s+:\s+(.+)/);
|
|
60
|
+
return m ? m[1].trim() : undefined;
|
|
27
61
|
}
|
|
28
62
|
export function buildRecordArgs(o) {
|
|
63
|
+
const isV4l2 = o.videoName.startsWith("/dev/");
|
|
64
|
+
if (isV4l2) {
|
|
65
|
+
return [
|
|
66
|
+
"-hide_banner", "-loglevel", "warning",
|
|
67
|
+
"-f", "v4l2",
|
|
68
|
+
"-i", o.videoName,
|
|
69
|
+
...(o.audioName ? ["-f", "alsa", "-i", o.audioName] : []),
|
|
70
|
+
"-t", String(o.durationSec),
|
|
71
|
+
"-c:v", "libx264", "-pix_fmt", "yuv420p",
|
|
72
|
+
...(o.audioName ? ["-c:a", "aac"] : []),
|
|
73
|
+
"-y", o.outputPath,
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
// dshow path (Windows)
|
|
29
77
|
const input = o.audioName
|
|
30
78
|
? `video=${o.videoName}:audio=${o.audioName}`
|
|
31
79
|
: `video=${o.videoName}`;
|
|
@@ -39,10 +87,95 @@ export function buildRecordArgs(o) {
|
|
|
39
87
|
];
|
|
40
88
|
}
|
|
41
89
|
export function buildPreviewArgs(o) {
|
|
90
|
+
const isV4l2 = o.videoName.startsWith("/dev/");
|
|
91
|
+
if (isV4l2) {
|
|
92
|
+
return [
|
|
93
|
+
"-hide_banner", "-loglevel", "warning",
|
|
94
|
+
"-f", "v4l2",
|
|
95
|
+
"-input_format", "mjpeg",
|
|
96
|
+
"-video_size", "1920x1080",
|
|
97
|
+
"-i", o.videoName,
|
|
98
|
+
"-window_title", "OBSBOT preview",
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
// dshow path
|
|
42
102
|
return [
|
|
43
103
|
"-hide_banner", "-loglevel", "warning", "-f", "dshow",
|
|
44
104
|
"-i", `video=${o.videoName}`,
|
|
45
105
|
"-window_title", "OBSBOT preview",
|
|
46
106
|
];
|
|
47
107
|
}
|
|
108
|
+
// ffmpeg -f avfoundation -list_devices true -i "" prints on stderr:
|
|
109
|
+
// [AVFoundation indev @ 0x...] AVFoundation video devices:
|
|
110
|
+
// [AVFoundation indev @ 0x...] [0] FaceTime HD Camera
|
|
111
|
+
// [AVFoundation indev @ 0x...] [1] OBSBOT Tiny 2
|
|
112
|
+
// [AVFoundation indev @ 0x...] AVFoundation audio devices:
|
|
113
|
+
// [AVFoundation indev @ 0x...] [0] Built-in Microphone
|
|
114
|
+
// [AVFoundation indev @ 0x...] [1] OBSBOT Tiny 2 Microphone
|
|
115
|
+
export function parseAvfDevices(stderr) {
|
|
116
|
+
const video = {};
|
|
117
|
+
const audio = {};
|
|
118
|
+
let section = null;
|
|
119
|
+
for (const line of stderr.split(/\r?\n/)) {
|
|
120
|
+
if (/AVFoundation video devices/i.test(line)) {
|
|
121
|
+
section = "video";
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (/AVFoundation audio devices/i.test(line)) {
|
|
125
|
+
section = "audio";
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (!section)
|
|
129
|
+
continue;
|
|
130
|
+
const m = line.match(/\[\s*(\d+)\]\s+(.+)/);
|
|
131
|
+
if (m) {
|
|
132
|
+
const idx = parseInt(m[1], 10);
|
|
133
|
+
const name = m[2].trim();
|
|
134
|
+
if (section === "video")
|
|
135
|
+
video[name] = idx;
|
|
136
|
+
else
|
|
137
|
+
audio[name] = idx;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { video, audio };
|
|
141
|
+
}
|
|
142
|
+
export function resolveAvfVideoName(devices, source) {
|
|
143
|
+
const names = Object.keys(devices.video);
|
|
144
|
+
let match;
|
|
145
|
+
if (source === "virtual")
|
|
146
|
+
match = names.find((n) => /OBSBOT Virtual Camera/i.test(n));
|
|
147
|
+
else if (source === "ndi")
|
|
148
|
+
match = names.find((n) => /NDI Webcam/i.test(n));
|
|
149
|
+
else
|
|
150
|
+
match = names.find((n) => /OBSBOT/i.test(n) && !/Virtual/i.test(n));
|
|
151
|
+
if (!match)
|
|
152
|
+
return undefined;
|
|
153
|
+
return { name: match, index: devices.video[match] };
|
|
154
|
+
}
|
|
155
|
+
export function resolveAvfAudioName(devices) {
|
|
156
|
+
const entry = Object.entries(devices.audio).find(([name]) => /OBSBOT.*Mic/i.test(name));
|
|
157
|
+
if (!entry)
|
|
158
|
+
return undefined;
|
|
159
|
+
return { name: entry[0], index: entry[1] };
|
|
160
|
+
}
|
|
161
|
+
export function buildAvfRecordArgs(o) {
|
|
162
|
+
const input = o.audioIndex !== undefined
|
|
163
|
+
? `${o.videoIndex}:${o.audioIndex}`
|
|
164
|
+
: `${o.videoIndex}`;
|
|
165
|
+
return [
|
|
166
|
+
"-hide_banner", "-loglevel", "warning", "-f", "avfoundation",
|
|
167
|
+
"-i", input,
|
|
168
|
+
"-t", String(o.durationSec),
|
|
169
|
+
"-c:v", "libx264", "-pix_fmt", "yuv420p",
|
|
170
|
+
...(o.audioIndex !== undefined ? ["-c:a", "aac"] : []),
|
|
171
|
+
"-y", o.outputPath,
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
export function buildAvfPreviewArgs(o) {
|
|
175
|
+
return [
|
|
176
|
+
"-hide_banner", "-loglevel", "warning", "-f", "avfoundation",
|
|
177
|
+
"-i", `${o.videoIndex}`,
|
|
178
|
+
"-window_title", "OBSBOT preview",
|
|
179
|
+
];
|
|
180
|
+
}
|
|
48
181
|
//# sourceMappingURL=ffmpeg-args.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffmpeg-args.js","sourceRoot":"","sources":["../../src/capture/ffmpeg-args.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ffmpeg-args.js","sourceRoot":"","sources":["../../src/capture/ffmpeg-args.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn as realSpawn } from "node:child_process";
|
|
2
|
-
import { type CaptureSource } from "./ffmpeg-args.js";
|
|
2
|
+
import { type CaptureSource, type DeviceList, type AvfDevices } from "./ffmpeg-args.js";
|
|
3
3
|
export interface CaptureSession {
|
|
4
4
|
id: string;
|
|
5
5
|
kind: "record" | "preview";
|
|
@@ -27,18 +27,30 @@ interface Deps {
|
|
|
27
27
|
clock?: () => string;
|
|
28
28
|
hasBinary?: (name: string) => boolean;
|
|
29
29
|
fs?: FsLike;
|
|
30
|
+
/** Override platform detection for testing. */
|
|
31
|
+
platform?: "darwin" | "win32" | "linux";
|
|
32
|
+
/** Override for device probe logic (used by tests to avoid real V4L2/dshow/AVF probing). */
|
|
33
|
+
probeDevices?: () => Promise<PlatformDevices>;
|
|
30
34
|
}
|
|
35
|
+
/** Union of all platform device-list shapes. */
|
|
36
|
+
type PlatformDevices = DeviceList | AvfDevices;
|
|
31
37
|
export declare class CaptureManager {
|
|
32
38
|
private readonly spawn;
|
|
33
39
|
private readonly clock;
|
|
34
40
|
private readonly hasBinary;
|
|
35
41
|
private readonly fs;
|
|
42
|
+
private readonly platform;
|
|
43
|
+
private readonly probeFn;
|
|
36
44
|
private readonly sessions;
|
|
37
45
|
private devices?;
|
|
38
46
|
private seq;
|
|
39
47
|
constructor(deps?: Deps);
|
|
40
48
|
private ensureFfmpeg;
|
|
41
49
|
private probeDevices;
|
|
50
|
+
private probeV4l2Devices;
|
|
51
|
+
private probeV4l2Card;
|
|
52
|
+
private probeAvfDevices;
|
|
53
|
+
private probeDshowDevices;
|
|
42
54
|
private timestampName;
|
|
43
55
|
startRecord(o: {
|
|
44
56
|
source: CaptureSource;
|
package/dist/capture/manager.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { spawn as realSpawn, spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
-
import { homedir } from "node:os";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { homedir, platform } from "node:os";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
-
import { parseDshowDevices, resolveVideoName, resolveAudioName, buildRecordArgs, buildPreviewArgs, } from "./ffmpeg-args.js";
|
|
5
|
+
import { parseDshowDevices, resolveVideoName, resolveAudioName, buildRecordArgs, buildPreviewArgs, parseAvfDevices, resolveAvfVideoName, resolveAvfAudioName, buildAvfRecordArgs, buildAvfPreviewArgs, } from "./ffmpeg-args.js";
|
|
6
6
|
/** Expected operational failure (surfaced to the user as text, not thrown to the client). */
|
|
7
7
|
export class CaptureError extends Error {
|
|
8
8
|
constructor(message) {
|
|
@@ -24,11 +24,16 @@ function defaultHasBinary(name) {
|
|
|
24
24
|
const r = spawnSync(name, ["-version"], { stdio: "ignore" });
|
|
25
25
|
return !r.error;
|
|
26
26
|
}
|
|
27
|
+
function isAvfDevices(d) {
|
|
28
|
+
return "video" in d && typeof d.video === "object" && !Array.isArray(d.video);
|
|
29
|
+
}
|
|
27
30
|
export class CaptureManager {
|
|
28
31
|
spawn;
|
|
29
32
|
clock;
|
|
30
33
|
hasBinary;
|
|
31
34
|
fs;
|
|
35
|
+
platform;
|
|
36
|
+
probeFn;
|
|
32
37
|
sessions = new Map();
|
|
33
38
|
devices;
|
|
34
39
|
seq = 0;
|
|
@@ -37,6 +42,8 @@ export class CaptureManager {
|
|
|
37
42
|
this.clock = deps.clock ?? (() => new Date().toISOString());
|
|
38
43
|
this.hasBinary = deps.hasBinary ?? defaultHasBinary;
|
|
39
44
|
this.fs = deps.fs ?? { existsSync, mkdirSync };
|
|
45
|
+
this.platform = deps.platform ?? platform();
|
|
46
|
+
this.probeFn = deps.probeDevices;
|
|
40
47
|
}
|
|
41
48
|
ensureFfmpeg() {
|
|
42
49
|
if (!this.hasBinary("ffmpeg") || !this.hasBinary("ffplay")) {
|
|
@@ -46,19 +53,77 @@ export class CaptureManager {
|
|
|
46
53
|
probeDevices() {
|
|
47
54
|
if (this.devices)
|
|
48
55
|
return Promise.resolve(this.devices);
|
|
56
|
+
// Allow tests to inject a mock probe
|
|
57
|
+
if (this.probeFn)
|
|
58
|
+
return this.probeFn();
|
|
49
59
|
return new Promise((resolve, reject) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
if (this.platform === "linux") {
|
|
61
|
+
// On Linux, list /dev/video* devices and probe each one
|
|
62
|
+
this.probeV4l2Devices().then(resolve).catch(reject);
|
|
63
|
+
}
|
|
64
|
+
else if (this.platform === "darwin") {
|
|
65
|
+
this.probeAvfDevices(resolve, reject);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.probeDshowDevices(resolve, reject);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async probeV4l2Devices() {
|
|
73
|
+
const video = [];
|
|
74
|
+
try {
|
|
75
|
+
const files = readdirSync("/dev");
|
|
76
|
+
const videoDevs = files
|
|
77
|
+
.filter((f) => /^video\d+$/.test(f))
|
|
78
|
+
.map((f) => `/dev/${f}`)
|
|
79
|
+
.sort();
|
|
80
|
+
for (const dev of videoDevs) {
|
|
81
|
+
const name = await this.probeV4l2Card(dev);
|
|
82
|
+
if (name)
|
|
83
|
+
video.push({ path: dev, card: name });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// /dev not readable
|
|
88
|
+
}
|
|
89
|
+
return { video, audio: [] };
|
|
90
|
+
}
|
|
91
|
+
probeV4l2Card(dev) {
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
try {
|
|
94
|
+
const idx = dev.match(/video(\d+)$/)?.[1];
|
|
95
|
+
if (!idx)
|
|
96
|
+
return resolve(undefined);
|
|
97
|
+
const sysfs = `/sys/class/video4linux/video${idx}/name`;
|
|
98
|
+
const name = readFileSync(sysfs, 'utf-8').trim();
|
|
99
|
+
resolve(name || undefined);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
resolve(undefined);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
probeAvfDevices(resolve, reject) {
|
|
107
|
+
const child = this.spawn("ffmpeg", ["-hide_banner", "-f", "avfoundation", "-list_devices", "true", "-i", ""], { stdio: ["pipe", "pipe", "pipe"] });
|
|
108
|
+
let err = "";
|
|
109
|
+
child.stderr?.on("data", (d) => { err += d.toString(); });
|
|
110
|
+
child.on("error", (e) => reject(new CaptureError(`failed to run ffmpeg for device probe: ${e.message}`)));
|
|
111
|
+
child.on("close", () => {
|
|
112
|
+
this.devices = parseAvfDevices(err);
|
|
113
|
+
resolve(this.devices);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
probeDshowDevices(resolve, reject) {
|
|
117
|
+
const child = this.spawn("ffmpeg", ["-hide_banner", "-f", "dshow", "-list_devices", "true", "-i", "dummy"], { stdio: ["pipe", "pipe", "pipe"] });
|
|
118
|
+
let err = "";
|
|
119
|
+
child.stderr?.on("data", (d) => { err += d.toString(); });
|
|
120
|
+
child.on("error", (e) => reject(new CaptureError(`failed to run ffmpeg for device probe: ${e.message}`)));
|
|
121
|
+
child.on("close", () => {
|
|
122
|
+
this.devices = parseDshowDevices(err);
|
|
123
|
+
resolve(this.devices);
|
|
58
124
|
});
|
|
59
125
|
}
|
|
60
126
|
timestampName() {
|
|
61
|
-
// clock() -> "2026-07-13T09:33:58.000Z"; make obsbot-YYYYMMDD-HHMMSS.mp4
|
|
62
127
|
const iso = this.clock();
|
|
63
128
|
const compact = iso.replace(/[-:]/g, "").replace("T", "-").replace(/\..*$/, "");
|
|
64
129
|
return `obsbot-${compact}.mp4`;
|
|
@@ -66,6 +131,36 @@ export class CaptureManager {
|
|
|
66
131
|
async startRecord(o) {
|
|
67
132
|
this.ensureFfmpeg();
|
|
68
133
|
const devices = await this.probeDevices();
|
|
134
|
+
if (isAvfDevices(devices)) {
|
|
135
|
+
const videoInfo = resolveAvfVideoName(devices, o.source);
|
|
136
|
+
if (!videoInfo)
|
|
137
|
+
throw new CaptureError(`no '${o.source}' video source found (is OBSBOT Center / NDI running?)`);
|
|
138
|
+
let audioIndex;
|
|
139
|
+
if (o.audio) {
|
|
140
|
+
const audioInfo = resolveAvfAudioName(devices);
|
|
141
|
+
if (!audioInfo)
|
|
142
|
+
throw new CaptureError("OBSBOT microphone not found; retry with audio:false for a silent clip");
|
|
143
|
+
audioIndex = audioInfo.index;
|
|
144
|
+
}
|
|
145
|
+
const outputPath = o.outputPath ?? join(homedir(), "Videos", "OBSBOT", this.timestampName());
|
|
146
|
+
if (o.outputPath && this.fs.existsSync(o.outputPath)) {
|
|
147
|
+
throw new CaptureError(`output file already exists: ${o.outputPath}`);
|
|
148
|
+
}
|
|
149
|
+
this.fs.mkdirSync(dirname(outputPath), { recursive: true });
|
|
150
|
+
const durationSec = o.durationSec ?? OPEN_ENDED_CAP_SEC;
|
|
151
|
+
const args = buildAvfRecordArgs({ videoIndex: videoInfo.index, audioIndex, durationSec, outputPath });
|
|
152
|
+
const child = this.spawn("ffmpeg", args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
153
|
+
const session = {
|
|
154
|
+
id: `cap${++this.seq}`, kind: "record", pid: child.pid ?? -1,
|
|
155
|
+
source: o.source, outputPath, durationSec, startedAtIso: this.clock(),
|
|
156
|
+
};
|
|
157
|
+
this.sessions.set(session.id, { session, child });
|
|
158
|
+
child.once("exit", () => this.sessions.delete(session.id));
|
|
159
|
+
child.on("error", () => this.sessions.delete(session.id));
|
|
160
|
+
return session;
|
|
161
|
+
}
|
|
162
|
+
// Windows (dshow) or Linux (v4l2) path — resolveVideoName/buildRecordArgs
|
|
163
|
+
// handle both via the DeviceList union and /dev/ prefix check.
|
|
69
164
|
const videoName = resolveVideoName(devices, o.source);
|
|
70
165
|
if (!videoName)
|
|
71
166
|
throw new CaptureError(`no '${o.source}' video source found (is OBSBOT Center / NDI running?)`);
|
|
@@ -95,6 +190,22 @@ export class CaptureManager {
|
|
|
95
190
|
async startPreview(o) {
|
|
96
191
|
this.ensureFfmpeg();
|
|
97
192
|
const devices = await this.probeDevices();
|
|
193
|
+
if (isAvfDevices(devices)) {
|
|
194
|
+
const videoInfo = resolveAvfVideoName(devices, o.source);
|
|
195
|
+
if (!videoInfo)
|
|
196
|
+
throw new CaptureError(`no '${o.source}' video source found (is OBSBOT Center / NDI running?)`);
|
|
197
|
+
const args = buildAvfPreviewArgs({ videoIndex: videoInfo.index });
|
|
198
|
+
const child = this.spawn("ffplay", args, { stdio: "ignore" });
|
|
199
|
+
const session = {
|
|
200
|
+
id: `cap${++this.seq}`, kind: "preview", pid: child.pid ?? -1,
|
|
201
|
+
source: o.source, startedAtIso: this.clock(),
|
|
202
|
+
};
|
|
203
|
+
this.sessions.set(session.id, { session, child });
|
|
204
|
+
child.once("exit", () => this.sessions.delete(session.id));
|
|
205
|
+
child.on("error", () => this.sessions.delete(session.id));
|
|
206
|
+
return session;
|
|
207
|
+
}
|
|
208
|
+
// Windows (dshow) or Linux (v4l2) path
|
|
98
209
|
const videoName = resolveVideoName(devices, o.source);
|
|
99
210
|
if (!videoName)
|
|
100
211
|
throw new CaptureError(`no '${o.source}' video source found (is OBSBOT Center / NDI running?)`);
|
|
@@ -116,7 +227,6 @@ export class CaptureManager {
|
|
|
116
227
|
const { session, child } = entry;
|
|
117
228
|
let graceful = true;
|
|
118
229
|
if (session.kind === "record") {
|
|
119
|
-
// 'q' on stdin is ffmpeg's clean stop (finalizes the MP4 moov atom).
|
|
120
230
|
graceful = await new Promise((resolve) => {
|
|
121
231
|
let done = false;
|
|
122
232
|
const timer = setTimeout(() => { if (!done) {
|
|
@@ -142,12 +252,10 @@ export class CaptureManager {
|
|
|
142
252
|
return { kind: session.kind, outputPath: session.outputPath, graceful };
|
|
143
253
|
}
|
|
144
254
|
list() {
|
|
145
|
-
return
|
|
255
|
+
return Array.from(this.sessions.values()).map((e) => e.session);
|
|
146
256
|
}
|
|
147
|
-
// Hard-kill every child. Wired to server shutdown so nothing orphans; this is
|
|
148
|
-
// last-resort cleanup, not a graceful stop.
|
|
149
257
|
stopAll() {
|
|
150
|
-
for (const { child } of this.sessions.values()) {
|
|
258
|
+
for (const { child } of Array.from(this.sessions.values())) {
|
|
151
259
|
try {
|
|
152
260
|
child.kill();
|
|
153
261
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/capture/manager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/capture/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/codec/commands.d.ts
CHANGED
|
@@ -25,6 +25,16 @@ export declare const AI_TRACK_SPEEDS: AiTrackSpeed[];
|
|
|
25
25
|
export declare const encodeAiTrackSpeed: (speed: AiTrackSpeed) => VendorFrame;
|
|
26
26
|
export declare const encodeZoomWithSpeed: (ratioX100: number, speed: number) => VendorFrame;
|
|
27
27
|
export declare const encodeFaceFocus: (enable: boolean) => VendorFrame;
|
|
28
|
+
export declare const encodeSetExposureMode: (manual: boolean) => VendorFrame;
|
|
29
|
+
export declare const encodeSetExposureValue: (raw: number) => VendorFrame;
|
|
30
|
+
export declare const encodeGetExposureMode: () => VendorFrame;
|
|
31
|
+
export declare const encodeGetExposureValue: () => VendorFrame;
|
|
32
|
+
export declare const encodeGetExposureRange: () => VendorFrame;
|
|
33
|
+
export interface ExposureRange {
|
|
34
|
+
min: number;
|
|
35
|
+
max: number;
|
|
36
|
+
}
|
|
37
|
+
export declare const decodeExposureRange: (payload: Buffer) => ExposureRange;
|
|
28
38
|
/** Request the current face-priority autofocus state (CAM_GET_FACE_FOCUS, cmd 0x35c2). */
|
|
29
39
|
export declare const encodeGetFaceFocus: () => VendorFrame;
|
|
30
40
|
export interface FaceFocusState {
|