noobs 0.0.29 → 0.0.31
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/dist/noobs.node +0 -0
- package/index.d.ts +11 -9
- package/package.json +1 -1
- package/src/main.cpp +30 -9
- package/src/obs_interface.cpp +106 -39
- package/src/obs_interface.h +7 -3
package/dist/noobs.node
CHANGED
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ type Signal = { // TODO export type?
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
interface Noobs {
|
|
7
|
-
|
|
7
|
+
Init(
|
|
8
8
|
pluginPath: string,
|
|
9
9
|
logPath: string,
|
|
10
10
|
dataPath: string,
|
|
@@ -12,15 +12,17 @@ interface Noobs {
|
|
|
12
12
|
cb: (signal: Signal) => void
|
|
13
13
|
): void;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
Shutdown(): void;
|
|
16
|
+
StartBuffer(): void;
|
|
17
|
+
StartRecording(offset: number): void;
|
|
18
|
+
StopRecording(): void;
|
|
19
|
+
GetLastRecording(): string;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
UpdateSource(x: number, y: number, scale: number): void;
|
|
22
|
+
|
|
23
|
+
InitPreview(hwnd: Buffer): void;
|
|
24
|
+
ShowPreview(x: number, y: number, width: number, height: number): void;
|
|
25
|
+
HidePreview(): void;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
declare const noobs: Noobs;
|
package/package.json
CHANGED
package/src/main.cpp
CHANGED
|
@@ -157,18 +157,39 @@ Napi::Value ObsHidePreview(const Napi::CallbackInfo& info) {
|
|
|
157
157
|
return info.Env().Undefined();
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
Napi::Value ObsUpdateSourcePos(const Napi::CallbackInfo& info) {
|
|
161
|
+
if (!obs) {
|
|
162
|
+
blog(LOG_ERROR, "ObsUpdateSource called but obs is not initialized");
|
|
163
|
+
throw std::runtime_error("Obs not initialized");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
bool valid = info.Length() == 3 &&
|
|
167
|
+
info[0].IsNumber() && // X position (px)
|
|
168
|
+
info[1].IsNumber() && // Y position (px)
|
|
169
|
+
info[2].IsNumber(); // Scale (multiplier)
|
|
170
|
+
|
|
171
|
+
int x = info[0].As<Napi::Number>().Int32Value();
|
|
172
|
+
int y = info[1].As<Napi::Number>().Int32Value();
|
|
173
|
+
float scale = info[2].As<Napi::Number>().FloatValue();
|
|
174
|
+
|
|
175
|
+
obs->updateSourcePos(x, y, scale);
|
|
176
|
+
return info.Env().Undefined();
|
|
177
|
+
}
|
|
178
|
+
|
|
160
179
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
161
|
-
exports.Set("
|
|
162
|
-
exports.Set("
|
|
180
|
+
exports.Set("Init", Napi::Function::New(env, ObsInit));
|
|
181
|
+
exports.Set("Shutdown", Napi::Function::New(env, ObsShutdown));
|
|
182
|
+
|
|
183
|
+
exports.Set("StartBuffer", Napi::Function::New(env, ObsStartBuffer));
|
|
184
|
+
exports.Set("StartRecording", Napi::Function::New(env, ObsStartRecording));
|
|
185
|
+
exports.Set("StopRecording", Napi::Function::New(env, ObsStopRecording));
|
|
186
|
+
exports.Set("GetLastRecording", Napi::Function::New(env, ObsGetLastRecording));
|
|
163
187
|
|
|
164
|
-
exports.Set("
|
|
165
|
-
exports.Set("ObsStartRecording", Napi::Function::New(env, ObsStartRecording));
|
|
166
|
-
exports.Set("ObsStopRecording", Napi::Function::New(env, ObsStopRecording));
|
|
167
|
-
exports.Set("ObsGetLastRecording", Napi::Function::New(env, ObsGetLastRecording));
|
|
188
|
+
exports.Set("UpdateSourcePos", Napi::Function::New(env, ObsUpdateSourcePos));
|
|
168
189
|
|
|
169
|
-
exports.Set("
|
|
170
|
-
exports.Set("
|
|
171
|
-
exports.Set("
|
|
190
|
+
exports.Set("InitPreview", Napi::Function::New(env, ObsInitPreview));
|
|
191
|
+
exports.Set("ShowPreview", Napi::Function::New(env, ObsShowPreview));
|
|
192
|
+
exports.Set("HidePreview", Napi::Function::New(env, ObsHidePreview));
|
|
172
193
|
return exports;
|
|
173
194
|
}
|
|
174
195
|
|
package/src/obs_interface.cpp
CHANGED
|
@@ -178,15 +178,26 @@ void ObsInterface::init_obs(const std::string& pluginPath, const std::string& da
|
|
|
178
178
|
blog(LOG_INFO, "Exit init_obs");
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
void ObsInterface::configure_output(const std::string& recordingPath) {
|
|
182
182
|
blog(LOG_INFO, "Create output");
|
|
183
|
-
|
|
183
|
+
|
|
184
|
+
if (output && obs_output_active(output)) {
|
|
185
|
+
blog(LOG_ERROR, "Tried to recreate active output");
|
|
186
|
+
throw std::runtime_error("Failed to create output!");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (output) {
|
|
190
|
+
blog(LOG_DEBUG, "Releasing output");
|
|
191
|
+
obs_output_release(output);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
output = obs_output_create("replay_buffer", "recording_output", NULL, NULL);
|
|
184
195
|
|
|
185
196
|
if (!output) {
|
|
186
197
|
blog(LOG_ERROR, "Failed to create output!");
|
|
187
198
|
throw std::runtime_error("Failed to create output!");
|
|
188
199
|
}
|
|
189
|
-
|
|
200
|
+
|
|
190
201
|
blog(LOG_INFO, "Set output settings");
|
|
191
202
|
obs_data_t *settings = obs_data_create();
|
|
192
203
|
obs_data_set_int(settings, "max_time_sec", 60);
|
|
@@ -197,7 +208,24 @@ obs_output_t* ObsInterface::create_output(const std::string& recordingPath) {
|
|
|
197
208
|
obs_output_update(output, settings);
|
|
198
209
|
obs_data_release(settings);
|
|
199
210
|
|
|
200
|
-
|
|
211
|
+
// Add the signal handler callback.
|
|
212
|
+
create_signal_handlers(output);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void ObsInterface::configure_video_encoder() {
|
|
216
|
+
blog(LOG_INFO, "Create video encoder");
|
|
217
|
+
|
|
218
|
+
if (!output) {
|
|
219
|
+
blog(LOG_ERROR, "No output on configure_video_encoder");
|
|
220
|
+
throw std::runtime_error("Failed to create video encoder!");
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (video_encoder) {
|
|
224
|
+
blog(LOG_DEBUG, "Releasing video encoder");
|
|
225
|
+
obs_encoder_release(video_encoder);
|
|
226
|
+
video_encoder = nullptr;
|
|
227
|
+
}
|
|
228
|
+
|
|
201
229
|
video_encoder = obs_video_encoder_create("obs_x264", "simple_h264_stream", NULL, NULL);
|
|
202
230
|
|
|
203
231
|
if (!video_encoder) {
|
|
@@ -205,18 +233,31 @@ obs_output_t* ObsInterface::create_output(const std::string& recordingPath) {
|
|
|
205
233
|
throw std::runtime_error("Failed to create video encoder!");
|
|
206
234
|
}
|
|
207
235
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
236
|
+
blog(LOG_INFO, "Set video encoder settings");
|
|
237
|
+
obs_data_t* venc_settings = obs_data_create();
|
|
238
|
+
obs_data_set_string(venc_settings, "preset", "speed"); // Faster preset
|
|
239
|
+
obs_data_set_string(venc_settings, "rate_control", "CRF");
|
|
240
|
+
obs_data_set_int(venc_settings, "crf", 30);
|
|
241
|
+
obs_data_set_string(venc_settings, "profile", "main");
|
|
242
|
+
obs_data_set_int(venc_settings, "keyint_sec", 1); // Set keyframe interval to 1 second
|
|
243
|
+
obs_encoder_update(video_encoder, venc_settings);
|
|
244
|
+
obs_data_release(venc_settings);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
void ObsInterface::configure_audio_encoder() {
|
|
248
|
+
blog(LOG_INFO, "Create audio encoder");
|
|
249
|
+
|
|
250
|
+
if (!output) {
|
|
251
|
+
blog(LOG_ERROR, "No output on configure_audio_encoder");
|
|
252
|
+
throw std::runtime_error("Failed to create audio encoder!");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (audio_encoder) {
|
|
256
|
+
blog(LOG_DEBUG, "Releasing audio encoder");
|
|
257
|
+
obs_encoder_release(audio_encoder);
|
|
258
|
+
audio_encoder = nullptr;
|
|
259
|
+
}
|
|
218
260
|
|
|
219
|
-
blog(LOG_INFO, "Create aenc");
|
|
220
261
|
audio_encoder = obs_audio_encoder_create("ffmpeg_aac", "simple_aac", NULL, 0, NULL);
|
|
221
262
|
|
|
222
263
|
if (!audio_encoder) {
|
|
@@ -235,40 +276,50 @@ obs_output_t* ObsInterface::create_output(const std::string& recordingPath) {
|
|
|
235
276
|
|
|
236
277
|
obs_encoder_set_video(video_encoder, obs_get_video());
|
|
237
278
|
obs_encoder_set_audio(audio_encoder, obs_get_audio());
|
|
238
|
-
|
|
239
|
-
return output;
|
|
240
279
|
}
|
|
241
280
|
|
|
242
|
-
|
|
243
|
-
blog(LOG_INFO, "
|
|
244
|
-
|
|
281
|
+
void ObsInterface::configure_scene() {
|
|
282
|
+
blog(LOG_INFO, "Configure scene");
|
|
283
|
+
|
|
284
|
+
if (scene) {
|
|
285
|
+
blog(LOG_DEBUG, "Releasing scene");
|
|
286
|
+
obs_scene_release(scene);
|
|
287
|
+
scene = nullptr;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
scene = obs_scene_create("WCR Scene");
|
|
245
291
|
|
|
246
|
-
if (!scene)
|
|
292
|
+
if (!scene) {
|
|
293
|
+
blog(LOG_ERROR, "Failed to create scene!");
|
|
247
294
|
throw std::runtime_error("Failed to create scene!");
|
|
295
|
+
}
|
|
248
296
|
|
|
249
297
|
obs_source_t *scene_source = obs_scene_get_source(scene);
|
|
250
298
|
|
|
251
|
-
if (!scene_source)
|
|
252
|
-
|
|
299
|
+
if (!scene_source) {
|
|
300
|
+
blog(LOG_ERROR, "Failed to get scene source!");
|
|
301
|
+
throw std::runtime_error("Failed to get scene source!");
|
|
302
|
+
}
|
|
253
303
|
|
|
254
|
-
obs_set_output_source(0, scene_source);
|
|
255
|
-
|
|
304
|
+
obs_set_output_source(0, scene_source); // 0 = video track
|
|
305
|
+
obs_scene_add(scene, video_source);
|
|
256
306
|
}
|
|
257
307
|
|
|
258
|
-
|
|
259
|
-
blog(LOG_INFO, "Create
|
|
308
|
+
void ObsInterface::configure_video_source() {
|
|
309
|
+
blog(LOG_INFO, "Create monitor capture source");
|
|
310
|
+
|
|
260
311
|
// Create settings for monitor capture
|
|
261
312
|
obs_data_t *monitor_settings = obs_data_create();
|
|
262
313
|
obs_data_set_int(monitor_settings, "monitor", 0); // Monitor 0
|
|
263
314
|
obs_data_set_bool(monitor_settings, "capture_cursor", true);
|
|
264
315
|
|
|
265
|
-
|
|
316
|
+
video_source = obs_source_create("monitor_capture", "video_source", monitor_settings, NULL);
|
|
266
317
|
obs_data_release(monitor_settings);
|
|
267
318
|
|
|
268
|
-
if (!
|
|
319
|
+
if (!video_source) {
|
|
320
|
+
blog(LOG_ERROR, "Failed to create video source!");
|
|
269
321
|
throw std::runtime_error("Failed to create video source!");
|
|
270
|
-
|
|
271
|
-
return source;
|
|
322
|
+
}
|
|
272
323
|
}
|
|
273
324
|
|
|
274
325
|
void call_jscb(Napi::Env env, Napi::Function cb, SignalData* sd) {
|
|
@@ -428,15 +479,15 @@ ObsInterface::ObsInterface(
|
|
|
428
479
|
// Initialize OBS and load required modules.
|
|
429
480
|
init_obs(pluginPath, dataPath);
|
|
430
481
|
|
|
431
|
-
//
|
|
432
|
-
output = create_output(recordingPath);
|
|
433
|
-
scene = create_scene();
|
|
434
|
-
video_source = create_video_source();
|
|
435
|
-
obs_scene_add(scene, video_source);
|
|
436
|
-
|
|
437
|
-
// Add the signal handler callback.
|
|
482
|
+
// Setup callback function.
|
|
438
483
|
jscb = cb;
|
|
439
|
-
|
|
484
|
+
|
|
485
|
+
// Create the resources we rely on.
|
|
486
|
+
configure_output(recordingPath);
|
|
487
|
+
configure_video_encoder();
|
|
488
|
+
configure_audio_encoder();
|
|
489
|
+
configure_video_source();
|
|
490
|
+
configure_scene();
|
|
440
491
|
}
|
|
441
492
|
|
|
442
493
|
ObsInterface::~ObsInterface() {
|
|
@@ -560,4 +611,20 @@ std::string ObsInterface::getLastRecording() {
|
|
|
560
611
|
|
|
561
612
|
blog(LOG_INFO, "return path: %s", path.c_str());
|
|
562
613
|
return path;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
void ObsInterface::updateSourcePos(int x, int y, float scale) {
|
|
617
|
+
blog(LOG_INFO, "ObsInterface::moveSource called at (%d, %d)", x, y);
|
|
618
|
+
obs_sceneitem_t *item = obs_scene_find_source(scene, "video_source");
|
|
619
|
+
|
|
620
|
+
if (!item) {
|
|
621
|
+
blog(LOG_ERROR, "Did not find scene item for video source");
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
struct vec2 pos = { (float)x, (float)y };
|
|
626
|
+
obs_sceneitem_set_pos(item, &pos);
|
|
627
|
+
|
|
628
|
+
struct vec2 scalep = { scale, scale };
|
|
629
|
+
obs_sceneitem_set_scale(item, &scalep);
|
|
563
630
|
}
|
package/src/obs_interface.h
CHANGED
|
@@ -24,6 +24,8 @@ class ObsInterface {
|
|
|
24
24
|
void stopRecording();
|
|
25
25
|
std::string getLastRecording();
|
|
26
26
|
|
|
27
|
+
void updateSourcePos(int x, int y, float scale);
|
|
28
|
+
|
|
27
29
|
void initPreview(HWND parent); // Must call this before showPreview to setup resources.
|
|
28
30
|
void showPreview(int x, int y, int width, int height); // Also used for moving and resizing.
|
|
29
31
|
void hidePreview();
|
|
@@ -65,7 +67,9 @@ class ObsInterface {
|
|
|
65
67
|
void list_input_types();
|
|
66
68
|
void list_output_types();
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
void configure_output(const std::string& recordingPath);
|
|
71
|
+
void configure_video_encoder();
|
|
72
|
+
void configure_audio_encoder();
|
|
73
|
+
void configure_scene();
|
|
74
|
+
void configure_video_source();
|
|
71
75
|
};
|