memoir-node 0.1.7 → 0.2.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/LICENSE CHANGED
@@ -1,27 +1,27 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 lunavod
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.
22
-
23
- ---
24
-
25
- This software links against FFmpeg, which is licensed under the
26
- GNU Lesser General Public License (LGPL) version 2.1 or later.
27
- See https://www.ffmpeg.org/legal.html for details.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lunavod
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.
22
+
23
+ ---
24
+
25
+ This software links against FFmpeg, which is licensed under the
26
+ GNU Lesser General Public License (LGPL) version 2.1 or later.
27
+ See https://www.ffmpeg.org/legal.html for details.
package/README.md CHANGED
@@ -1,249 +1,249 @@
1
- # memoir-node
2
-
3
- Windows-native screen capture module with Node.js bindings for real-time frame analysis and deterministic replay recording.
4
-
5
- Memoir captures frames from a window or monitor using Windows Graphics Capture (WGC), delivers them as Buffers, and optionally records them to HEVC video with per-frame metadata.
6
-
7
- ## Features
8
-
9
- - **WGC capture** — continuous frame capture from any window or monitor
10
- - **Zero-copy Buffers** — BGRA frames delivered as Node.js Buffers without copying
11
- - **Hardware-accelerated recording** — lossless HEVC encoding via NVENC, AMF, or x265 fallback
12
- - **Binary metadata** — `.meta` sidecar with per-frame keyboard state, timestamps, and frame IDs
13
- - **Dynamic recording** — start/stop recording without restarting capture
14
- - **Frame-accurate keyboard** — key state snapshot at the exact moment each frame is accepted
15
- - **Pure TypeScript meta reader/writer** — read and write `.meta` files without the native addon
16
- - **Synchronous blocking API** — designed for Worker threads running tick loops
17
-
18
- ## Requirements
19
-
20
- - Windows 10 1903+
21
- - Node.js 18+
22
- - x64 architecture
23
- - NVIDIA GPU (NVENC), AMD GPU (AMF), or CPU-only (x265) for recording
24
-
25
- ## Installation
26
-
27
- ```
28
- npm install memoir-node
29
- ```
30
-
31
- ## Quick Start
32
-
33
- ### Capture frames
34
-
35
- ```typescript
36
- import { CaptureEngine } from 'memoir-node'
37
-
38
- const engine = new CaptureEngine({
39
- target: { type: 'monitor', index: 0 }, // primary monitor
40
- maxFps: 10,
41
- })
42
- engine.start()
43
-
44
- const frame = engine.getNextFrame(5000)
45
- if (frame) {
46
- console.log(`Frame ${frame.frameId}: ${frame.width}x${frame.height}`)
47
- console.log(`Keys: ${frame.keyboardMask.toString(16)}`)
48
- // frame.data is a Buffer with BGRA pixels
49
- frame.release()
50
- }
51
-
52
- engine.stop()
53
- ```
54
-
55
- ### Capture a specific window
56
-
57
- ```typescript
58
- const engine = new CaptureEngine({
59
- target: { type: 'windowTitle', pattern: '(?i)notepad' },
60
- maxFps: 30,
61
- })
62
- ```
63
-
64
- Or by executable name:
65
-
66
- ```typescript
67
- const engine = new CaptureEngine({
68
- target: { type: 'windowExe', pattern: 'notepad\\.exe' },
69
- maxFps: 30,
70
- })
71
- ```
72
-
73
- ### Record to MP4
74
-
75
- ```typescript
76
- const engine = new CaptureEngine({
77
- target: { type: 'monitor', index: 0 },
78
- maxFps: 10,
79
- recordWidth: 1920,
80
- recordHeight: 1080,
81
- })
82
- engine.start()
83
-
84
- const info = engine.startRecording('session_001')
85
- console.log(`Recording to ${info.videoPath}`) // session_001.mp4
86
-
87
- for (let i = 0; i < 100; i++) {
88
- const frame = engine.getNextFrame(5000)
89
- if (frame) frame.release()
90
- }
91
-
92
- engine.stopRecording() // finalizes .mp4 + .meta
93
- engine.stop()
94
- ```
95
-
96
- ### Read metadata
97
-
98
- ```typescript
99
- import { readMeta, pressedKeys } from 'memoir-node'
100
-
101
- const meta = readMeta('session_001.meta')
102
- console.log(`Keys tracked: ${meta.keys.map(k => k.name)}`)
103
-
104
- for (const row of meta.rows) {
105
- console.log(`Frame ${row.frameId}: ${pressedKeys(row, meta.keys).join(', ')}`)
106
- }
107
- ```
108
-
109
- ### Write metadata (for synthetic replays)
110
-
111
- ```typescript
112
- import { writeMeta, type MetaKeyEntry, type MetaRow } from 'memoir-node'
113
-
114
- const keys: MetaKeyEntry[] = [
115
- { bit: 0, vk: 0x57, name: 'W' },
116
- { bit: 1, vk: 0x41, name: 'A' },
117
- ]
118
-
119
- const rows: MetaRow[] = [{
120
- frameId: 0n, recordFrameIndex: 0n,
121
- captureQpc: 0n, hostAcceptQpc: 0n,
122
- keyboardMask: 0b01n,
123
- width: 1920, height: 1080, analysisStride: 7680, flags: 0,
124
- }]
125
-
126
- writeMeta('synthetic.meta', keys, rows)
127
- ```
128
-
129
- ### Worker thread usage (Electron)
130
-
131
- ```typescript
132
- // tick-worker.ts — runs in Worker thread
133
- import { CaptureEngine } from 'memoir-node'
134
- import { parentPort } from 'worker_threads'
135
-
136
- const engine = new CaptureEngine({
137
- target: { type: 'windowExe', pattern: 'myapp\\.exe' },
138
- maxFps: 10,
139
- })
140
- engine.start()
141
-
142
- while (true) {
143
- const frame = engine.getNextFrame(2000)
144
- if (!frame) {
145
- const err = engine.lastError()
146
- if (err) { parentPort!.postMessage({ type: 'error', error: err }); break }
147
- continue
148
- }
149
-
150
- // frame.data is a Buffer — process it here, don't post it to main thread
151
- parentPort!.postMessage({
152
- type: 'tick',
153
- frameId: frame.frameId,
154
- width: frame.width,
155
- height: frame.height,
156
- })
157
-
158
- frame.release()
159
- }
160
- ```
161
-
162
- ## API Reference
163
-
164
- ### `new CaptureEngine(options)`
165
-
166
- | Option | Default | Description |
167
- |--------|---------|-------------|
168
- | `target` | required | `{ type: 'monitor', index }`, `{ type: 'windowTitle', pattern }`, or `{ type: 'windowExe', pattern }` |
169
- | `maxFps` | `10` | Maximum accepted frame rate |
170
- | `queueCapacity` | `1` | Bounded queue size |
171
- | `captureCursor` | `false` | Include cursor in capture |
172
- | `keys` | 40-key gaming set | Array of `{ bit, vk, name }` for keyboard tracking |
173
- | `recordWidth` | `1920` | Recording output width |
174
- | `recordHeight` | `1080` | Recording output height |
175
- | `recordGop` | `1` | GOP size (1 = all-intra) |
176
-
177
- ### Methods
178
-
179
- | Method | Returns | Description |
180
- |--------|---------|-------------|
181
- | `start()` | `void` | Initialize D3D11, create WGC session, begin capturing |
182
- | `stop()` | `void` | Stop capture and any active recording |
183
- | `getNextFrame(timeoutMs?)` | `FramePacket \| null` | Block until frame available. -1 = forever, 0 = poll |
184
- | `startRecording(basePath, encoder?)` | `RecordingInfo` | Start recording to `basePath.mp4` + `basePath.meta` |
185
- | `startRecording(opts)` | `RecordingInfo` | Start recording with `{ path, videoName, metaName, encoder? }` |
186
- | `stopRecording()` | `void` | Finalize recording |
187
- | `isRecording()` | `boolean` | Whether a recording session is active |
188
- | `stats()` | `EngineStats` | Live counters |
189
- | `lastError()` | `string \| null` | Last non-fatal error |
190
-
191
- ### `FramePacket`
192
-
193
- | Property | Type | Description |
194
- |----------|------|-------------|
195
- | `frameId` | `number` | Monotonic frame ID |
196
- | `data` | `Buffer` | BGRA pixels, length = stride * height |
197
- | `keyboardMask` | `bigint` | 64-bit key state bitmask |
198
- | `captureQpc` | `bigint` | WGC timestamp (100ns units) |
199
- | `hostAcceptQpc` | `bigint` | Host QPC when frame was accepted |
200
- | `width`, `height`, `stride` | `number` | Frame dimensions |
201
- | `released` | `boolean` | Whether pixel memory has been freed |
202
-
203
- Call `frame.release()` when done to free pixel memory.
204
-
205
- ### Recording
206
-
207
- Encoding: lossless HEVC (QP=0), YUV 4:4:4. Encoder selected automatically: `hevc_nvenc` (NVIDIA) → `hevc_amf` (AMD) → `libx265` (software). Force a specific encoder:
208
-
209
- ```typescript
210
- const info = engine.startRecording('session', 'libx265')
211
- console.log(info.codec) // "libx265"
212
- ```
213
-
214
- ### Meta utilities
215
-
216
- ```typescript
217
- import { readMeta, writeMeta, isPressed, pressedKeys, synthesizeKeyEvents } from 'memoir-node'
218
-
219
- // Read
220
- const meta = readMeta('session.meta')
221
-
222
- // Check keys
223
- isPressed(meta.rows[0], 'W', meta.keys) // boolean
224
- pressedKeys(meta.rows[0], meta.keys) // string[]
225
-
226
- // Generate key events for replay
227
- const events = synthesizeKeyEvents(meta.rows, meta.keys)
228
- // [{ frame: 0n, type: 'keyDown', key: 'W' }, ...]
229
- ```
230
-
231
- ## Architecture
232
-
233
- ```
234
- WGC FrameArrived (thread pool)
235
-
236
- ├─ FPS limiter → drop if too soon
237
- ├─ Queue check → drop if full (drop-new policy)
238
-
239
- ├─ Accept: assign frame_id, snapshot keyboard
240
- ├─ GPU→CPU: CopyResource → staging → Map → memcpy → Buffer (zero-copy)
241
- ├─ Recording: swscale (BGRA→YUV444) → HEVC encoder → MP4
242
- └─ Enqueue → Node.js consumer
243
- ```
244
-
245
- `getNextFrame()` is a synchronous blocking call that waits on a condition variable. No GIL concerns (unlike Python) — the calling thread simply sleeps until a frame arrives. Use in a Worker thread to avoid blocking the main V8 thread.
246
-
247
- ## License
248
-
249
- MIT. Links against FFmpeg (LGPL 2.1+).
1
+ # memoir-node
2
+
3
+ Windows-native screen capture module with Node.js bindings for real-time frame analysis and deterministic replay recording.
4
+
5
+ Memoir captures frames from a window or monitor using Windows Graphics Capture (WGC), delivers them as Buffers, and optionally records them to HEVC video with per-frame metadata.
6
+
7
+ ## Features
8
+
9
+ - **WGC capture** — continuous frame capture from any window or monitor
10
+ - **Zero-copy Buffers** — BGRA frames delivered as Node.js Buffers without copying
11
+ - **Hardware-accelerated recording** — lossless HEVC encoding via NVENC, AMF, or x265 fallback
12
+ - **Binary metadata** — `.meta` sidecar with per-frame keyboard state, timestamps, and frame IDs
13
+ - **Dynamic recording** — start/stop recording without restarting capture
14
+ - **Frame-accurate keyboard** — key state snapshot at the exact moment each frame is accepted
15
+ - **Pure TypeScript meta reader/writer** — read and write `.meta` files without the native addon
16
+ - **Synchronous blocking API** — designed for Worker threads running tick loops
17
+
18
+ ## Requirements
19
+
20
+ - Windows 10 1903+
21
+ - Node.js 18+
22
+ - x64 architecture
23
+ - NVIDIA GPU (NVENC), AMD GPU (AMF), or CPU-only (x265) for recording
24
+
25
+ ## Installation
26
+
27
+ ```
28
+ npm install memoir-node
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### Capture frames
34
+
35
+ ```typescript
36
+ import { CaptureEngine } from 'memoir-node'
37
+
38
+ const engine = new CaptureEngine({
39
+ target: { type: 'monitor', index: 0 }, // primary monitor
40
+ maxFps: 10,
41
+ })
42
+ engine.start()
43
+
44
+ const frame = engine.getNextFrame(5000)
45
+ if (frame) {
46
+ console.log(`Frame ${frame.frameId}: ${frame.width}x${frame.height}`)
47
+ console.log(`Keys: ${frame.keyboardMask.toString(16)}`)
48
+ // frame.data is a Buffer with BGRA pixels
49
+ frame.release()
50
+ }
51
+
52
+ engine.stop()
53
+ ```
54
+
55
+ ### Capture a specific window
56
+
57
+ ```typescript
58
+ const engine = new CaptureEngine({
59
+ target: { type: 'windowTitle', pattern: '(?i)notepad' },
60
+ maxFps: 30,
61
+ })
62
+ ```
63
+
64
+ Or by executable name:
65
+
66
+ ```typescript
67
+ const engine = new CaptureEngine({
68
+ target: { type: 'windowExe', pattern: 'notepad\\.exe' },
69
+ maxFps: 30,
70
+ })
71
+ ```
72
+
73
+ ### Record to MP4
74
+
75
+ ```typescript
76
+ const engine = new CaptureEngine({
77
+ target: { type: 'monitor', index: 0 },
78
+ maxFps: 10,
79
+ recordWidth: 1920,
80
+ recordHeight: 1080,
81
+ })
82
+ engine.start()
83
+
84
+ const info = engine.startRecording('session_001')
85
+ console.log(`Recording to ${info.videoPath}`) // session_001.mp4
86
+
87
+ for (let i = 0; i < 100; i++) {
88
+ const frame = engine.getNextFrame(5000)
89
+ if (frame) frame.release()
90
+ }
91
+
92
+ engine.stopRecording() // finalizes .mp4 + .meta
93
+ engine.stop()
94
+ ```
95
+
96
+ ### Read metadata
97
+
98
+ ```typescript
99
+ import { readMeta, pressedKeys } from 'memoir-node'
100
+
101
+ const meta = readMeta('session_001.meta')
102
+ console.log(`Keys tracked: ${meta.keys.map(k => k.name)}`)
103
+
104
+ for (const row of meta.rows) {
105
+ console.log(`Frame ${row.frameId}: ${pressedKeys(row, meta.keys).join(', ')}`)
106
+ }
107
+ ```
108
+
109
+ ### Write metadata (for synthetic replays)
110
+
111
+ ```typescript
112
+ import { writeMeta, type MetaKeyEntry, type MetaRow } from 'memoir-node'
113
+
114
+ const keys: MetaKeyEntry[] = [
115
+ { bit: 0, vk: 0x57, name: 'W' },
116
+ { bit: 1, vk: 0x41, name: 'A' },
117
+ ]
118
+
119
+ const rows: MetaRow[] = [{
120
+ frameId: 0n, recordFrameIndex: 0n,
121
+ captureQpc: 0n, hostAcceptQpc: 0n,
122
+ keyboardMask: 0b01n,
123
+ width: 1920, height: 1080, analysisStride: 7680, flags: 0,
124
+ }]
125
+
126
+ writeMeta('synthetic.meta', keys, rows)
127
+ ```
128
+
129
+ ### Worker thread usage (Electron)
130
+
131
+ ```typescript
132
+ // tick-worker.ts — runs in Worker thread
133
+ import { CaptureEngine } from 'memoir-node'
134
+ import { parentPort } from 'worker_threads'
135
+
136
+ const engine = new CaptureEngine({
137
+ target: { type: 'windowExe', pattern: 'myapp\\.exe' },
138
+ maxFps: 10,
139
+ })
140
+ engine.start()
141
+
142
+ while (true) {
143
+ const frame = engine.getNextFrame(2000)
144
+ if (!frame) {
145
+ const err = engine.lastError()
146
+ if (err) { parentPort!.postMessage({ type: 'error', error: err }); break }
147
+ continue
148
+ }
149
+
150
+ // frame.data is a Buffer — process it here, don't post it to main thread
151
+ parentPort!.postMessage({
152
+ type: 'tick',
153
+ frameId: frame.frameId,
154
+ width: frame.width,
155
+ height: frame.height,
156
+ })
157
+
158
+ frame.release()
159
+ }
160
+ ```
161
+
162
+ ## API Reference
163
+
164
+ ### `new CaptureEngine(options)`
165
+
166
+ | Option | Default | Description |
167
+ |--------|---------|-------------|
168
+ | `target` | required | `{ type: 'monitor', index }`, `{ type: 'windowTitle', pattern }`, or `{ type: 'windowExe', pattern }` |
169
+ | `maxFps` | `10` | Maximum accepted frame rate |
170
+ | `queueCapacity` | `1` | Bounded queue size |
171
+ | `captureCursor` | `false` | Include cursor in capture |
172
+ | `keys` | 40-key gaming set | Array of `{ bit, vk, name }` for keyboard tracking |
173
+ | `recordWidth` | `1920` | Recording output width |
174
+ | `recordHeight` | `1080` | Recording output height |
175
+ | `recordGop` | `1` | GOP size (1 = all-intra) |
176
+
177
+ ### Methods
178
+
179
+ | Method | Returns | Description |
180
+ |--------|---------|-------------|
181
+ | `start()` | `void` | Initialize D3D11, create WGC session, begin capturing |
182
+ | `stop()` | `void` | Stop capture and any active recording |
183
+ | `getNextFrame(timeoutMs?)` | `FramePacket \| null` | Block until frame available. -1 = forever, 0 = poll |
184
+ | `startRecording(basePath, encoder?)` | `RecordingInfo` | Start recording to `basePath.mp4` + `basePath.meta` |
185
+ | `startRecording(opts)` | `RecordingInfo` | Start recording with `{ path, videoName, metaName, encoder? }` |
186
+ | `stopRecording()` | `void` | Finalize recording |
187
+ | `isRecording()` | `boolean` | Whether a recording session is active |
188
+ | `stats()` | `EngineStats` | Live counters |
189
+ | `lastError()` | `string \| null` | Last non-fatal error |
190
+
191
+ ### `FramePacket`
192
+
193
+ | Property | Type | Description |
194
+ |----------|------|-------------|
195
+ | `frameId` | `number` | Monotonic frame ID |
196
+ | `data` | `Buffer` | BGRA pixels, length = stride * height |
197
+ | `keyboardMask` | `bigint` | 64-bit key state bitmask |
198
+ | `captureQpc` | `bigint` | WGC timestamp (100ns units) |
199
+ | `hostAcceptQpc` | `bigint` | Host QPC when frame was accepted |
200
+ | `width`, `height`, `stride` | `number` | Frame dimensions |
201
+ | `released` | `boolean` | Whether pixel memory has been freed |
202
+
203
+ Call `frame.release()` when done to free pixel memory.
204
+
205
+ ### Recording
206
+
207
+ Encoding: lossless HEVC (QP=0), YUV 4:4:4. Encoder selected automatically: `hevc_nvenc` (NVIDIA) → `hevc_amf` (AMD) → `libx265` (software). Force a specific encoder:
208
+
209
+ ```typescript
210
+ const info = engine.startRecording('session', 'libx265')
211
+ console.log(info.codec) // "libx265"
212
+ ```
213
+
214
+ ### Meta utilities
215
+
216
+ ```typescript
217
+ import { readMeta, writeMeta, isPressed, pressedKeys, synthesizeKeyEvents } from 'memoir-node'
218
+
219
+ // Read
220
+ const meta = readMeta('session.meta')
221
+
222
+ // Check keys
223
+ isPressed(meta.rows[0], 'W', meta.keys) // boolean
224
+ pressedKeys(meta.rows[0], meta.keys) // string[]
225
+
226
+ // Generate key events for replay
227
+ const events = synthesizeKeyEvents(meta.rows, meta.keys)
228
+ // [{ frame: 0n, type: 'keyDown', key: 'W' }, ...]
229
+ ```
230
+
231
+ ## Architecture
232
+
233
+ ```
234
+ WGC FrameArrived (thread pool)
235
+
236
+ ├─ FPS limiter → drop if too soon
237
+ ├─ Queue check → drop if full (drop-new policy)
238
+
239
+ ├─ Accept: assign frame_id, snapshot keyboard
240
+ ├─ GPU→CPU: CopyResource → staging → Map → memcpy → Buffer (zero-copy)
241
+ ├─ Recording: swscale (BGRA→YUV444) → HEVC encoder → MP4
242
+ └─ Enqueue → Node.js consumer
243
+ ```
244
+
245
+ `getNextFrame()` is a synchronous blocking call that waits on a condition variable. No GIL concerns (unlike Python) — the calling thread simply sleeps until a frame arrives. Use in a Worker thread to avoid blocking the main V8 thread.
246
+
247
+ ## License
248
+
249
+ MIT. Links against FFmpeg (LGPL 2.1+).
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,42 +1,40 @@
1
- {
2
- "name": "memoir-node",
3
- "version": "0.1.7",
4
- "description": "Windows-native screen capture with Node.js bindings",
5
- "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/lunavod/memoir-capture.git"
9
- },
10
- "os": ["win32"],
11
- "cpu": ["x64"],
12
- "engines": {
13
- "node": ">=18"
14
- },
15
- "keywords": ["screen-capture", "windows", "native", "napi", "wgc", "ffmpeg", "recording"],
16
- "main": "dist/index.js",
17
- "types": "dist/index.d.ts",
18
- "scripts": {
19
- "build:native": "cmake-js build --CDMEMOIR_BUILD_NODE=ON --CDMEMOIR_BUILD_PYTHON=OFF --CDCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake --CDVCPKG_OVERLAY_TRIPLETS=cmake/triplets --CDVCPKG_TARGET_TRIPLET=x64-windows-release",
20
- "build:ts": "tsc",
21
- "build": "npm run build:native && tsc",
22
- "rebuild": "cmake-js rebuild --CDMEMOIR_BUILD_NODE=ON --CDMEMOIR_BUILD_PYTHON=OFF --CDCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake --CDVCPKG_OVERLAY_TRIPLETS=cmake/triplets --CDVCPKG_TARGET_TRIPLET=x64-windows-release",
23
- "test": "vitest run",
24
- "prepublishOnly": "node -e \"const fs=require('fs'); fs.copyFileSync('README.md','README-python.md'); fs.copyFileSync('README-node.md','README.md')\"",
25
- "postpublish": "node -e \"const fs=require('fs'); fs.copyFileSync('README-python.md','README.md'); fs.unlinkSync('README-python.md')\""
26
- },
27
- "dependencies": {},
28
- "devDependencies": {
29
- "@types/node": "^22.0.0",
30
- "cmake-js": "^7.0.0",
31
- "node-addon-api": "^7.0.0",
32
- "typescript": "^5.5.0",
33
- "vitest": "^3.0.0"
34
- },
35
- "files": [
36
- "dist/*.js",
37
- "dist/*.d.ts",
38
- "build/Release/memoir_node.node",
39
- "build/Release/*.dll",
40
- "LICENSE"
41
- ]
42
- }
1
+ {
2
+ "name": "memoir-node",
3
+ "version": "0.2.0",
4
+ "description": "Windows-native screen capture with Node.js bindings",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/lunavod/memoir-capture.git"
9
+ },
10
+ "os": ["win32"],
11
+ "cpu": ["x64"],
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "keywords": ["screen-capture", "windows", "native", "napi", "wgc", "ffmpeg", "recording"],
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "scripts": {
19
+ "build:native": "cmake-js build --CDMEMOIR_BUILD_NODE=ON --CDMEMOIR_BUILD_PYTHON=OFF --CDCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake --CDVCPKG_OVERLAY_TRIPLETS=cmake/triplets --CDVCPKG_TARGET_TRIPLET=x64-windows-release",
20
+ "build:ts": "tsc",
21
+ "build": "npm run build:native && tsc",
22
+ "rebuild": "cmake-js rebuild --CDMEMOIR_BUILD_NODE=ON --CDMEMOIR_BUILD_PYTHON=OFF --CDCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake --CDVCPKG_OVERLAY_TRIPLETS=cmake/triplets --CDVCPKG_TARGET_TRIPLET=x64-windows-release",
23
+ "test": "vitest run"
24
+ },
25
+ "dependencies": {},
26
+ "devDependencies": {
27
+ "@types/node": "^22.0.0",
28
+ "cmake-js": "^7.0.0",
29
+ "node-addon-api": "^7.0.0",
30
+ "typescript": "^5.5.0",
31
+ "vitest": "^3.0.0"
32
+ },
33
+ "files": [
34
+ "dist/*.js",
35
+ "dist/*.d.ts",
36
+ "build/Release/memoir_node.node",
37
+ "build/Release/*.dll",
38
+ "LICENSE"
39
+ ]
40
+ }